PC端CSS佈局彙總

前言

此文章是 解剖CSS佈局原理 的續集,以前那篇文章講的都是理論,本文章講具體的實例,根據本身對佈局的理解與開發經驗分爲如下幾類。css

由於PC端和移動端佈局差別較大,因此我將兩端佈局分開講,本文章將針對PC端的佈局進行講解,如下代碼只寫關鍵代碼。若是你發現你寫了關鍵打代碼還達不到效果,請檢查是否寫了不應寫的樣式。html

爲了提升網頁性能,考慮到repaint/reflow,表格元素儘可能少用,有其餘選擇的狀況儘可能用其餘佈局。segmentfault

居中佈局

1、單個元素水平居中

<div id="container">
  <div class="box"></div>
</div>

1. 寬度固定

方法一:app

.box {
  width: 300px;
  margin: 0 auto;
}

比較經常使用的方法ide

方法二:佈局

#container {
  position: relative;
}
.box {
  width: 100px;
  position: absolute;
  left: 0;
  right: 0;
  margin: 0 auto;
}

此方法適用於定位時的居中方式性能

2. 寬度不固定

方法一:flex

.box {
  display: table;
  margin: 0 auto;
}

缺點:設置爲表格元素,內部元素的佈局有可能收到影響flexbox

方法二:spa

#container {
  position: relative;
}
.box {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
}

缺點:要用到 transform ,兼容性較差

方法三:

#container {
  display: table-cell;   // 這屬性在這可加可不加
  text-align: center;
}
.box {
  display: inline-block;
}

缺點:須要涉及到父類的樣式

2、單個元素垂直居中

<div id="container">
  <div class="box"></div>
</div>

高度固定

方法一:

#container {
  position: relative;
}
.box {
  height: 50px;
  position: absolute;
  top: 0;
  bottom: 0;
  margin: auto 0;
}

缺點:要用到定位,脫離文檔流

方法二:

#container {
  height: 400px;
  line-height: 400px;
}
.box {
  display: inline-block;
  height: 50px;
  vertical-align: middle;
}

注意,父容器設置了行高,子類要記得重置行高

高度不固定

方法一:

#container {
  position: relative;
}
.box {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}

缺點:要用到 transform ,兼容性較差

方法二:

#container {
  display: table-cell;
  verticle-align: middle;
}

缺點:由父類控制是否居中

3、多個元素水平居中

<div id="container">
  <span>1</span>
  <span>2</span>
  <span>3</span>
</div>
#container {
  width: 200px;
  height: 100px;
  background: #ccc;
  text-align: center;
}
span {
  display: inline-block;
  background: #9fc;
}

4、多個元素垂直居中

<div id="container">
  <p>1</p>
  <p>2</p>
  <p>3</p>
</div>
#container {
  height: 200px;
  display: table-cell;
  vertical-align: middle;
}

單行多列布局

1、等寬排列

<div id="container">
  <div class="box box1"></div>
  <div class="box box2"></div>
  <div class="box box3"></div> 
</div>
#container {
  display: table;
  table-layout: fixed;
}
.box {
  display: table-cell;
}

2、兩列布局

<div id="container">
  <div class="left"></div>
  <div class="right"></div>
</div>

1. 一列定寬,一列自適應,高度各自自適應

左列定寬:

.left {
  float: left;
  width: 100px;
}
.right {
  margin-left: 100px;
}

右列定寬:

#container {
  padding-right: 100px;
  overflow: hidden;
}
.left {
  float: left;
  width: 100%;
}
.right {
  position: relative;
  float: left;
  width: 100px;
  right: -100px;
  margin-left: -100px;
}

2. 一列定寬,一列自適應,高度相同取二者最大值

#container {
  display: table;
  table-layout: fixed;
}
.left,
.right {
  display: table-cell;
}
.right {
  width: 100px;
}

須要定寬的那列設置寬度

三、一列不定寬,一列自適應

右列自適應:

<div id="container">
  <div class="left"></div>
  <div class="right"></div>
</div>
.left {
  float: left;
}
.right {
  overflow: auto;
}

左列自適應:

<div id="container">
  <div class="right"></div>
  <div class="left"></div>
</div>
.left {
  overflow: auto;
}
.right {
  float: right;
}

3、三列布局

一、兩側定寬,中間自適應,高度各類自適應

方法一:

<div id="container">
  <div class="left">定寬</div>
  <div class="center">自適應</div>
  <div class="right">定寬</div>
</div>
.left,
.right {
  position: absolute;
  top: 0;
}
.left {
  left: 0;
  width: 150px;
}
.center {
  margin: 0 80px 0 150px;
}
.right {
  right: 0;
  width: 80px;
}

方法二:聖盃佈局

<div id="container">
  <div class="left">定寬</div>
  <div class="center">自適應</div>
  <div class="right">定寬</div>
</div>
#container {
  padding: 0 8px 0 150;
}
.left,
.center,
.right {
  position: relative;
  float: left;
}
.left {
  width: 150px;
  left: -150px;
  margin-right: -100%;
}
.center {
  width: 100%;
  height: 200px;
}
.right {
  width: 80px;
  right: -80px;
  margin-left: -80px;
}

方法三:雙飛翼佈局

<div id="container">
  <div class="wrap">
    <div class="center">自適應</div>
  </div>
  <div class="left">定寬</div>
  <div class="right">定寬</div>
</div>
.left,
.wrap,
.right {
  float: left;
}
.left {
  width: 150px;
  margin-left: -100%;
}
.wrap {
  width: 100%;
}
.center {
  margin: 0 80px 0 150px;
}
.right {
  width: 80px;
  margin-left: -80px;
}

二、兩列定寬,中間自適應,高度相同取二者最大值

<div id="container">
  <div class="left">定寬</div>
  <div class="center">自適應</div>
  <div class="right">定寬</div>
</div>
#container {
  width: 100%;
  display: table;
}
.left,
.right,
.center {
  display: table-cell;
}
.left {
  width: 150px;
}
.right {
  width: 80px;
}

多行多列布局

1、圖文並茂

<div class="article">
  <img src="../img/icon.png">隨着HTML的成長,爲了知足頁面設計者的要求,HTML添加了不少顯示功能。可是隨着這些功能的增長,HTML變的愈來愈雜亂,並且HTML頁面也愈來愈臃腫。因而CSS便誕生了。
</div>
img {
  float: left;
}

2、均衡分佈

一、相同間距

<ul class="list">
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

方法一:用浮動

.list {
  width: 500px;
  height: 260px;
}
.list li {
  float: left;
  width: 100px;
  height: 100px;
  margin-left: 20px;
  margin-top: 20px;
  background: #c9f;
}

經過 margin 來達到等距效果,根據父容器寬高和子類寬高與個數,算出 margin-leftmargin-top 的值

方法二:用內聯塊

.list {
  width: 500px;
  height: 260px;
  font-size: 0;
}
.list li {
  display: inline-block;
  width: 100px;
  height: 100px;
  margin-left: 20px;
  margin-top: 20px;
  background: #c9f;
}

用內聯塊的話,若是子類有文本,要記得設置 font-size

2. 去除邊界間距

在上一個例子下去除邊界間距

.list {
  width: 460px;
  height: 220px;
}
.list li {
  float: left;
  width: 100px;
  height: 100px;
  margin-left: 20px;
  margin-top: 20px;
  background: #c9f;
}
.list li:nth-of-type(4n+1) { margin-left: 0 }
.list li:nth-of-type(-n+4) { margin-top: 0 }

若要兼容IE8,則在對應的標籤上加類名,單獨處理

3、瀑布流佈局

如上圖,所謂的瀑布流佈局就是一系列盒子或圖片的等寬不等高佈局。

真正的瀑布流佈局是這樣:

  1. 給每張圖片設置相同的寬度,第一行所有置頂,順序排列

  1. 從第二行開始尋找最低高度的那一列做爲下一張圖片的排列位置,這時很顯然第二列高度最低,就把第四張圖片放在第二列下面

  1. 這時第一列和第三列高度相同,咱們優先選擇左邊那列,把第五張圖片放在第一列下面

  1. 這時第三列高度最低,第六張圖片放在第三列下面,以此類推。

網上有人說用多列浮動佈局、用CSS3佈局、用flexbox,其實實現的都是假的瀑布流,都有可能出現三列的高度差別較大的狀況,真正的瀑布流是三列高度相差不大的。如下的瀑布流的具體實現

html

<div class="list">
  <img src="../img/1.jpg" class="img1">
  <img src="../img/2.jpg" class="img2">
  <img src="../img/3.jpg" class="img3">
  <img src="../img/4.jpg" class="img4">
  <img src="../img/5.jpg" class="img5">
  <img src="../img/6.jpg" class="img6">
  <img src="../img/7.jpg" class="img7">
  <img src="../img/8.jpg" class="img8">
  <img src="../img/9.jpg" class="img9">
</div>

css

.list {
  position: relative;
  width: 600px;
}
.list img {
  position: absolute;
}

js

document.addEventListener('DOMContentLoaded', function () {
  var listDOM = document.querySelector('.list');
  var imgsDOM = listDOM.querySelectorAll('img');
  
  waterfallFlowLayout(listDOM, imgsDOM, 3);
})

/**
 * 瀑布流佈局
 * 
 * @param {DOM object} listDOM  存放圖片列表的容器DOM
 * @param {DOM object} imgsDOM  圖片DOM
 * @param {number} colsCount    列數
 */
function waterfallFlowLayout (listDOM, imgsDOM, colsCount) {
  colsCount = colsCount || 3;   // 默認3列

  var currHeightArr = []; // 存放當前每列的總高度
  var imgWidth = listDOM.offsetWidth / colsCount

  // 遍歷全部圖片DOM元素
  for (var i = 0; i < imgsDOM.length; i++) {
    var imgDOM = imgsDOM[i];
    imgDOM.style.width = imgWidth + 'px';  // 設置各個圖片的寬度

    // 若是是第一行的就直接存高度,並設置top和left
    if (i < colsCount) {
      currHeightArr.push(imgDOM.offsetHeight);
      imgDOM.style.left = (i % colsCount) * imgWidth + 'px';
      imgDOM.style.top = 0;
    }
    // 不然
    else {
      var minNum = Math.min.apply(Math, currHeightArr);     // 獲取最小值
      var index = currHeightArr.indexOf(minNum);            // 獲取最小值的下標

      // 根據最小值下標獲得對應的DOM,獲取它的left賦給當前的left
      imgDOM.style.left = imgsDOM[index].offsetLeft + 'px'; 
      imgDOM.style.top = minNum + 'px'; // 使用最小值做爲當前的top

      // 更新每列的總高度
      currHeightArr[index] += imgDOM.offsetHeight;
    }
  }
}

全屏佈局

<div class="head">頭部</div>
<div class="sidebar">側邊導航</div>
<div class="main">主體內容</div>
<div class="foot">底部</div>
.head,
.foot,
.sidebar,
.main {
  position: absolute;
}
.head {
  top: 0;
  left: 0;
  right: 0;
  height: 80px;
}
.foot {
  bottom: 0;
  left: 0;
  right: 0;
  height: 60px;
}
.sidebar {
  top: 80px;
  bottom: 60px;
  left: 0;
  width: 100px;
}
.main {
  top: 80px;
  bottom: 60px;
  left: 100px;
  right: 0;
}
相關文章
相關標籤/搜索