CSS 多栏布局

🌙
手机阅读
本文目录结构
axihe

栅格系统,是 bootstrap 常用的布局模式,下列就举个简单四栏例子

html:

<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>

css:

.col{
    width:25%;
    height:500px;
    float: left;
    background: #ccc;
}
.col:nth-child(1){
    background: red;
}
.col:nth-child(2){
    background: green;
}
.col:nth-child(3){
    background: black;
}
.col:nth-child(4){
    background: yellow;
}

常见还有 column-count、column-gap、column-rule、columns

  1. 弹性布局 (flex) html:

    <ul>
    <li><a href="#">菜单1</a></li>
    <li><a href="#">菜单2</a></li>
    <li><a href="#">菜单3</a></li>
    <li><a href="#">菜单4</a></li>
    </ul>
    

  css:

ul{
    display: flex;
    height:100px;
    width:100%;
}
ul li{
    flex: auto;
    list-style:none;
    text-align:center;
    border:1px solid red;
}

CSS 等宽布局

//假如是n个child
<div class="parent-fix">
    <div class="parent">
        <div class="child"><p>1</p></div>
        <div class="child"><p>2</p></div>
        <div class="child"><p>3</p></div>
        <div class="child"><p>4</p></div>
    </div>
</div>

table

.parent-fix{
    margin-left: -20px;
}
.parent{
    display: table;
    width: 100%;
    table-layout: fixed;
}
.child{
    display: table-cell;
    padding-left: 20px;
}

flex


.parent{
    display: flex;
}
.child{
    flex: 1;
}
.child+.child {
    margin-left: 20px;
}

等高布局

<div class="parent"  style="background: black;">
    <div class="left" style="background: red;">
        <p>left</p>
    </div>
    <div class="right" style="background: green;">
        <p>right</p>
        <p>right</p>
    </div>
</div>

table

.parent{
    display: table;
    width: 100%;
    table-layout: fixed;
}
.left,.right{
    display: table-cell;
}
.left{
    width: 100px;
    border-right: 20px solid transparent;
    background-clip: padding-box;
}

flex

.parent{
    display: flex;
}
.right{
    flex: 1;
}
.left{
    width: 100px;
    margin-right: 20px;
}

float

//部分UI框架采用的就是这种方式,
.parent{
    overflow: hidden;
}
.left{
    float: left;
    margin-right: 20px;
}
.right{
    overflow: hidden;
}
.left,.right{
    padding-bottom: 9999px;
    margin-bottom: -9999px;
}

等分等高

5,等分

float + margin

.parent {
    margin-left: -20px;
}
.column {
    float: left;
    width: 25%;
    padding-left: 20px;
    box-sizing: border-box;
}

table + margin

.parent-fix{
    margin-left: -20px;
}
.parent{
    display: table;
    width:100%;
    table-layout: fixed;
}
.column{
    display: table-cell;
    padding-left: 20px;
}

flex

.parent{
    display:  flex;
}
.column{
    flex:  1;
}
.column+.column{
    margin-left: 20px;
}

6,等高

float + overflow

.parent {
    overflow: hidden;
}
.left,.right {
    padding-bottom: 9999px;
    margin-bottom: -9999px;
}
.left {
    float: left;
    width: 100px;
}
.right {
    overflow: hidden;
}

table

.parent {
    display: table;
    width: 100%;
}
.left {
    display:table-cell;
    width: 100px;
    margin-right: 20px;
}
.right {
    display:table-cell;
}

flex

.parent {
    display:flex;
    width: 100%;
}
.left {
    width: 100px;
}
.right {
    flex:1;
}

7,并排等分,单排对齐靠左布局

.main {
    display: flex;
    flex-flow: row-wrap;
    justify-content: space-between;
}
.item {
    display: inline-block;
}
.empty {
    height: 0;
    visibility: hidden;
}

6.1 等宽布局

6.1.1四列等宽

(1)使用float实现▲

效果图:

image.png

html代码:

<body>
<div id="parent">
    <div class="column">1 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">2 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">3 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">4 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
</div>
</body>

css代码:

/*使整体内容看起来居中,抵消padding-left的影响*/
#parent {margin-left: -20px;}
.column{
    padding-left: 20px;  /*盒子的边距*/
    width: 25%;
    float: left;
    box-sizing: border-box;
    border: 1px solid #000;
    background-clip: content-box; /*背景色从内容开始绘制,方便观察*/
    height: 500px;
}
.column:nth-child(odd){background-color: #f00;}
.column:nth-child(even){background-color: #0f0;}

原理:根据父元素空间宽度平分,子元素设置浮动,用padding去模拟间隔,再给父元素一个位移抵消第一个间隔

优缺点:

优点:代码简单,容易理解;兼容性较好(ie8+) 缺点:需要手动清除浮动,否则会产生高度塌陷;由于是百分比平分宽度不能设置margin,否则占位超出父元素宽度换行显示

(2)使用table实现▲

效果图:

image.png

html代码:

<body>
<div id="parent">
    <div class="column">1 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">2 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">3 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">4 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
</div>
</body>

css代码:

#parent {
    height: 540px;  /*抵消上下边20*2间距的高度影响*/
    display: table;
    margin: -20px 0;  /*抵消上下边20*2间距的位置影响*/
    /*两边离页面间距无法消除,改用子元素设置padding来当成间隔就不会有这样的问题*/
    border-spacing: 20px;  /*设置间距*/
}
.column{display: table-cell;}
.column:nth-child(odd){background-color: #f00;}
.column:nth-child(even){background-color: #0f0;}

原理:CSS Table以表格的形式显示

优缺点:

优点:代码简单;容易理解;适用于宽度高度未知情况;兼容性好(ie8+) 缺点:margin失效;设置间隔比较麻烦;设置tabl-cell的元素,宽度和高度的值设置百分比无效,需要给它的父元素设置display: table; 才生效;table-cell不感知margin,在父元素上设置table-row等属性,也会使其不感知height;设置float或position会对默认布局造成破坏,可以考虑为之增加一个父div定义float等属性;内容溢出时会自动撑开父元素

(3)使用flex实现

效果图:

image.png

html代码:

<body>
<div id="parent">
    <div class="column">1 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">2 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">3 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">4 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
</div>
</body>

css代码:

#parent {
    margin-left: -15px;  /*使内容看起来居中*/
    height: 500px;
    display: flex;
}
.column{
    flex: 1; /*一起平分#parent*/
    margin-left: 15px; /*设置间距*/
}
.column:nth-child(odd){background-color: #f00;}
.column:nth-child(even){background-color: #0f0;}

原理:flex设置排列方式、对齐方式罢了,请查阅文末flex阅读推荐

优缺点

优点:简单灵活;功能强大 缺点:PC端兼容性不好,移动端(Android4.0+) flex务必带上兼容,写法请参考文末阅读推荐,也可以使用autoprefixer

6.1.2多列等宽

效果图:

image.png

(1)使用float实现▲

html代码:

<body>
<div id="parent">
    <div class="column">1 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">2 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">3 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">4 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">5 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">6 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
</div>
</body>

css代码:

#parent {height: 500px;}
.column{
    float: left;  /*添加浮动*/
    width: 16.66666666666667%;  /*100÷列数,得出百分比*/
    height: 500px;
}
.column:nth-child(odd){background-color: #f00;}
.column:nth-child(even){background-color: #0f0;}

原理:根据父元素空间宽度平分,子元素设置浮动,用padding去模拟间隔,再给父元素一个位移抵消第一个间隔

优缺点:

优点:代码简单,容易理解;兼容性较好(ie8+) 缺点:需要手动清除浮动,否则会产生高度塌陷;由于是百分比平分宽度不能设置margin,否则占位超出父元素宽度换行显示

(2)使用table实现▲

html代码

<body>
<div id="parent">
    <div class="column">1 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">2 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">3 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">4 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">5 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">6 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
</div>
</body>

css代码:

#parent {
    width: 100%;
    height: 500px;
    display: table;
}
/*无需关注列数,单元格自动平分*/
.column{display: table-cell;}
.column:nth-child(odd){background-color: #f00;}
.column:nth-child(even){background-color: #0f0;}

原理:CSS Table以表格的形式显示

优缺点:

优点:代码简单;容易理解;适用于宽度高度未知情况;兼容性好(ie8+) 缺点:margin失效;设置间隔比较麻烦;设置tabl-cell的元素,宽度和高度的值设置百分比无效,需要给它的父元素设置display: table; 才生效;table-cell不感知margin,在父元素上设置table-row等属性,也会使其不感知height;设置float或position会对默认布局造成破坏,可以考虑为之增加一个父div定义float等属性;内容溢出时会自动撑开父元素

(3)使用flex实现

html代码:

<body>
<div id="parent">
    <div class="column">1 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">2 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">3 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">4 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">5 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">6 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
</div>
</body>

css代码:

#parent {
    height: 500px;
    display: flex;
}
/*无需关注列数,一起平分#parent*/
.column{flex: 1;}
.column:nth-child(odd){background-color: #f00;}
.column:nth-child(even){background-color: #0f0;}

原理:flex设置排列方式、对齐方式罢了,请查阅文末flex阅读推荐

优缺点

优点:简单灵活;功能强大 缺点:PC端兼容性不好,移动端(Android4.0+) flex务必带上兼容,写法请参考文末阅读推荐,也可以使用autoprefixer

(4)使用Grid实现

html代码:

<body>
<div id="parent">
    <div class="column">1 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">2 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">3 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">4 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">5 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">6 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
</div>
</body>

css代码:

#parent {
    height: 500px;
    display: grid;
    grid-template-columns: repeat(6,1fr);  /*6就是列数*/
}
.column{}
.column:nth-child(odd){background-color: #f00;}
.column:nth-child(even){background-color: #0f0;}

原理:css grid布局,请查看文末的阅读推荐

优缺点

优点:灵活划分网格区域;新型布局利器,适用于页面三维布局 缺点:兼容性不好,移动端(Android5.0+)

6.2 九宫格布局

效果图:

image.png

(1)使用table实现▲

html代码:

<body>
<div id="parent">
    <div class="row">
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
    </div>
    <div class="row">
        <div class="item">4</div>
        <div class="item">5</div>
        <div class="item">6</div>
    </div>
    <div class="row">
        <div class="item">7</div>
        <div class="item">8</div>
        <div class="item">9</div>
    </div>
</div>
</body>

css代码:

#parent {
    width: 1200px;
    height: 500px;
    margin: 0 auto;
    display: table;
}
.row {display: table-row;}
.item {
    border: 1px solid #000;
    display: table-cell;
}

原理:CSS Table以表格的形式显示

优缺点:

优点:代码简单;容易理解;适用于宽度高度未知情况;兼容性好(ie8+) 缺点:margin失效;设置间隔比较麻烦;设置tabl-cell的元素,宽度和高度的值设置百分比无效,需要给它的父元素设置display: table; 才生效;table-cell不感知margin,在父元素上设置table-row等属性,也会使其不感知height;设置float或position会对默认布局造成破坏,可以考虑为之增加一个父div定义float等属性;内容溢出时会自动撑开父元素

(2-1)使用flex实现

html代码:

<body>
<div id="parent">
    <div class="row">
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
    </div>
    <div class="row">
        <div class="item">4</div>
        <div class="item">5</div>
        <div class="item">6</div>
    </div>
    <div class="row">
        <div class="item">7</div>
        <div class="item">8</div>
        <div class="item">9</div>
    </div>
</div>
</body>

css代码:

#parent {
    width: 1200px;
    height: 500px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
}
.row {
    display: flex;
    flex: 1;
}
.item {
    flex: 1;
    border: 1px solid #000;
}

原理:flex设置排列方式、对齐方式罢了,请查阅文末flex阅读推荐

优缺点

优点:简单灵活;功能强大 缺点:每三个一行,对于动态创建不确定数量的元素要控制好嵌套结构,PC端兼容性不好,移动端(Android4.0+) flex务必带上兼容,写法请参考文末阅读推荐,也可以使用autoprefixer

(2-2)flex优化版(不需要遵守三个嵌套一行)

image.png

html代码:

<body>
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>
</body>

css代码:

* {
    margin: 0;
    padding: 0;
}
ul {
    width: 100%;
    background-color: #ccc;
    list-style: none;
    display: flex;
    flex-wrap: wrap;
}
ul > li {
    width: 33.333333333333%;
    height: 100px;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    border: 1px solid #000;
}

原理:父元素flex并设置换行,子元素不设置伸缩,转而定宽设置宽三分之一,高度自定义,计算好宽度即能实现九宫格布局(也可以多列等宽布局)

优缺点

优点:简单;功能强大;不需要额外的嵌套关系,灵活运用于动态创建数量不等的元素布局中; 缺点:高度需要自定无法等宽,PC端兼容性不好,移动端(Android4.0+) flex务必带上兼容,写法请参考文末阅读推荐,也可以使用autoprefixer

(2-3)flex再优化版(高度等宽九宫格)

image.png

html代码:

<body>
<ul>
    <li>
        <span>1</span>
    </li>
    <li>
        <span>1</span>
    </li>
    <li>
        <span>1</span>
    </li>
    <li>
        <span>1</span>
    </li>
</ul>
</body>

css代码:

*{
    margin: 0;
    padding: 0;
}
ul{
    width: 100%;
    margin: 0 auto;
    background-color: #ccc;
    list-style: none;
    display: flex;
    flex-wrap: wrap;
}
ul>li{
    width: 33.33333%;
    padding-top: 33.33333%;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    border: 1px solid #000;
    position: relative;
    height: 0;
}
ul>li>span{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: #999;
}

原理:无法实现高度等宽的原因是因为宽度根据百分比而定,无法通过px去确定高度,又由于padding,width,margin这些百分比都是相对于父元素宽度的,那么只要padding-top或者padding-bottom和width的百分比一样,就能实现一个元素宽高相等,同时利用子绝父相,让子元素占满这个盒子就实现正方形的效果了,此处的span换成img同样可行,这个特性同时也适用于之前介绍的布局(比如float…)。单纯一个正方形效果,除去flex,兼容ie8+

优缺点

优点:简单;功能强大;高度等宽;不需要额外的嵌套关系,灵活运用于动态创建数量不等的元素布局中 缺点:PC端兼容性不好,移动端(Android4.0+) flex务必带上兼容,写法请参考文末阅读推荐,也可以使用autoprefixer

(3)使用Grid实现

CSS Grid非常强大,可以实现各种各样的三维布局,可查阅本文结尾的阅读推荐

html代码:

<body>
<div id="parent">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
    <div class="item">7</div>
    <div class="item">8</div>
    <div class="item">9</div>
</div>
</body>

css代码:

#parent {
    width: 1200px;
    height: 500px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: repeat(3, 1fr); /*等同于1fr 1fr 1fr,此为重复的合并写法*/
    grid-template-rows: repeat(3, 1fr);  /*等同于1fr 1fr 1fr,此为重复的合并写法*/
}
.item {border: 1px solid #000;}

6.3 栅格系统▲

优缺点:

优点:代码简洁,容易理解;提高页面内容的流动性,能适应多种设备; 缺点:浮动脱离文档流,需要清除浮动;由于是百分比平分宽度不能设置margin,否则占位超出父元素宽度换行显示

(1)用Less生成

/*生成栅格系统*/
@media screen and (max-width: 768px){
  .generate-columns(12);     /*此处设置生成列数*/
  .generate-columns(@n, @i: 1) when (@i <= @n) {
    .column-xs-@{i} {
      width: (@i * 100% / @n);
    }
    .generate-columns(@n, (@i+1));
  }
}
@media screen and (min-width: 768px){
  .generate-columns(12);    /*此处设置生成列数*/
  .generate-columns(@n, @i: 1) when (@i <= @n) {
    .column-sm-@{i} {
      width: (@i * 100% / @n);
    }
    .generate-columns(@n, (@i+1));
  }
}
div[class^="column-xs-"]{
    float: left;
}
div[class^="column-sm-"]{
    float: left;
}

编译后的CSS代码:

@media screen and (max-width: 768px) {
  .column-xs-1 {  width: 8.33333333%;  }
  .column-xs-2 {  width: 16.66666667%;  }
  .column-xs-3 {  width: 25%;  }
  .column-xs-4 {  width: 33.33333333%;  }
  .column-xs-5 {  width: 41.66666667%;  }
  .column-xs-6 {  width: 50%;  }
  .column-xs-7 {  width: 58.33333333%;  }
  .column-xs-8 {  width: 66.66666667%;  }
  .column-xs-9 {  width: 75%;  }
  .column-xs-10 {  width: 83.33333333%;  }
  .column-xs-11 {  width: 91.66666667%;  }
  .column-xs-12 {  width: 100%;  }
}
@media screen and (min-width: 768px) {
  .column-sm-1 {  width: 8.33333333%;  }
  .column-sm-2 {  width: 16.66666667%;  }
  .column-sm-3 {  width: 25%;  }
  .column-sm-4 {  width: 33.33333333%;  }
  .column-sm-5 {  width: 41.66666667%;  }
  .column-sm-6 {  width: 50%;  }
  .column-sm-7 {  width: 58.33333333%;  }
  .column-sm-8 {  width: 66.66666667%;  }
  .column-sm-9 {  width: 75%;  }
  .column-sm-10 {  width: 83.33333333%;  }
  .column-sm-11 {  width: 91.66666667%;  }  
  .column-sm-12 {  width: 100%;  }
}
div[class^="column-xs-"]{
    float: left;
}
div[class^="column-sm-"]{
    float: left;
}

★本章小结:

  • 对于多列等宽布局,目前常用的还是浮动,宽度按百分比去平分。要是百分比的话就不太好设置margin,只能用padding去模拟间隔。又或者是固定宽度,计算好间隔,刚好填满或接近填满,这样倒是可以直接设置margin;
  • 除了浮动,其实还可以用到inline-block,但是要注意html换行或空格都会占位,有可能导致空间不够换行显示,这样就要给父元素设置一个font-size:0,然后再给设置inline-block的盒子设置所需要大小的font-size;
  • 然后就是css table布局了,想划分多少列都可以,灵活简单,就是一些不感知属性要注意;
  • 移动端兼容性允许的情况下能用flex就用flex,务必带上兼容,写法可参考文末阅读推荐,也可以使用Autoprefixer;

AXIHE / 精选资源

浏览全部教程

面试题

学习网站

前端培训
自己甄别

前端书籍

关于朱安邦

我叫 朱安邦,阿西河的站长,在杭州。

以前是一名平面设计师,后来开始接接触前端开发,主要研究前端技术中的JS方向。

业余时间我喜欢分享和交流自己的技术,欢迎大家关注我的 Bilibili 和抖音。

关注我: Github / 知乎

如果你加我的私人微信,麻烦写上您的 称呼,所在地区,职业,方便我备注,谢谢


本站的微信公众号

阿西河前端教程

Anbang

Bilibili(B站)

朱安邦

Anbang