CSS常见布局大汇总

  此文包括的布局类型有:未知宽高元素的水平垂直居中、 两栏等高、两栏布局、三栏布局(包括双飞翼布局和圣杯布局),三栏布局之固定高度中间自适应,除了代码外,还有笔者的一点个人理解,若是有所错误或不足的,欢迎大家指出!

未知宽高元素的水平垂直居中

"container">
"ele">hello world
为了便于观察,先设置一些css样式: .container { width: 200px; height: 200px; background-color: #eee; } .ele { background-color: rgb(179, 174, 174); } 复制代码

将下面任一种方法的css样式分别添加到上面的代码中,都能得到下图这个效果。

方法一:绝对定位 + 平移

.contaienr {
  position: relative;
}
.ele {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  // 若宽高已知,还可以使用margin-left,margin-right代替
}
复制代码
// 若是ele指定了宽高,还可以设置距上下左右都为0再自动间隔
// 若没有设置宽高就直接使用的话,ele的宽高都会是父元素的100%
.ele {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  margin: auto;
  width: 100px;
  height: 100px;
}
复制代码

方法二:tabel布局

.container {
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}
.ele {
  display: inline-block;  // 可选,若不加则ele的宽度将是父元素的100%
}
复制代码

方法三: flex布局

.container {
  display: flex;
  justify-content: center;
  align-items: center;
}
复制代码

两栏等高

padding内补偿法

"box">
"left">

左浮动

左浮动

左浮动

"right">

也是左浮动

也是左浮动

也是左浮动

也是左浮动

也是左浮动

也是左浮动

.box { overflow: hidden; } .left { width: 50px; float: left; background-color: yellow; padding-bottom: 2000px; margin-bottom: -2000px; } .right { width: 100px; float: left; background-color: red; padding-bottom: 2000px; margin-bottom: -2000px; } 复制代码

两栏等高的原理是,给每一栏都设置一个很大的padding-bottom的值,以此来弥补高度较小的那一栏。再使用一个等大的负的margin-bottom来收缩,正如我在另一篇文章里我解释的,使用负margin-bottom收缩后,虽然元素自身的宽高没有改变,但它的元素框会随着减小,最终元素框的高度取决于两栏中较高一栏。这时如果给它们的父元素添加overflow: hidden,则会隐藏掉溢出元素框的部分内容,于是就达到了高度较低的一栏和较高的一栏等高的效果。

但是使用padding内补偿法有一个缺陷,如果每一栏设置了border的话,因为每一栏的高被padding撑高而且隐藏了超出的内容,所以border-bottom是显示不出来的。解决办法是,再在每一栏的最后一个子元素设置一个div来模仿border-bottom。记得还要给父元素box设置为相对定位,才能让伪border-bottom定位到那一栏的底部。

.border {
  width: 52px;
  height: 2px;
  background-color: blue;
  position: absolute;
  bottom: 0;
}

复制代码

使用div模仿border-bottom还是有一个限制,就是必须先设置好那一栏的宽度,才好给border设置width。使用width: calc(100% + 2px)是没用的,因为每一栏都没有相对定位,所以100%是参考box而言的。如果要给每一栏设置相对定位,则border的绝对定位是相对于每一栏而言的,显示的边框又会被隐藏掉了。

tabel布局

利用表格(table)中每个单元格(table-cell)等高的特性

// IE8以下不支持
.box { 
  display: table;
  overflow: hidden;
}
.left {
  width: 50px;
  background-color: yellow;
  display: table-cell;
}
.right {
  width: 100px;
  background-color: red;
  display: table-cell;
}
复制代码

flex布局

.box {
  display: flex;
}
.left {
  background-color: blue;
  width: 100px;
}
.right {
  background-color: yellow;
}
复制代码

js / jq动态设置

在js代码里去获取box里每一栏的高度并取它们的最大值,再将每一栏的高度设置为该最大值。但这不可避免会操作到DOM,难免对性能造成影响。

两栏布局

左栏固定宽度,右栏自适应。

利用负margin

实现逻辑请看盒模型和负margin这篇文章里的解释。


"box">
"slider">

slider

"content">

content

content

content

content

.box { overflow: hidden } .slider { float: left; width: 100px; height: 200px; background-color: blue; } .content { float: left; width: 100%; height: 200px; background-color: yellow; margin-right: -100px; } .content p { margin-right: 100px; } 复制代码

"box">
"content">

content

content

content

content

"slider">

slider

.slider { float: left; width: 100px; height: 200px; background-color: blue; margin-left: -100%; } .content { float: left; width: 100%; height: 200px; background-color: yellow; } .content p { margin-left: 100px; } 复制代码

绝对定位

两栏都绝对定位并使用calc计算自适应那一栏的宽度

"box">
"slider">

slider

"content">

content

content

content

content

.box { position: relative; } .slider { width: 100px; height: 200px; background-color: blue; position: absolute; left: 0; } .content { width: 100%; height: 200px; background-color: yellow; position: absolute; left: 100px; } 复制代码

tabel布局

利用表格的宽度等于所有单元格宽度之和的特性

"box">
"slider">

slider

"content">

content

content

content

content

.box { display: table; width: 100%; } .slider { width: 100px; display: table-cell; background-color: blue; } .content { display: table-cell; background-color: yellow; } 复制代码

flex布局

flex大法真香

"box">
"slider">

slider

"content">

content

content

content

content

.box { display: flex; } .slider { background-color: blue; width: 100px; } .content { background-color: yellow; flex: 1; } 复制代码

grid布局

"box">
"slider">

slider

"content">

content

content

content

content

.box { display: grid; grid-template-rows: 100px; grid-template-columns: 100px auto; } .slider { background-color: blue; } .content { background-color: yellow; } 复制代码

三栏布局

跟两栏布局差不多,三栏布局是左右两栏固定宽度,中间栏自适应宽度(即固比固布局)。

浮动

"box">
"left">

我是左导航栏我是左导航栏我是左导航栏

"right">

我是右导航栏我是右导航栏我是右导航栏

"content">
"inner-content">

我是内容主题部分

我是内容主题部分

我是内容主题部分

我是内容主题部分

.content { background-color: blue; } .inner-content { margin-left: 100px; margin-right: 100px; } .left { float: left; width: 100px; background-color: red; } .right { float: right; width: 100px; background-color: yellow; } 复制代码

从效果图中可以看出,使用浮动实现三栏布局在中间栏容纳得下内容时是可以正常工作的,但内容一旦超出,中间栏就会向下扩展。如果给它们指定 height 的话自然就不存在这问题了,不过内容还是会溢出来的(见下图)。当然我们可以选择给外层容器box设置overflow: hidden来隐藏,但如果我们要显示全部内容的话要怎么办?答案是给左中右三个元素使用padding内补偿法,使它们三栏等高。(当浏览器宽度小于左右两栏的宽度和时,右栏会被挤下来,这时要也只能去给 body 设置min-width了,这点跟圣杯布局一样)。

绝对定位

"box">
"left">

我是左导航栏我是左导航栏我是左导航栏

"content">
"inner-content">

我是内容主题部分

我是内容主题部分

我是内容主题部分

我是内容主题部分

"right">

我是右导航栏我是右导航栏我是右导航栏

.box { position: relative; } .content { background-color: blue; } .inner-content { margin-left: 100px; margin-right: 100px; } .left { width: 100px; background-color: red; position: absolute; left: 0; top: 0; } .right { width: 100px; background-color: yellow; position: absolute; right: 0; top: 0; } 复制代码

也存在内容大于中间栏宽度,中间栏会向下扩展的问题。

flex布局

"box">
"left">

我是左导航栏我是左导航栏我是左导航栏

"content">
"inner-content">

我是内容主题部分

我是内容主题部分

我是内容主题部分

我是内容主题部分

"right">

我是右导航栏我是右导航栏我是右导航栏

.box { display: flex; } .content { background-color: blue; flex: 1; } .left { width: 100px; background-color: red; } .right { width: 100px; background-color: yellow; } 复制代码

对高度会自适应,内容超出时三栏会自动调整高度。

tabel布局

"box">
"left">

我是左导航栏我是左导航栏我是左导航栏

"content">
"inner-content">

我是内容主题部分

我是内容主题部分

我是内容主题部分

我是内容主题部分

"right">

我是右导航栏我是右导航栏我是右导航栏

.box { display: table; width: 100%; } .content { background-color: blue; display: table-cell; } .left { width: 100px; background-color: red; display: table-cell; } .right { width: 100px; background-color: yellow; display: table-cell; } 复制代码

对高度会自适应,内容超出时三栏会自动调整高度。

grid布局

"box">
"left">

我是左导航栏我是左导航栏我是左导航栏

"content">
"inner-content">

我是内容主题部分

我是内容主题部分

我是内容主题部分

我是内容主题部分

"right">

我是右导航栏我是右导航栏我是右导航栏

.box { display: grid; grid-template-columns: 100px auto 100px; } .content { background-color: blue; } .left { background-color: red; } .right { background-color: yellow; } 复制代码

对高度会自适应,内容超出时三栏会自动调整高度。

双飞翼布局

"box">
"content">
"inner-content">

我是内容主题部分

我是内容主题部分

我是内容主题部分

我是内容主题部分

我是内容主题部分

我是内容主题部分

我是内容主题部分

我是内容主题部分

"left">

我是左导航栏我是左导航栏我是左导航栏

"right">

我是右导航栏我是右导航栏我是右导航栏

.left { width: 100px; height: 100px; background-color: red; float: left; margin-left: -100%; } .right { width: 100px; height: 100px; background-color: yellow; float: left; margin-left: -100px; } .content { width: 100%; height: 100px; float: left; background-color: blue; } .inner-content { margin-left: 100px; margin-right: 100px; } 复制代码

同样是使用浮动,但双飞翼布局是对负margin的应用,实现详情请看负margin实现两栏布局。同样的是,在HTML代码部分也是把content放到left和right前面的优先渲染 ,否则left放前面的话会造成left被content覆盖或是内容超出视图,也存在前面的那两个问题。听说双飞翼布局是淘宝创造的?

圣杯布局

"box">
"content">
"inner-content">

我是内容主题部分

我是内容主题部分

我是内容主题部分

我是内容主题部分

"left">

我是左导航栏我是左导航栏我是左导航栏

"right">

我是右导航栏我是右导航栏我是右导航栏

body { min-width: 400px; } .box { padding: 0 100px 0 100px; } .left { width: 100px; height: 100px; background-color: red; float: left; margin-left: -100%; position: relative; left: -100px; } .right { width: 100px; height: 100px; background-color: yellow; float: left; margin-left: -100px; position: relative; right: -100px; } .content { width: 100%; height: 100px; float: left; background-color: blue; } 复制代码

圣杯布局和双飞翼布局同样是对负margin的应用,区别在于解决中间栏内容不被左右侧边栏遮挡的方法不同。双飞翼布局是直接给content设置一个子div,利用margin-left和margin-right来间隔开彼此。而圣杯布局给父容器box设置padding来间隔开content主体内容和左右的距离,再给左右两栏分别相对定位设置left和right使其回到原先的位置。圣杯布局潜在的问题是,但浏览器缩小到一定程度后,左右两栏会被挤下来,不过可以给body设置min-width来解决这个问题。个人比较推荐双飞翼布局,两者实现的效果是一样的,而圣杯布局又要用到相对定位甚至min-width,为什么不简单点直接用margin解决同样的问题呢,不仅思路简单些代码也简洁。

三栏布局总结

  • 普通的浮动布局和双飞翼布局圣杯布局: 在 HTML 代码上普通的浮动是把中间栏放到最后,左右两栏分别左右浮动后中间空出来的空间给中间栏。而双飞翼布局和圣杯布局是把中间栏放在最前面使其先渲染,让三栏都左浮动后再利用左栏margin-left: -100%,右栏margin-left: -100px使其都并排布局。   因为普通浮动里是把中间栏放到最后才渲染的,所以当页面内容较多时可能会影响用户体验。

  • 对高度的适应性: 如果没有设置高度,flex布局,table布局,grid布局对三栏的高度变化有适应性,即使内容超出了三栏会都自动扩大自身高度来适应。而浮动和绝对定位两种方法内容一旦超出,中间栏则会向下扩展,双飞翼布局也一样有这问题,可以直接设置height来避免这问题。或者使用padding内补偿法使三栏都等高。

  • 局限性: 浮动和绝对定位脱离文档流,需要处理好和其他元素的位置关系,不过兼容性比较好。

  flex布局和grid布局是新生的布局方式,功能强大对高度的适应性好,但对浏览器的兼容性不是很好。

  table布局适应性好,对浏览器的兼容性也好,但table布局好像一直受人诟病,似乎毛病很多?我没在项目里用到过,也不知道真假。

三栏布局之固定高度中间自适应

上下固定高度,中间自适应。都需要使用overflow: scroll来使中间栏溢出的部分在内部滚动,否则中间栏会扩展自身高度把底栏挤出视图,这我也不知道有什么更好的解决办法了。

绝对定位

"box">
"top">

我是头部

我是头部

我是头部

我是头部

"content">
"inner_content">

我是内容主题部分

我是内容主题部分

我是内容主题部分

我是内容主题部分

我是内容主题部分

我是内容主题部分

"bottom">

我是底部

我是底部

我是底部

.box { width: 100%; height: 100vh; position: relative; } .content { width: 100%; height: 100%; background-color: blue; overflow: scroll; } .top { width: 100%; height: 100px; background-color: red; position: absolute; left: 0; top: 0; } .bottom { width: 100%; background-color: yellow; position: absolute; left: 0; bottom: 0; } .inner_content { padding-top: 100px; } 复制代码

此处使用绝对定位有一个局限,需要事先知道顶部栏的高度,才好给中间栏的内容部分设置padding-top,否则内容会被顶部栏遮住。对于中间栏需要使用overflow: scroll来使溢出部分在中间栏里滚动,否则中间栏会向下扩展。

flex布局

"box">
"top">

我是头部

我是头部

我是头部

"content">
"inner_content">

我是内容主题部分

我是内容主题部分

我是内容主题部分

我是内容主题部分

"bottom">

我是底部

我是底部

我是底部

.box { width: 100%; height: 100vh; display: flex; flex-direction: column; } .content { width: 100%; flex: 1; background-color: blue; overflow: scroll; } .top { width: 100%; background-color: red; } .bottom { width: 100%; background-color: yellow; } 复制代码

中间栏同样需要使用overflow: scroll

grid布局

"box">
"top">

我是头部

我是头部

我是头部

"content">
"inner_content">

我是内容主题部分

我是内容主题部分

我是内容主题部分

我是内容主题部分

"bottom">

我是底部

我是底部

我是底部

.box { width: 100%; height: 100vh; display: grid; grid-template-rows: 100px auto 100px; grid-template-columns: 100%; } .content { background-color: blue; } .top { background-color: red; } .bottom { background-color: yellow; } 复制代码

中间栏同样需要使用overflow: scroll

收官

  笔者暂时只想到这些常见的布局,若是有所缺漏的,欢迎大家指出,笔者会再做补充。

  最后附Blog原文 和 笔者Github,欢迎大家一起交流学习~

转载于:https://juejin.im/post/5c94da60e51d450fd87d6db7

你可能感兴趣的:(CSS常见布局大汇总)