iT邦幫忙

2021 iThome 鐵人賽

DAY 16
0
Modern Web

Follow me! 來一場前端技能樹之旅系列 第 16

[Day 16 - 小試身手] 用HTML、CSS、JS打造個人網站 (3)

在上一篇:用HTML、CSS、JS打造個人網站 (2),完成了網頁的所有內容,接下來的工作就是讓網頁能夠適應各種螢幕大小,讓使用者在每個裝置都能有最基本的使用體驗。

前面的文章跨平台生存之道 — RWD響應式網頁設計,有提到可以設置斷點(Break point),讓網頁在縮放的時候可以根據斷點去做響應的變化。在這次練習的設計稿,定義出了網頁在三種不同的尺寸下的排版,你可以在 assets/design 資料夾裡面找到,分別是:desktop.png、tablet.png、mobile.png

設置的斷點會是 1024px、768px,螢幕寬度來到 1024px 以上就會顯示 Desktop 版本、1024px~768px 顯示 Tablet 版本、768px 以下顯示 Mobile 版本,接下來就會帶大家分別調整三個區段的排版。

螢幕寬度>=1024px

雖然我們說版面要適應螢幕的大小來縮放,但當你在很大的螢幕上瀏覽網頁,需要從螢幕最左邊看到最右邊其實是很累人的一件事。所以在大尺寸下,通常不會讓網頁的內容滿版顯示,會去設定內容文字最大的縮放寬度 max-width ,只有讓背景適應網頁做滿版顯示。

...
.wrapper-content {
  ...
  width: 100%;
  max-width: 1024px;
  margin: 0 auto;
}
...

header,.section-primary,footer {
  background-color: #fff5da;
}

這時候開啟瀏覽器的開發者工具,調整尺寸到 1024px 以上,就可以看到設置的結果囉。

Before

After


螢幕寬度1023px~768px

我們會將 Desktop 設為預設的樣式,接著是 Tablet 的版本。使用 Media Query 偵測螢幕寬度,在 1024px 以下、768px (含)以上時,就會採用裡面設定的樣式。

Section Primary

在 Pimary 區塊,除了調整左右兩欄的寬度佔比,還要讓右側的圖片貼緊區塊的底部。

@media screen and (max-width: 1023px) and (min-width: 768px) {
  .primary-content {
    padding-bottom: 0;
  }
  
  .wrapper-primary-text {
    width: 50%;
    padding-bottom: 80px;
  }

  .primary__main-img {
    width: 50%;
    align-self: flex-end;
  }
}

Before

After

Selected works

原本是讓作品並排顯示,但在 Tablet 版本要讓作品垂直排列,所以設定 wrapper-selected-worksflex-direction 值為 column ;另外再將 wrapper-work 設定 display 值為 flex,就會自動讓內部的圖片跟文字區根據水平的方向去排列。

@media screen and (max-width: 1023px) and (min-width: 768px) {
  .wrapper-selected-works {
    width: 600px;
    flex-direction: column;
    justify-content: flex-start;
  }
  .wrapper-work {
    display: flex;
    margin-bottom: 50px;
  }
  .wrapper-work-text {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    margin-left: 30px;
  }
  .work__title {
    margin-top: 0;
  }
}

Before

After

About

在 About 這個區塊,依照之前百分比的設定,左右兩欄會自動去縮放。但縮放到某個尺寸的時候,你會發現兩欄的大小好像不太夠,圖片跟文字會擠在一起。所以就將最外層的容器寬度再調大一點,並設定它最大的尺寸:

@media screen and (max-width: 1023px) and (min-width: 768px) {
  .wrapper-about {
    max-width: 820px;
    width: 90%;
  }
}

Before

After

Footer

Footer 這個區塊也很簡單,因為寬度會不夠把 Logo 跟連結選單並排顯示,只要修改排列的方式變成垂直排列就行了。

@media screen and (max-width: 1023px) and (min-width: 768px) {
  .footer-content {
    flex-direction: column;
    justify-content: flex-start;
    width: fit-content;
  }

  footer nav {
    margin-top: 30px;
  }
}

Before

After


螢幕寬度<768px

最後一個版本 Mobile,終於會來到我們的重頭戲 — 漢堡選單。當你在手機上瀏覽網頁的時候,你應該有注意到大部分的導覽列,都會被收進一個像漢堡的按鈕裡,按下按鈕就可以開啟導覽選單。那是因為在手機上因為螢幕太小,很難去放置前面做的那種展開的導覽列,所以會選擇把選單收合起來,是在網站上非常常見的一個做法。

Header — 漢堡選單

首先先設定選單尚未展開的樣式,在 Header 區塊裡加上按鈕的 HTML,展開後的選單元件不會另外新增,會直接使用 Header 內部的元素,並調整它的樣式。

<header>
    <div class="header-content wrapper-content">
        <h1 class="logo">PEI-YUN</h1>
        <div class="wrapper-hamburger">
            <div class="cross-button-top cross-button"></div>
            <div class="cross-button-bottom cross-button"></div>
        </div>
        <nav class="header-nav">
            ...
        </nav>
    </div>
</header>

除了設定按鈕的樣式,在還沒展開選單的狀態下,要讓導覽列先消失不見,而且不會影響到其他元素,想要做到這樣的效果可以用 display: none

/* header */
@media screen and (max-width: 767px) {
  .wrapper-hamburger {
    height: 15px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    cursor: pointer;
  }

  .cross-button {
    width: 30px;
    height: 3px;
    background-color: #333;
    transition: all 0.2s;
  }

  .header-nav {
    display: none;
  }
}

/* section-primary */
@media screen and (max-width: 767px) {
.primary-content {
    ...
    padding-top: 70px;
  }
}

沒有展開選單時的 Header

要如何做到按下按鈕之後展開選單?很簡單,在前面的章節有提到可以利用 Javascript 來操作 DOM 元素。當按下按鈕展開選單,就在指定的元素加上展開後的樣式;相反的要收合選單,移除那些樣式就能回復到展開之前。

所以只要加上 header-content_active,並用 CSS 的後代選擇器來設定底下元素在展開後的樣式。這樣一來只要透過 Javascript 新增移除 header-content_active 這個 ClassName,就能實現選單開闔的效果。

<header>
    <div class="header-content_active header-content wrapper-content">
        ...
    </div>
</header>
@media screen and (max-width: 767px) {
  .header-content_active {
    background-color: #333;
    height: 100vh;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-content: flex-start;
    align-items: center;
    padding-bottom: 20px;
  }

  .header-content_active .header-nav {
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-top: 20vh;
  }

  .header-content_active .logo {
    color: white;
  }

  .header-content_active .link-text {
    color: white;
    font-size: 36px;
    margin-bottom: 50px;
  }

  .header-content_active .wrapper-hamburger {
    height: 30px;
    justify-content: center;
  }

  .header-content_active .cross-button {
    background-color: white;
  }

  .header-content_active .cross-button-top {
    transform: rotate(45deg) translateY(2px);
  }

  .header-content_active .cross-button-bottom {
    transform: rotate(-45deg) translateY(-2px);
  }
}

選單展開後的 Header

設定完選單展開前後的樣式後,最後一步就是要加上 Javascript 來操作元素,點擊按鈕打開選單,要對 header-content 新增 ClassName header-content_active;點擊按鈕關閉選單,再移除 header-content_active,透過這樣的機制讓底下元素變化對應的樣式。

<header>
    <div id="header-content" class="header-content wrapper-content">
        ...
        <div id="hamburger" class="wrapper-hamburger">
            ...
        </div>
        ...
    </div>
</header>
...
<!-- 記得將js檔放在body最後引入 -->
<script src="js/index.js"></script>
</body>
</html>

index.js

let target = document.getElementById("header-content");
let button = document.getElementById("hamburger");

button.addEventListener("click", function (event) {
  target.classList.toggle("header-content_active");
});

利用 CSS 屬性 transition,加上一點轉場效果:

@media screen and (max-width: 767px) {
  .header-content {
    transition: background-color 0.2s;
  }
}

Section Primary

做完最難的漢堡選單,剩下的區塊基本上就跟調整 Tablet 的時候一樣。在 Primary 區塊,改變左右欄的排列方式變成上下欄:

@media screen and (max-width: 767px) {
  .primary-content {
    flex-direction: column;
    padding-bottom: 0;
  }
  .wrapper-primary-text {
    width: 90%;
  }

  .primary__title {
    font-size: 48px;
  }

  .primary__social {
    display: none;
  }

  .primary__main-img {
    width: 80%;
    align-self: center;
  }
}

Before

After

Selected works

Selected works 區塊在 768px 以下,會從 Desktop 版本的並排模式,轉換成作品垂直排列,所以一樣設定 flex-direction 值為 column,讓作品內容可以完整顯示在網頁上。

@media screen and (max-width: 767px) {
  .secondary__title {
    font-size: 28px;
  }
  .wrapper-selected-works {
    width: 300px;
    flex-direction: column;
  }
  .work__title {
    font-size: 20px;
  }
  .wrapper-work {
    margin-bottom: 50px;
  }
}

Before

After

About

About 區塊也是一樣。基本上你可以發現,在 Mobile 版本,就是把原本寬度不夠不好並排顯示的內容,轉換一下排列的方式變成垂直排列,再調整一下寬度比例,就可以讓內容最佳的呈現在網頁上

@media screen and (max-width: 767px) {
  .wrapper-about {
    width: 95%;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
  }

  .wrapper-about-text {
    width: 80%;
    margin-top: 50px;
  }
}

Before

After

Footer

終於來到最後一個區塊 Footer,除了左右兩欄要調整成垂直排列,選單內部的每個小區塊也要垂直顯示。

@media screen and (max-width: 767px) {
  .footer-content {
    width: 100%;
    flex-direction: column;
    justify-content: flex-start;
  }

  footer nav {
    width: 100%;
    flex-direction: column;
    margin-top: 30px;
  }

  .footer-nav-list {
    margin-top: 30px;
  }
}

Before

After


小結

你做完的網頁應該會長成這樣

終於帶大家完成我們的個人網頁,在過程中也使用到前面一路學習到的 HTML、CSS、RWD、JS,這些都是構成一個完整的網頁不可獲缺的技能。當然網頁版面五花八門,如何成為一等一的網頁刻版大師?最好的學習方法就是:「動手做!」,建議大家可以去找各式各樣的網站,動手做出一模一樣的版型,你可以在過程中學習到更多技能的知識,未來碰到什麼樣式的版面也難不倒你喔!

如果文章中有錯誤的地方,要麻煩各位大大不吝賜教;喜歡的話,也要記得幫我按讚訂閱喔❤️


上一篇
[Day 15 - 小試身手] 用HTML、CSS、JS打造個人網站 (2)
下一篇
[Day 17 - npm] 哆啦A夢有百寶袋,我有套件管理工具npm
系列文
Follow me! 來一場前端技能樹之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言