從 1 開始的多頁式網站

更新於 2024/07/03閱讀時間約 14 分鐘
多頁式網站

多頁式網站


從上次作完喵喵健身教練網頁後,覺得自己以前作的個人簡歷網站實在是太醜了,而且當初為了搶快,直接套用 Bootstrap 版型,根本不用寫 JavaScript(燦笑)

所以這次決定把網站重寫,就算是從 1 開始吧,1-10 分作到 8 分就好,不然完美主義真的會搞死自己,那道光很快就來了(?)

HTML 架構

多頁式網站多半是 header 跟 footer 會是一樣的,這樣使用者在瀏覽時,不會一下要去左側找導覽列、一下又去上方點選導覽列,所以只要替換中間的 main 內容就好。

<header>

<main>

<footer>

首頁的內容

接著就是 main 的內容了,首頁我想讓使用者直接看到我的作品集,並且用卡片形式:包含照片、標題、使用的工具、描述、 gitHub repo 的連結,而這些資料會寫成 JSON 檔案,最後用 JavaScript 把資料轉換成 DOM 節點,讓瀏覽器渲染。

<main>
<div class="card">
</main>

關於我的內容

關於我是最簡單的,只要放一張照片、簡歷、社群媒體的連結即可。

<main>
<section class="profile-section">
<div class="profile-avatar">
<div class="profile-content">
</section>

<section class="contact-section">
<a class="instagram">
</section>
</main>

經歷與技能的內容

經歷就用條列式的方式,技能除了條列出來外,還要有百分比表示 level,看起來比較能知道技能的程度。

<main>
<section class="experience">
<h2 class="title">
<ul class="job">
</section>

<section class="skills">
<h2 class="title">
<ul class="skill-list">
</section>

<section class="other-activities">
<h2 class="title">
<ul class="activities-list">
</section>
</main>

我真棒(雙手交叉拍拍自己肩膀)。



CSS 樣式

導覽列推出式動畫

導覽列往下推擠

導覽列往下推擠

導覽列覆蓋在元素上方

導覽列覆蓋在元素上方


上一次是作淡出淡入動畫,這樣導覽列可以想像成 photoshop 的圖層,順序會蓋在頁面上面,當淡出時,不會推擠到下方的圖層。(左圖)

這次想改成在同一個圖層上,導覽列下拉時,會把其他元素往下推擠。(上圖)

這裡依舊使用 animation 與 keyframes 來做出效果,關鍵影格在初始設定高度 height 及透明度 opacity 為 0,動畫結束時將透明度 opacity 為 1,將高度設定為導覽列的高度..要怎麼知道?用 google DevTools 去看就可以了,這部分也是未來可以優化的地方

反之,如果是要將導覽列收起,就設定相反的數值即可。

@keyframes pushin {
0% {
height: 0;
opacity: 0;
}
100% {
height: 170px;
opacity: 1;
}
}

再來將 animation 設定效果呈現的秒數。

.push-in {
animation: pushin 0.4s;
}

最後去 JavaScript 掛載事件監聽器,用來觸發設定好的效果。

const toggler = document.querySelector('.toggler')
const collapse = document.querySelector('#navbarCollapse')
let isShow = false // 先設定導覽列是隱藏的

toggler.addEventListener('click', function (e) {
const btn = e.target.closest('.toggler-icon')
if (!btn) return
toggleNavigation()
})

const toggleNavigation = function () {
if (isShow) {
// 當導覽列正在顯示時 加入 push-out 並移除 push-in 動畫
collapse.classList.add('push-out')
collapse.classList.remove('push-in')
collapse.style.height = '0' // 高度設定回 0
} else {
// 當導覽列是隱藏時 加入 push-in 並移除 push-out 動畫
collapse.classList.add('push-in')
collapse.classList.remove('push-out')
collapse.style.height = '100%' // 高度設定 100%
}
isShow = !isShow // 動作結束時 將 isShow 狀態反轉
}

技能百分比圖示

百分比樣式

百分比樣式

HTML 中將條列式的技能列出,除了技能名稱外,另外包一個 span 標籤在裡面,用來設定百分比樣式。

<li class="skill-item">
<span>技能名稱</span>

<span class="level-percentage"> <!-- 設定百分比樣式 -->
<span class="percentage""></span>
</span>
</li>

css 部分,先將 skill-item 設定為 grid,讓兩個子元素:技能名稱、百分比樣式可以排排站,為什麼不用 flex 的原因是,在排列的時候兩個子元素會一直緊緊相依,視覺上就沒有對齊的感覺。(下圖)

flex 與 grid 差異

flex 與 grid 差異


.skill-item {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: 1fr;
margin: 0.5rem;
align-items: center;
}

.skill-item span {
flex-basis: 20%;
}


flex 就像是把兩個東西都放在同一層格子中,如果要跟上一層格子對齊,需要耐心調整,並且只要寬度不同時,就有可能無法對齊。

grid 則是把兩個東西各自放在一層兩格的櫃子,上下要對齊時,只要把東西同時置中或靠左靠右,而不用去考慮到另一個東西的位置,調整就不會太吃力。


再來設定百分比,在 HTML 中,我把百分比寫成一個父元素 level-percentage 跟一個子元素 percentage,父元素用來寫外框,也就是百分比的黑色部分,子元素則是用來寫技能的百分比%樣式。

.level-percentage {
position: relative; /* 父元素的位置設定 relative 讓子元素可以依賴父元素的位置*/
z-index: 10;
display: inline-block;
width: 100%; /* 寬度就是那格 grid 格子的寬度 */
height: 0.8rem;
border: 2px solid #434343;
border-radius: 10px;
background-color: #434343;
}

.percentage {
position: absolute; /* 讓子元素可以依賴父元素的位置去做調整 */
z-index: 20; /* 子元素的 z 軸位置較高 才能蓋在父元素上方 */
left: 0;
top: 50%; /* 垂直置中 */
transform: translateY(-50%); /* 垂直置中 */
/* width: ; 寬度之後用 JavaScript 來設定*/
height: 0.6rem;
border-radius: inherit;
background-color: #eeeeee;
}

這裡就完成了,接著就要用 JavaScript 來抓資料。



JavaScript 抓 JSON 資料

抓資料渲染畫面

抓資料渲染畫面

不想把 HTML 寫的太長,所以想把資料寫成 JSON 檔案,未來資料有更動時,就不用逐一調整,還有可能調錯的風險存在。

這次先把作品集跟技能的資料寫成 JSON 檔案:

{
"portfolios": [
{
"title": "作品標題",
"skills": ["使用技能1", "技能2", "技能3"],
"content_zh": "中文介紹",
"content_en": "英文介紹",
"live_url": "發佈的網址",
"image_url": "圖片路徑",
"repo_url": "git 倉庫網址",
"copyright": "版權聲明"
}
]
}

再來就是抓資料,因為 JSON 檔中有幾個 key name 包含下底線,所以先把它們轉成駝峰式寫法,例如:repo_url 改成 repoUrl,就不會在使用資料時,還要回去看名稱是哪種寫法。

const renameKeys = function (obj) {
const keyValues = Object.keys(obj).map((key) => {
const index = key.indexOf('_') // 取得下底線在名稱中的位置
const newKey =index > 1 // 如果下底線不在第一個字母時
? `${key.slice(0, index)}${key
.slice(index + 1)[0]
.toUpperCase()}${key.slice(index + 2)}` // 移除下底線後將後方的字母改成大寫
: key // 反之 下底線在第一個字母時就不用轉換
return { [newKey]: obj[key] }
})
return Object.assign({}, ...keyValues) // 返回新的物件
}

接著使用 fetch 取得資料:

const displaySection = async function (url, callback) {
try {
// ​依 url 取得資料 如果沒有取得資料 就丟出錯誤
const res = await fetch(url)
if (!res.ok) throw new Error('Something went wrong!')

// 將資料解析 如果沒有資料 就丟出錯誤
const data = await res.json()
if (!data) throw new Error('Data not found')

// 將解析的資料傳入函式
callback(data)
} catch (err) {
console.error(err) // 如果有錯誤 就顯示在主控台
}
}

把 callback function 另外寫,將資料改寫成 HTML 模板後,置入 DOM tree:

const portfolioMarkup = function (data) {
const { portfolios } = data // 解構 portfolios
portfolios.forEach(function (portfolio) {
const port = renameKeys(portfolio) // 轉換 key 的名稱

// 寫成 HTML 模板​
const html = `
<div class="card">
<div class="card-img">
<img src="${port.imageUrl}" class="block" alt="${port.title}">
</div>

<div class="card-body">
<p class="card-title">${port.title}</p>
<p class="card-description">${port.contentZh}</p>
</div>

<div class="card-footer">
<p class="card-copyright">${port.copyright}</p>
</div>
</div>
`
// 置入 DOM
portfolioContainer?.insertAdjacentHTML('beforeend', html)
})
}

再來就是調用 displaySection 函式就完成了。



網頁在此:我的個人簡歷。希望大家給我愛心(???)

avatar-img
5會員
14內容數
本來是理科生,在被物理放棄之後成為了文科生,有時理性思考,偶爾卻會脫口出感性的字句;喜歡打字的聲音,以生活為靈感寫下過去、現在與未來。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
碎碎念 的其他內容
一切都從思考作品集要怎麼準備開始,所謂的 one 是起頭難(?),在動手寫 code 之前,總覺得自己做不到,一直在自己煩惱,直到前輩們說:開始做看看吧,一頁式網站也好,不開始做永遠不知道自己哪些知識需要補強。 於是決定先幫我的繆思女神做一個網站,讓她可以介紹自己的工作,再放社群連結
前言: 雖然前面有些定義還沒有完整的解釋,但還是後面再說吧, 誰想一直看理論啊(摔本子)
前言: 前一篇講了 JS 的定義,這裡來談談能用它來做什麼, 希望能限制在 500 字以內(這是我看文章的極限,超過字數就會開始分心(?))
前言: 一直想要把自己的學習筆記整理整理,至少在寫下筆記的時候,也能釐清觀念。 結果拖延到現在,終於要提筆了,不知道能堅持多久(???)。
使用 React 做出一個便條紙的頁面,可以紀錄自己的想法後丟上去。並且讓使用者即使重新整理頁面,也不會遺失資料。
C2 開始終於使用到 visual studio code, 這個階段學到 JavaScript 核心概念、DOM 操作、API 串接、MVC 架構, 每天都在 coding,每週都在追進度, 用壓縮到極致的時間寫完作業, 但跟著課程內容寫程式碼,真的有學到嗎? 有,吧。 畢竟在寫最後的電影清單
一切都從思考作品集要怎麼準備開始,所謂的 one 是起頭難(?),在動手寫 code 之前,總覺得自己做不到,一直在自己煩惱,直到前輩們說:開始做看看吧,一頁式網站也好,不開始做永遠不知道自己哪些知識需要補強。 於是決定先幫我的繆思女神做一個網站,讓她可以介紹自己的工作,再放社群連結
前言: 雖然前面有些定義還沒有完整的解釋,但還是後面再說吧, 誰想一直看理論啊(摔本子)
前言: 前一篇講了 JS 的定義,這裡來談談能用它來做什麼, 希望能限制在 500 字以內(這是我看文章的極限,超過字數就會開始分心(?))
前言: 一直想要把自己的學習筆記整理整理,至少在寫下筆記的時候,也能釐清觀念。 結果拖延到現在,終於要提筆了,不知道能堅持多久(???)。
使用 React 做出一個便條紙的頁面,可以紀錄自己的想法後丟上去。並且讓使用者即使重新整理頁面,也不會遺失資料。
C2 開始終於使用到 visual studio code, 這個階段學到 JavaScript 核心概念、DOM 操作、API 串接、MVC 架構, 每天都在 coding,每週都在追進度, 用壓縮到極致的時間寫完作業, 但跟著課程內容寫程式碼,真的有學到嗎? 有,吧。 畢竟在寫最後的電影清單
你可能也想看
Google News 追蹤
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
經濟學開宗明義第一句話會告訴你:「資源有限,慾望無窮。」在大家思索手上所得如何分配時,卻很少想到,時間也是如此。本書副標:「每天7分鐘的微行動,在追求中釐清優先順序,每個選項都能為人生加分」揭露你能為自己人生做的那1%的選擇,就是每天撥出7分鐘,思考當日/隔日要完成的5件最重要的事情是什麼。
Thumbnail
新系列《京都散步》的第一篇,七条東山的散步路線以及店家介紹。
★如果生命對你有求必應,你對人生有何企求?其實人生早就準備好我們所需,只需要問問自己「到底要追求什麼?」
Thumbnail
我們常常陷入一種潛意識自動導航,放任慣性去過日子,因此常分散注意力,作者艾莉森.路易斯在《從1%的選擇開始,去做你真正渴望的事》這本書告訴我們如何過濾訊息、降低噪音來如何精準『分配注意力』。 (讀)思考—(寫)書寫—(做)行動的3個步驟, 打破負循理脫離窮忙迴圈! -----
Thumbnail
書中提到的[想、寫、做]是我最印象深刻的方法,透過大腦思考,動手把想法寫下來,在去完成目標這樣可以做到你真正可望的選擇。在大腦的物理結構,會隨著每個想法而改變。透過重複這些想法,你會看到真正的變化。因為神經可以塑性之故,思考變得非常重要,能讓你變成理想中的自己。 ˇ
Thumbnail
「最多被浪費的時間,就是還沒開始行動的時間。」 ——Dawson Trotman. 一直到前陣子我才發現,我生活中有許多的低潮,都是源自於忙碌的生活讓我喘不過氣。但其中最讓我沮喪的,不是忙碌本身,而是瞎忙。 時常一整天像個轉不停的陀螺,一點一滴榨乾自己的身心,回過神來卻發現自己似乎一事無成,感受不
Thumbnail
40歲是人生的黃金時期,然而在忙進忙出的生活中,該如何延續過往的順遂、推開曾經的挫敗?又該如何擁抱自己的美好人生?
以下人名內容與團體純屬虛構,若與現實有所雷同皆屬巧合。     
Thumbnail
從〝認同自我〞出發,要去接納別人之前,我們必須先懂得如何好好接納自己,了解各種需求,克服各種情緒,這個我們談判之前的第一課,也是最關鍵但卻最容易被遺忘的一件事。 了解自我感受、尋找替代方案,在試圖影響別人之前,要先影響自己。想要與別人合作偷快,都得從學習與自己相處,與自己好好合作開始。
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
經濟學開宗明義第一句話會告訴你:「資源有限,慾望無窮。」在大家思索手上所得如何分配時,卻很少想到,時間也是如此。本書副標:「每天7分鐘的微行動,在追求中釐清優先順序,每個選項都能為人生加分」揭露你能為自己人生做的那1%的選擇,就是每天撥出7分鐘,思考當日/隔日要完成的5件最重要的事情是什麼。
Thumbnail
新系列《京都散步》的第一篇,七条東山的散步路線以及店家介紹。
★如果生命對你有求必應,你對人生有何企求?其實人生早就準備好我們所需,只需要問問自己「到底要追求什麼?」
Thumbnail
我們常常陷入一種潛意識自動導航,放任慣性去過日子,因此常分散注意力,作者艾莉森.路易斯在《從1%的選擇開始,去做你真正渴望的事》這本書告訴我們如何過濾訊息、降低噪音來如何精準『分配注意力』。 (讀)思考—(寫)書寫—(做)行動的3個步驟, 打破負循理脫離窮忙迴圈! -----
Thumbnail
書中提到的[想、寫、做]是我最印象深刻的方法,透過大腦思考,動手把想法寫下來,在去完成目標這樣可以做到你真正可望的選擇。在大腦的物理結構,會隨著每個想法而改變。透過重複這些想法,你會看到真正的變化。因為神經可以塑性之故,思考變得非常重要,能讓你變成理想中的自己。 ˇ
Thumbnail
「最多被浪費的時間,就是還沒開始行動的時間。」 ——Dawson Trotman. 一直到前陣子我才發現,我生活中有許多的低潮,都是源自於忙碌的生活讓我喘不過氣。但其中最讓我沮喪的,不是忙碌本身,而是瞎忙。 時常一整天像個轉不停的陀螺,一點一滴榨乾自己的身心,回過神來卻發現自己似乎一事無成,感受不
Thumbnail
40歲是人生的黃金時期,然而在忙進忙出的生活中,該如何延續過往的順遂、推開曾經的挫敗?又該如何擁抱自己的美好人生?
以下人名內容與團體純屬虛構,若與現實有所雷同皆屬巧合。     
Thumbnail
從〝認同自我〞出發,要去接納別人之前,我們必須先懂得如何好好接納自己,了解各種需求,克服各種情緒,這個我們談判之前的第一課,也是最關鍵但卻最容易被遺忘的一件事。 了解自我感受、尋找替代方案,在試圖影響別人之前,要先影響自己。想要與別人合作偷快,都得從學習與自己相處,與自己好好合作開始。