如何實現兩欄佈局,右側自適應?三欄佈局中間自適應呢?

林恒發表於2024-06-01

一、背景

在日常佈局中,無論是兩欄佈局還是三欄佈局,使用的頻率都非常高

兩欄佈局

兩欄佈局實現效果就是將頁面分割成左右寬度不等的兩列,寬度較小的列設定為固定寬度,剩餘寬度由另一列撐滿,

比如 Ant Design 文件,藍色區域為主要內容佈局容器,側邊欄為次要內容佈局容器

這裡稱寬度較小的列父元素為次要佈局容器,寬度較大的列父元素為主要佈局容器

這種佈局適用於內容上具有明顯主次關係的網頁

三欄佈局

三欄佈局按照左中右的順序進行排列,通常中間列最寬,左右兩列次之

大家最常見的就是github

二、兩欄佈局

兩欄佈局非常常見,往往是以一個定寬欄和一個自適應的欄並排展示存在

實現思路也非常的簡單:

  • 使用 float 左浮左邊欄
  • 右邊模組使用 margin-left 撐出內容塊做內容展示
  • 為父級元素新增BFC,防止下方元素飛到上方內容

程式碼如下:

<style>
    .box{
        overflow: hidden; 新增BFC
    }
    .left {
        float: left;
        width: 200px;
        background-color: gray;
        height: 400px;
    }
    .right {
        margin-left: 210px;
        background-color: lightgray;
        height: 200px;
    }
</style>
<div class="box">
    <div class="left">左邊</div>
    <div class="right">右邊</div>
</div>

還有一種更為簡單的使用則是採取:flex彈性佈局

flex彈性佈局

<style>
    .box{
        display: flex;
    }
    .left {
        width: 100px;
    }
    .right {
        flex: 1;
    }
</style>
<div class="box">
    <div class="left">左邊</div>
    <div class="right">右邊</div>
</div>

flex可以說是最好的方案了,程式碼少,使用簡單

注意的是,flex容器的一個預設屬性值:align-items: stretch;

這個屬性導致了列等高的效果。 為了讓兩個盒子高度自動,需要設定: align-items: flex-start

三、三欄佈局

實現三欄佈局中間自適應的佈局方式有:

  • 兩邊使用 float,中間使用 margin
  • 兩邊使用 absolute,中間使用 margin
  • 兩邊使用 float 和負 margin
  • display: table 實現
  • flex實現
  • grid網格佈局

兩邊使用 float,中間使用 margin

需要將中間的內容放在html結構最後,否則右側會臣在中間內容的下方

實現程式碼如下:

<style>
    .wrap {
        background: #eee;
        overflow: hidden; <!-- 生成BFC,計算高度時考慮浮動的元素 -->
        padding: 20px;
        height: 200px;
    }
    .left {
        width: 200px;
        height: 200px;
        float: left;
        background: coral;
    }
    .right {
        width: 120px;
        height: 200px;
        float: right;
        background: lightblue;
    }
    .middle {
        margin-left: 220px;
        height: 200px;
        background: lightpink;
        margin-right: 140px;
    }
</style>
<div class="wrap">
    <div class="left">左側</div>
    <div class="right">右側</div>
    <div class="middle">中間</div>
</div>

原理如下:

  • 兩邊固定寬度,中間寬度自適應。
  • 利用中間元素的margin值控制兩邊的間距
  • 寬度小於左右部分寬度之和時,右側部分會被擠下去

這種實現方式存在缺陷:

  • 主體內容是最後載入的。

  • 右邊在主體內容之前,如果是響應式設計,不能簡單的換行展示

兩邊使用 absolute,中間使用 margin

基於絕對定位的三欄佈局:注意絕對定位的元素脫離文件流,相對於最近的已經定位的祖先元素進行定位。無需考慮HTML中結構的順序

<style>
  .container {
    position: relative;
  }
  
  .left,
  .right,
  .main {
    height: 200px;
    line-height: 200px;
    text-align: center;
  }

  .left {
    position: absolute;
    top: 0;
    left: 0;
    width: 100px;
    background: green;
  }

  .right {
    position: absolute;
    top: 0;
    right: 0;
    width: 100px;
    background: green;
  }

  .main {
    margin: 0 110px;
    background: black;
    color: white;
  }
</style>

<div class="container">
  <div class="left">左邊固定寬度</div>
  <div class="right">右邊固定寬度</div>
  <div class="main">中間自適應</div>
</div>

實現流程:

  • 左右兩邊使用絕對定位,固定在兩側。
  • 中間佔滿一行,但透過 margin和左右兩邊留出10px的間隔

兩邊使用 float 和負 margin

<style>
  .left,
  .right,
  .main {
    height: 200px;
    line-height: 200px;
    text-align: center;
  }

  .main-wrapper {
    float: left;
    width: 100%;
  }

  .main {
    margin: 0 110px;
    background: black;
    color: white;
  }

  .left,
  .right {
    float: left;
    width: 100px;
    margin-left: -100%;
    background: green;
  }

  .right {
    margin-left: -100px; /* 同自身寬度 */
  }
</style>

<div class="main-wrapper">
  <div class="main">中間自適應</div>
</div>
<div class="left">左邊固定寬度</div>
<div class="right">右邊固定寬度</div>

實現過程:

  • 中間使用了雙層標籤,外層是浮動的,以便左中右能在同一行展示
  • 左邊透過使用負 margin-left:-100%,相當於中間的寬度,所以向上偏移到左側
  • 右邊透過使用負 margin-left:-100px,相當於自身寬度,所以向上偏移到最右側

缺點:

  • 增加了 .main-wrapper 一層,結構變複雜
  • 使用負 margin,除錯也相對麻煩

使用 display: table 實現

<table> 標籤用於展示行列資料,不適合用於佈局。但是可以使用 display: table 來實現佈局的效果

<style>
  .container {
    height: 200px;
    line-height: 200px;
    text-align: center;
    display: table;
    table-layout: fixed;
    width: 100%;
  }

  .left,
  .right,
  .main {
    display: table-cell;
  }

  .left,
  .right {
    width: 100px;
    background: green;
  }

  .main {
    background: black;
    color: white;
    width: 100%;
  }
</style>

<div class="container">
  <div class="left">左邊固定寬度</div>
  <div class="main">中間自適應</div>
  <div class="right">右邊固定寬度</div>
</div>

實現原理:

  • 層透過 display: table設定為表格,設定 table-layout: fixed`表示列寬自身寬度決定,而不是自動計算。
  • 內層的左中右透過 display: table-cell設定為表格單元。
  • 左右設定固定寬度,中間設定 width: 100% 填充剩下的寬度

使用flex實現

利用flex彈性佈局,可以簡單實現中間自適應

程式碼如下:

<style type="text/css">
    .wrap {
        display: flex;
        justify-content: space-between;
    }

    .left,
    .right,
    .middle {
        height: 100px;
    }

    .left {
        width: 200px;
        background: coral;
    }

    .right {
        width: 120px;
        background: lightblue;
    }

    .middle {
        background: #555;
        width: 100%;
        margin: 0 20px;
    }
</style>
<div class="wrap">
    <div class="left">左側</div>
    <div class="middle">中間</div>
    <div class="right">右側</div>
</div>

實現過程:

  • 僅需將容器設定為display:flex;
  • 盒內元素兩端對其,將中間元素設定為100%寬度,或者設為flex:1,即可填充空白
  • 盒內元素的高度撐開容器的高度

優點:

  • 結構簡單直觀
  • 可以結合 flex的其他功能實現更多效果,例如使用 order屬性調整顯示順序,讓主體內容優先載入,但展示在中間

grid網格佈局

程式碼如下:

<style>
    .wrap {
        display: grid;
        width: 100%;
        grid-template-columns: 300px auto 300px;
    }

    .left,
    .right,
    .middle {
        height: 100px;
    }

    .left {
        background: coral;
    }

    .right {
        background: lightblue;
    }

    .middle {
        background: #555;
    }
</style>
<div class="wrap">
    <div class="left">左側</div>
    <div class="middle">中間</div>
    <div class="right">右側</div>
</div>

flex彈性佈局一樣的簡單

參考文獻

  • https://zhuqingguang.github.io/2017/08/16/adapting-two-layout/

  • https://segmentfault.com/a/1190000008705541

如果對您有所幫助,歡迎您點個關注,我會定時更新技術文件,大家一起討論學習,一起進步。

如何實現兩欄佈局,右側自適應?三欄佈局中間自適應呢?

相關文章