使用Flexible Box設計版面配置

by vivid 14. 十一月 2018 03:11

.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號: N181120101
出刊日期: 2018/11/14

在這篇文章之中,我將介紹使用HTML5的Flexible Box Layout(CSS 彈性盒子布局)進行網頁版面配置,它是出自於CSS Flexible Box Layout Module Level 1(目前最新版本為W3C Candidate Recommendation, 19 October 2017),提供了更有效率、簡單的方式來進行網頁版面的配置動作,也非常適合於RWD響應式網頁設計。

 

CSS 「box-sizing」屬性

在開始進行Flexible Box Layout(CSS 彈性盒子布局)設計網頁配置之前,我們先來探討一個CSS屬性:「box-sizing」。我們先看一個範例,參考以下範例程式碼:

<!DOCTYPE html>
<html lang = "en">

<head>
  <meta charset = "UTF-8">
  <meta name = "viewport" content = "width=device-width, initial-scale=1.0">
  <meta http-equiv = "X-UA-Compatible" content = "ie=edge">
  <title> Document </title>
  <style>
    .div1 {
      width: 200px;
      margin: 20px auto;
      border: 1px solid red;
    }

    .div2 {
      width: 200px;
      margin: 20px auto;
      padding: 15px;
      border: 5px solid red;
    }
  </style>
</head>

<body>
  <div class = "div1"> div1 </div>
  <div class = "div2"> div2 </div>
</body>

</html>


 

 

範例中有兩個「div」標籤設分別設定了CSS樣式,這兩個樣式寬度(width)設定相同,但是最後在網頁呈現的實際寬度看起來卻不太一樣。這是因為div2最終的寬度還要加上內距(padding)與邊框(border)的寬度,換句話說,HTML項目的寬、高會受內距與邊框影響。

clip_image002

圖 1:HTML項目的寬、高會受內距與邊框影響。

在過去我們都要做一些數學計算來算出實際佔有的寬度,以便處理排版問題,現在我們有更簡單的做法利用 CSS「box-sizing」 屬性便可以輕易解決這個問題。只要設定HTML項目的「box-sizing」屬性為「border-box」,那麼內距(padding)與邊框(border)的寬度就不會加總到HTML項目本身的寬度。參考以下範例程式碼,修改上述範例程式,我們利用萬用選取器「*」將所有HTML項目的「box-sizing」屬性都設為「border-box」。

<!DOCTYPE html>
<html lang = "en">

<head>
  <meta charset = "UTF-8">
  <meta name = "viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv = "X-UA-Compatible" content = "ie=edge">
  <title> Document </title>
  <style>
    *,
    *::after,
    *::before {
      box-sizing: border-box;
    }

    .div1 {
      width: 200px;
      margin: 20px auto;
      border: 1px solid red;
    }

    .div2 {
      width: 200px;
      margin: 20px auto;
      padding: 15px;
      border: 5px solid red;
    }
  </style>
</head>

<body>
  <div class = "div1"> div1 </div>
  <div class = "div2"> div2 </div>
</body>

</html>

 

這次再檢視網頁執行結果,這兩個div項目的寬度看起來就會是一樣:

clip_image004

圖 2:設定「box-sizing: border-box」HTML項目的寬度便不受內距與邊框影響。

建立網格(Grid)系統

為了便於網頁版面配置,我們假設網頁寬度最多可以有12欄,則寬度為「100%」時,我們便可以從這個簡單的算數: 「100%/12 = 8.33% 」,算出一個欄位寬度約佔「8.33%」,如此我們就可以定義以下CSS樣式,方便後續設計網頁時,可以重複使用這些樣式來設定寬度。

.col-1 {
    flex : 8.33%;
  }

  .col-2 {
    flex : 16.66%;
  }

  .col-3 {
    flex : 25%;
  }

  .col-4 {
    flex : 33.33%;
  }

  .col-5 {
    flex : 41.66%;
  }

  .col-6 {
    flex : 50%;
  }

  .col-7 {
    flex : 58.33%;
  }

  .col-8 {
    flex : 66.66%;
  }

  .col-9 {
    flex : 75%;
  }

  .col-10 {
    flex : 83.33%;
  }

  .col-11 {
    flex : 91.66%;
  }

  .col-12 {
    width : 100%;
  }

未來,若我們需要將網頁內容的寬度平均切為兩欄,那麼只要讓兩個HTML項目分別套用「col-6」樣式:

clip_image006

圖 3:網頁內容的寬度平均切為兩欄。

我們需要將網頁內容的寬度切為兩欄,左邊寬度是右邊一半,那麼只要讓兩個HTML項目分別套用「col-4」、「col-8」樣式:

clip_image008

圖 4:網頁內容的寬度切為兩,左邊寬度是右邊一半。

我們需要將網頁內容的寬度平均切為三欄那麼,只要讓兩個HTML項目分別套用「col-4」樣式:

clip_image010

圖 5:網頁內容的寬度平均切為三欄。

使用Flexible Box配置版面

我們來看使用Flexible Box做網頁版面配置的範例,網頁的表頭(Header)、導覽列(Navigation Bar)與表尾(Footer)寬度要跟瀏覽器寬度一致。中間將切為4欄,顯示網頁內容,完成的結果參考下圖:

clip_image012

圖 6:網頁版面。

使用的網頁程式表列如下:

<!DOCTYPE html>
<html>

<head>
  <title>Page Title</title>
  <meta charset = "UTF-8">
  <meta name = "viewport" content = "width=device-width, initial-scale=1">
  <style>
    *,
    *::after,
    *::before {
      box-sizing: border-box;
    }

    body {
      font-family: Arial;
      margin: 0;
    }

    .header {
      padding: 60px;
      text-align: center;
      background: coral;
      color: white;
    }

    .navbar {
      display: flex;
      background-color:brown;
      flex-wrap: wrap;
    }

    .navbar a {
      color: white;
      padding: 14px 20px;
      text-decoration: none;
      text-align: center;
    }

    .navbar a:hover {
      background-color: #ddd;
      color:brown;
    }

    .row {
      display: flex;
      flex-wrap: wrap;
    }

    .left-panel {
      background-color: khaki;
      padding: 20px;
    }

    .right-panel {
      background-color: #f1f1f1;
      padding: 20px;
    }

    .main {
      background-color: white;
      padding: 20px;
    }

    .footer {
      padding: 20px;
      text-align: center;
      background: bisque;
    }

    .col-1 {
      flex: 8.33%;
    }

    .col-2 {
      flex: 16.66%;
    }

    .col-3 {
      flex: 25%;
    }

    .col-4 {
      flex: 33.33%;
    }

    .col-5 {
      flex: 41.66%;
    }

    .col-6 {
      flex: 50%;
    }

    .col-7 {
      flex: 58.33%;
    }

    .col-8 {
      flex: 66.66%;
    }

    .col-9 {
      flex: 75%;
    }

    .col-10 {
      flex: 83.33%;
    }

    .col-11 {
      flex: 91.66%;
    }

    .col-12 {
      width: 100%;
    }
  </style>
</head>

<body>
  <!-- Header -->
  <div class = "header">
    <h1>Personal Website</h1>
    <p>Lorem ipsum dolor sit amet.</p>
  </div>
  <!-- Navigation Bar -->
  <div class = "navbar">
    <a href = "#">Link1 </a>
    <a href = "#">Link2</a>
    <a href = "#">Link3</a>
    <a href = "#">Link4</a>
    <a href = "#">Link5</a>
    <a href = "#">Link6</a>
  </div>

  <div class = "container">
      <!-- flex grid -->
    <div class = "row">
      <div class = "col-3 left-panel">
        <h2>Information 1</h2>
        <h5>Lorem ipsum dolor sit amet.</h5>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Magni quos dolorum, neque mollitia deserunt tempore sit velit quo ad obcaecati.</p>

        <h2>Information 2</h2>
        <h5>Lorem ipsum dolor sit amet.</h5>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Magni quos dolorum, neque mollitia deserunt tempore sit velit quo ad obcaecati.</p>

        <h2>Information 3</h2>
        <h5>Lorem ipsum dolor sit amet.</h5>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Magni quos dolorum, neque mollitia deserunt tempore sit velit quo ad obcaecati.</p>

      </div>
      <div class = "col-3 main">
        <h2>Section 1</h2>
        <h5>Lorem ipsum dolor sit amet.</h5>
        <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Corporis rem quae libero voluptates nostrum sapiente repellendus mollitia delectus ratione atque rerum enim cumque non magni adipisci vel impedit, qui iusto?</p>

      </div>
      <div class = "col-3 main">
        <h2>Section 2</h2>
        <h5>Lorem ipsum dolor sit amet.</h5>
        <p>Lorem ipsum, dolor sit ametsse nulla, laudantium at delectus?</p>

      </div>
      <div class = "col-3 right-panel">
        <h2>Advetrisement</h2>
        <h5>Lorem ipsum dolor sit amet.</h5>
        <p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Doloremque eum ratione itaque vero delectus. Voluptatem
          molestias dicta accusantium dolorem minus.</p>
      </div>
    </div>
  </div>
  <!-- Footer -->
  <div class = "footer">
    <h2>Footer</h2>
  </div>

</body>

</html>

 

在容器類型的標籤設定樣式「display: flex」就可以啟用Flexible Box配置;「flex-wrap: wrap」設定表示寬度不夠時,自動換行,請參考下圖所示:

clip_image014

圖 7:使用「flex-wrap: wrap」設定自動換行。

使用媒體查詢(Media Query)

CSS3新增媒體查詢(Media Query)可以為CSS加上一些規則,在某個條件滿足的情況下,套用特定樣式,這也是響應式網頁必要的條件之一。例如我們可以為上個範例加上以下媒體查詢(Media Query),在瀏覽器的寬度小於575px的情況下,設定「flex-direction: column」,如此HTML項目便可以自動以堆疊方式呈現,接著再將導覽列隱藏起來,當使用者利用手機檢視網頁時,就看不到複雜的選單:

@media screen and (max-width: 575px) {
  .row,
  .navbar {
    flex-direction: column;
  }
  .navbar {
    display: none;
  }
}

 

參考以下執行結果:

clip_image016

圖 8:使用媒體查詢(Media Query)控制換行。

使用圖片

響應式網頁要求圖片應該隨著瀏覽器的寬度自動調整大小,只要將圖片的「width」設定為「100%」,「height」設為「auto」,再設定適當的內距即可,讓我們修改範例程式,為圖片加上以下樣式:

img {

    width: 100%;

    padding: 20px;

    height: auto;

}

最後完整的範例程式碼如下:

<!DOCTYPE html>
<html>

<head>
  <title>Page Title</title>
  <meta charset = "UTF-8">
  <meta name = "viewport" content = "width=device-width, initial-scale=1">
  <style>
    *,
    *::after,
    *::before {
      box-sizing: border-box;
    }

    body {
      font-family: Arial;
      margin: 0;
    }

    .header {
      padding: 60px;
      text-align: center;
      background: coral;
      color: white;
    }

    .navbar {
      display: flex;
      background-color: brown;
      flex-wrap: wrap;
    }

    .navbar a {
      color: white;
      padding: 14px 20px;
      text-decoration: none;
      text-align: center;
    }

    .navbar a:hover {
      background-color: #ddd;
      color: brown;
    }

    .row {
      display: flex;
      flex-wrap: wrap;
    }

    .left-panel {
      background-color: khaki;
      padding: 20px;
    }

    .right-panel {
      background-color: #f1f1f1;
      padding: 20px;
    }

    .main {
      background-color: white;
      padding: 20px;
    }

    .footer {
      padding: 20px;
      text-align: center;
      background: bisque;
    }

    .col-1 {
      flex: 8.33%;
    }

    .col-2 {
      flex: 16.66%;
    }

    .col-3 {
      flex: 25%;
    }

    .col-4 {
      flex: 33.33%;
    }

    .col-5 {
      flex: 41.66%;
    }

    .col-6 {
      flex: 50%;
    }

    .col-7 {
      flex: 58.33%;
    }

    .col-8 {
      flex: 66.66%;
    }

    .col-9 {
      flex: 75%;
    }

    .col-10 {
      flex: 83.33%;
    }

    .col-11 {
      flex: 91.66%;
    }

    .col-12 {
      width: 100%;
    }

    img {
      width: 100%;
      padding: 20px;
      height: auto;
    }

    @media screen and (max-width: 575px) {
      .row,
      .navbar {
        flex-direction: column;
      }
      .navbar {
        display: none;
      }
    }
  </style>
</head>

<body>
  <!-- Header -->
  <div class = "header">
    <h1>Personal Website</h1>
    <p>Lorem ipsum dolor sit amet.</p>
  </div>
  <!-- Navigation Bar -->
  <div class = "navbar">
    <a href = "#">Link1 </a>
    <a href = "#">Link2</a>
    <a href = "#">Link3</a>
    <a href = "#">Link4</a>
    <a href = "#">Link5</a>
    <a href = "#">Link6</a>
  </div>

  <div class = "container">
    <!-- flex grid -->
    <div class = "row">
      <div class = "col-3 left-panel">
        <h2>Information 1</h2>
        <h5>Lorem ipsum dolor sit amet.</h5>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Magni quos dolorum, neque mollitia deserunt tempore sit
          velit quo ad obcaecati.</p>

        <h2>Information 2</h2>
        <h5>Lorem ipsum dolor sit amet.</h5>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Magni quos dolorum, neque mollitia deserunt tempore sit
          velit quo ad obcaecati.</p>

        <h2>Information 3</h2>
        <h5>Lorem ipsum dolor sit amet.</h5>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Magni quos dolorum, neque mollitia deserunt tempore sit
          velit quo ad obcaecati.</p>

      </div>
      <div class = "col-3 main">
        <h2>Section 1</h2>
        <h5>Lorem ipsum dolor sit amet.</h5>
        <img src = "/images/cat_tied.png">
        <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Corporis rem quae libero voluptates nostrum sapiente repellendus
          mollitia delectus ratione atque rerum enim cumque non magni adipisci vel impedit, qui iusto?</p>

      </div>
      <div class = "col-3 main">
        <h2>Section 2</h2>
        <img src = "/images/cat_cage.png">
        <h5>Lorem ipsum dolor sit amet.</h5>
        <p>Lorem ipsum, dolor sit ametsse nulla, laudantium at delectus?</p>

      </div>
      <div class = "col-3 right-panel">
        <h2>Advetrisement</h2>
        <h5>Lorem ipsum dolor sit amet.</h5>
        <p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Doloremque eum ratione itaque vero delectus. Voluptatem
          molestias dicta accusantium dolorem minus.</p>
      </div>
    </div>
  </div>
  <!-- Footer -->
  <div class = "footer">
    <h2>Footer</h2>
  </div>

</body>

</html>

 

如此只要瀏覽器的寬度變動,圖片便隨之調整大小來做顯示,請參考下圖所示:

clip_image018

圖 9:圖片隨著瀏覽器寬度自動調整大小。

但當瀏覽器的寬度很大時,圖片可能也會放大超過實際原始寬度,解析度看起來會變差,此時可以改用「max-width」屬性,這樣圖片縮放時,便不會超過原始大小:

img {
   max-width: 100%;
   padding: 20px;
   height: auto;
}

小結

Flexible Layout Model的特色是:能在容器類型的標籤中,定義其中包含的項目之對齊方式、間距等等功能,並能適當地調整項目的寬、高,以符合最佳的螢幕大小或裝置顯示的需求,此外它也可以很容易地以垂直堆疊的方式呈現區(block)內容,也可以水平排列方式呈現(Inline),很適合來設計網頁的版面,例如知名的Bootstrap 4便採用Flexible Layout Model來設計。

Tags:

.NET Magazine國際中文電子雜誌 | 許薰尹Vivid Hsu | CSS

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List