本文系统梳理CSS
盒模型及盒模型布局。详细讲解内容盒模型与边框盒模型异同,系统讲解BFC
创建条件及应用,系统讲解Flex
布局新老版本,详解flex
属性值,简单总结grid
布局及案例,另外通过案例快速了解掌握table
布局。
li
与li
之间为什么有空白?如何解决margin
不生效的问题吗?如何解决?flex
属性有哪些快捷值,分别是什么含义?flex
画骰子grid
吗说说它与flex
的异同table
布局带着问题从文中找答案吧
什么是盒模型?
盒子从内到外由内容(Content
)、内边距(Padding
)、边框(Border
)和外边距(Margin
)组成,如下图:
margin
border
pading
是盒模型的一部分内容盒模型
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 flow
root-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-reverse
flex-wrap
是否允许换行
nowrap
| wrap
| wrap-reverse
flex-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
| normal
align-items
定义项目在交叉轴的对齐方式
stretch
| flex-start
| flex-end
| center
| start
| end
| normal
| baseline
| self-start
| self-end
align-content
定义了多根轴线的对齐方式,如果只有一根则不起作用
stretch
| flex-start
| flex-end
| center
| start
| end
| space-between
| space-around
| space-evenly
| normal
| baseline
order
定义项目的排列 数值越小排列越靠前,默认值为0flex-grow
定义项目的放大比例 默认0,即如果存在剩余空间也不放大flex-shrik
定义项目的缩小比例 默认1, 0表示不缩小flex-basis
在分配多余空间之前,项目占据的主轴空间,默认值为auto,即项目分身大小
auto
| content
| fit-content
| max-content
| min-content
flex
以上三个属性的简写,默认值 0 1 auto
, 建议优先使用这个值
auto
1 1 auto
| none
0 0 auto
align-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.muti-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-axis
box-direction
确定项目的排列顺序 有一点点像 flex-direction
normal
| reverse
box-align
项目在交叉轴上的对齐方式 类似 align-items
start
| end
| center
| baseline
| stretch
box-pack
项目在主轴上的对齐方式 类似justify-content
box-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-gap
grid-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 dense
justify-items
、align-items
、place-items
align-items
设置单元格内容的垂直对齐方式 属性值同Flex布局的align-items
justify-items
设置单元格水平对齐位置 属性值同 Flex的justity-items
此外还有三个值 left
right
legacy
place-items
<justify-items
> <align-items
>justify-content
align-content
place-content
place-content
属性值同Flex布局的justify-content
align-content
grid-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 许可协议。转载请注明出处!