本文系统梳理CSS盒模型及盒模型布局。详细讲解内容盒模型与边框盒模型异同,系统讲解BFC创建条件及应用,系统讲解Flex布局新老版本,详解flex属性值,简单总结grid布局及案例,另外通过案例快速了解掌握table布局。
li与li之间为什么有空白?如何解决margin不生效的问题吗?如何解决?flex属性有哪些快捷值,分别是什么含义?flex画骰子grid吗说说它与flex的异同table布局带着问题从文中找答案吧
什么是盒模型?
盒子从内到外由内容(Content)、内边距(Padding)、边框(Border)和外边距(Margin)组成,如下图:

margin border padding 是盒模型的一部分内容盒模型
content)的width/height=我们设置的width/height;width/height+padding+border+margin边框盒模型
box-sizing: border-box (起源IE的bug 怪异模式)padding+边框border宽度=我们设置的width(height也是如此)width/height + margin = 内容区宽度/高度 + padding + border + margin盒主要包括了块盒、行内盒、匿名盒(没有名字不能被选择器选中的盒)以及一些实验性的盒(未来可能添加到规范中)。盒的类型由display属性决定。
display的值为block、table或者list-item的元素是块级元素(block level element),它们会生成块级盒子(block level box)并且参加块级格式化上下文(Block Formatting Context,BFC)。
块级盒行为如下:
width 和 height 属性可以发挥作用display的值为inline
内联盒子行为如下
width 和 height 属性将不起作用。display有一个特殊的值inline-block,它在内联和块之间提供了一个中间状态。(对外inline特性对内block特性)
这对于以下情况非常有用: 您不希望一个项切换到新行,但希望它可以设定宽度和高度,并避免上面看到的重叠。
它的行为如下:
width 和height 属性会生效。padding, margin, 以及border 会推开其他元素。浏览器会把inline内联元素之间的空白字符(空格、换行、Tab)等渲染成一个空格。为了美观通常换成一行,会占用一个字符的宽度

解决办法:
float:left
font-size:0。
letter-spacing:-8px,
letter-spacing:normal。定义: 在CSS中,两个或多个毗邻的普通流中的盒子(父子关系、祖先关系、兄弟元素)在垂直方向上的外边距会发生叠加,这种形成的外边距称之为外边距叠加
padding、border、clear和line-box分隔开。float、absolutely positioned和root element时就是in flowroot-element 即 display: flow-root参考资料:
What?
BFC(Block Formatting Context)块级格式化上下文,是Web页面中盒模型布局的CSS渲染模式,指一个独立的渲染区域或者说是一个隔离的独立容器。
首先说一下盒模型与BFC之间的关系
BFC 的创建<li>,用来存放项目符号<html>)float 不是 none)position 为 absolute || fixed)display 为 inline-block)display 为 table-cell,HTML表格单元格默认为该值)
display 为 table-caption,HTML表格标题默认为该值)display 为 table、table-row、 table-row-group、table-header-group、table-footer-group(分别是HTML标签 table、row、tbody、thead、tfoot 的默认属性)或 inline-table)overflow 计算值(Computed)不为 visible 的块元素display 值为 flow-root 的元素contain 值为 layout、content 或 paint 的元素display 为 flex 或 inline-flex 元素的直接子元素)display 为 grid 或 inline-grid 元素的直接子元素)column-count 或 column-width(en-US) 不为 auto,包括 column-count 为 1)
column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更,Chrome bug)。
案例:自适应两栏布局
html<!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>
</head>
<style>
*{
margin: 0;
padding: 0;
}
body {
width: 100%;
}
/* 自适应两栏布局 */
.left {
width: 100px;
height: 100px;
float: left;
background: rgb(139, 214, 78);
text-align: center;
font-size: 20px;
}
.right {
height: 200px;
background: rgb(170, 54, 236);
text-align: center;
font-size: 40px;
/* width: 100% */ /* 不要设置宽度,块级元素会宽度自适应 */
overflow: hidden; /* 添加此行代码 */
}
</style>
<body>
<div class="left">LEFT</div>
<div class="right">RIGHT</div>
</body>
</html>
Inline Formatting Contexts,也就是“内联格式化上下文”。

值得注意的是display: inline-block,以单个封闭块来参与外部的 IFC,而内部则生成了一个 BFC
参考资料:
案例:IFC实现元素水平垂直居中
代码如下:
html<!doctype html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<style>
.wrap {
line-height: 300px;
width: 100%;
height: 300px;
background-color: #ccc;
font-size: 0;
}
p {
line-height: normal;
display: inline-block;
vertical-align: middle;
background-color: #333;
font-size: 18px;
padding: 10px;
width: 360px;
color: #fff;
}
</style>
</head>
<body>
<div class="wrap">
<p>
外部 height = line-height <br>
内部是IFC布局,使用vertical-align:middle方法来实现文本垂直居中
</p>
</div>
</body>
</html>
运行效果

关于flex语法,建议先看阮一峰老师的《flex语法篇》 , 接着再看他的《Flex布局教程:实例篇》,最后在看我这里的总结。 由于阮老师文章比较早,部分flex相关属性的值不全,以下内容既是我的总结,也有我对flex布局知识的补充和完善。
flex记忆 心法口诀
flex后 项目的float vertical-align clear属性会失效。flex-direction 决定主轴的方向
row | row-reverse | column | column-reverseflex-wrap 是否允许换行
nowrap | wrap | wrap-reverseflex-flow flex-direction 和 flex-wrap 的简写justify-content 定义项目在主轴的对齐方式(默认横轴为主轴,随flex-direction改变)
flex-start | flex-end | center | start | end| stretch | space-between | space-around | space-evenly |left | right | normalalign-items 定义项目在交叉轴的对齐方式
stretch | flex-start | flex-end | center | start | end | normal | baseline | self-start | self-endalign-content 定义了多根轴线的对齐方式,如果只有一根则不起作用
stretch| flex-start | flex-end | center | start | end | space-between | space-around| space-evenly| normal | baselineorder 定义项目的排列 数值越小排列越靠前,默认值为0flex-grow 定义项目的放大比例 默认0,即如果存在剩余空间也不放大flex-shrik 定义项目的缩小比例 默认1, 0表示不缩小flex-basis 在分配多余空间之前,项目占据的主轴空间,默认值为auto,即项目分身大小
auto | content | fit-content | max-content | min-contentflex 以上三个属性的简写,默认值 0 1 auto, 建议优先使用这个值
auto 1 1 auto | none 0 0 autoalign-self 允许单个项目与其他项目有不一样的对齐方式, 可覆盖align-items属性,默认值auto
auto | flex-start | flex-end | start | end | center | stretch | baseline | self-start | self-end
参考资料 这里

这个效果翻译成文字: 如果您希望项目与 flex-direction 定义的 end 对齐,请使用 flex-end。要将其与对齐容器的末端对齐,请使用 end
self-start会受到到 direction属性的影响

start会受到 direction属性的影响,如下图 direction: rtl;

参考资料:https://stackoverflow.com/questions/57720598/what-is-the-default-value-of-justify-content
大概意思是:
justify-content justify-items justify-self align-content align-items align-self 都有该属性值老实说我一直不愿意学老版flex, 觉得它是被淘汰的东西,但是有个东西,多行文本溢出省略号只能又该来实现,另外它也可以实现一些布局(如水平垂直居中),所以它并没有被淘汰,还是要去了解它。
css.multi-lines {
display: -webkit-box;
overflow: hidden;
word-break: break-all;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
flexbox布局的语法规范经过几年发生了很大的变化。从2007年07月,flex第一版本的工作草案发布,到2012年09月,flex最新版本成为候选推荐。flex主要经历了三个版本
display:box | inline-box;display:flexbox | inline-flexbox;

display: flex | inline-flex
IE11+、firefox、safari、chrome、opera及移动端,但移动端ios7.1-8.4需要添加前缀-webkit-综上现在还要需学一下 display: box即可,可能是因为display:box是草案,没有最终成为标准, 所以需要加浏览器前缀display: -webkit-box
容器属性
box-orient 确定容器内项目的排列方向 有一点点像 flex-direction
horizontal | vertical | inline-axis | block-axisbox-direction 确定项目的排列顺序 有一点点像 flex-direction
normal | reversebox-align 项目在交叉轴上的对齐方式 类似 align-items
start | end | center | baseline | stretchbox-pack 项目在主轴上的对齐方式 类似justify-contentbox-lines 容器内的项目是否换行 不生效
single | multiple项目属性
box-flex 项目的分配权重 类似flex属性box-ordinal-group 项目的排列优先级 类似 order属性
html<!doctype html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<style>
.box {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-align: center;
-webkit-box-pack: center;
height: 200px;
width: 300px;
color: white;
background-color: #eee;
}
.child {
height: 100px;
width: 100px;
background-color: gray;
padding: 10px;
}
</style>
</head>
<body>
<div class="box">
<div class="child">-webkit-box实现水平垂直居中</div>
</div>
</body>
</html>
Grid布局与Flex具有一定的相似性,都可以指定容器内部多个项目的位置。但是他们也有重大区别。
Grid布局远比Flex强大。
Grid布局入门推荐先看阮老师的《CSS Grid 网格布局教程》,以下内容是个人总结。
float、display:inline-block、display:table-ceil、 vertical-align和column-*等设置都将失效grid-template-columns、grid-template-rows 属性划分行和列,定义每一个列的列宽和每一行的行高
repeat() 简化重复的值 如 repeat(3, 33.33%)、 repeat(2, 10px 20px 8px)auto-fill 有的单元格大小是固定的但容器的大小不是固定的,希望每一行(列)尽可能容纳更多的单元格fr 为了方便表示比例关系minmax() 产生一个长度范围,表示长度就在这个范围内 如minmax(100px, 1fr) 表示不小于100px 不大于1frauto 该行或列的长度自适应grid-template-rows: [c1] 100px [c2] 100px [c3]
grid-row-gap grid-column-gap 设置行与行列与列的间隔
row-gap column-gapgrid-template-areas属性及项目的grid-column grid-row grid-area使用grid-template-areas 网格布局允许指定区域,一个区域有一个或多个单元格组成,该属性用于定义区域。
grid-template-areas: 'a b' 'c d';grid-template-areas: 'header header header' 'sidebar main main' 'footer footer footer';grid-template-areas: 'a.' '. .'; 某些区域不需要利用则用.表示grid-auto-flow 指定项目的排列方式, row 先行后列 colmn先列后行
row | column | row dense | column densejustify-items、align-items、place-items
align-items 设置单元格内容的垂直对齐方式 属性值同Flex布局的align-itemsjustify-items 设置单元格水平对齐位置 属性值同 Flex的justity-items 此外还有三个值 left right legacyplace-items <justify-items> <align-items>justify-content align-content place-content
place-content属性值同Flex布局的justify-content align-contentgrid-auto-columns、grid-auto-rows
grid-template 是 grid-template-columns grid-template-rows grid-template-areas的合并简写方式grid 是 grid-template-rows、grid-template-columns、grid-template-areas、grid-auto-rows、grid-auto-columns、grid-auto-flow 的合并简写形式grid-column-start、grid-column-end、grid-row-start、 grid-row-end、grid-column grid-row
grid-column 是 grid-column-start和grid-column-end的简写grid-row 是 grid-row-start和 grid-row-end的简写grid-area <row-start>/<column-start>/<row-end>/<column-end>justify-self、align-self、 place-items
justify-items align-items place-items 一一对应
html<!doctype html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.p {
height: 150px;
width: 300px;
background-color: #888888;
display: grid;
grid-template-columns: repeat(3, 80px);
grid-template-rows: repeat(3, 32px);
/* grid-template-areas 也是一种方式*/
place-content: space-around space-evenly;
}
.item {
background-color: #ffffff);
}
.item1 {
grid-column-start: 2 span;
grid-row-start: 2 span;
background-color: rgb(162, 62, 55);
}
.item2 {
background-color: rgb(87, 166, 164);
}
.item3 {
background-color: rgb(80, 151, 125);
}
.item4 {
grid-column-start: 3;
grid-column-end: 4;
grid-row-start: 2;
grid-row-end: 4;
background-color: rgb(101, 74, 139);
}
.item5 {
background-color: rgb(204, 116, 60);
}
</style>
</head>
<body>
<div class="p">
<div class="item item1"></div>
<div class="item item2"></div>
<div class="item item3"></div>
<div class="item item4"></div>
<div class="item item5"></div>
</div>
</body>
</html>
表格布局,尝试用css画一个table标签布局

由上图可知<colspan> <rowspan>CSS模拟不了
html<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<table border="1px" style="border-spacing: 0;">
<caption>这是表格的标题</caption>
<colgroup>
<col width="100">
<col width="200">
<col width="60">
</colgroup>
<thead>
<tr>
<th>col名称</th>
<th>官网</th>
<th>性质</th>
</tr>
</thead>
<tbody>
<tr>
<td>C语言中文网</td>
<td>http://c.biancheng.net/</td>
<td>教育</td>
</tr>
<tr>
<td colspan="2">当当http://www.dangdang.com/</td>
<td>图书</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>名称</th>
<th>官网</th>
<th>性质</th>
</tr>
</tfoot>
</table>
<section border="1px" class="table-box" style="display:table;">
<div style="display:table-caption;text-align: -webkit-center;">CSS模拟table标签</div>
<div style="display: table-column-group;">
<span style="display: table-column;width:auto" width="100"></span>
<span style="display: table-column;width:200px" width="200"></span>
<span style="display: table-column;width:60px" width="60"></span>
</div>
<div style="display:table-header-group;" class="thead">
<div style="display:table-row;text-align: -webkit-center;">
<span style="display: table-cell;">名称</span>
<span style="display: table-cell;">官网</span>
<span style="display: table-cell;">性质</span>
</div>
</div>
<div style="display:table-row-group;" class="tbody">
<div style="display:table-row">
<span style="display: table-cell;">C语言中文网</span>
<span style="display: table-cell;">http://c.biancheng.net/</span>
<span style="display: table-cell;">教育</span>
</div>
<div style="display:table-row">
<span style="display: table-cell;">当当</span>
<span style="display: table-cell;">http://www.dangdang.com/</span>
<span style="display: table-cell;">图书</span>
</div>
</div>
<div style="display:table-footer-group" class="tfoot">
<div style="display:table-row;text-align: -webkit-center;">
<span style="display: table-cell;">名称</span>
<span style="display: table-cell;">官网</span>
<span style="display: table-cell;">性质</span>
</div>
</div>
</section>
<style>
.table-box {
margin-top: 40px;
border: 1px solid grey;
border-collapse: separate;
text-indent: initial;
border-spacing: 0;
}
.table-box span {
border: 1px solid gray;
vertical-align: inherit;
}
.table-box .tbody {
vertical-align: middle;
border-color: inherit;
}
.table-box .thead, .table-box .tfoot {
vertical-align: middle;
border-color: inherit;
}
.table-box .thead span, .table-box .tfoot span {
font-weight: bold;
}
</style>
</body>
</html>
display:table系列值几乎是和<table>标签系列 相对应,请看下表

<table>元素时,它需要先计算和渲染整个表格结构,以确定每个单元格的大小和位置,然后才能继续渲染后续的内容。<table>元素时,需要处理完整个表格结构,当表格结构比较复杂或数据量大时就会阻塞后续内容的渲染。参考资料
本文作者:郭敬文
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!