本文总结于张鑫旭老师的《css世界》,个人学习笔记。
CSS流
CSS流,即文档流,实际上是CSS世界中的一种基本的定位和布局机制,元素会按照流体布局自动从左往右,从上而下排列。
块级元素
块级元素(block-level element),与display:block
的元素不是一个概念,其基本特征为:一个水平流上只能单独显示一个元素,多个块级元素则换行显示。
我们知道display:inline-block
的元素既可以和图文一行显示,又可以设置width/height,所以一个块级元素如果只有一个块级盒子控制是否换行显示是不够的,这里我们可以理解为元素由两层盒子控制:外在盒子(块级盒子)负责元素是可以一行显示,还是只能换行显示;内在盒子(容器盒子)负责宽高、内容呈现什么的。
display:inline-block
元素外面的盒子是inline级别,里面的盒子是block级别,按照这种理解,display:block
可以理解为display:block-block
。
width/height
元素都有内外两个盒子,width/height作用在内在盒子,也就是作用在content box容器盒子上。
width:auto与witdh:100%
width
默认值是auto
,width:auto
和width:100%
的区别是什么呢?我们先看一下案例1。
width:auto
具有流动性,所谓流动性,并不是看上去的宽度 100%显示这么简单,而是一种 margin/border/padding和content内容区域自动分配水平空间的机制。一旦设置了宽度,流动性就丢失了,案例中子元素设置了width:100%
,其border会超出父元素,不能自适应。
width:auto
:是子元素的 content+padding+border+margin撑满父元素的 content 区域。
width:100%
:是子元素的 content 撑满父元素的content,如果子元素还有padding、border、margin属性,可能会造成子元素区域溢出显示;
针对上述案例,我们可以重新设置子元素的宽度(减去padding,border,margin宽度),也可以用box-sizing:border-box
解决,更推荐不设置宽度,auto自身有很好的自适应性。
min-width/max-width和min-height/max-height
min-width/max-width min-height/max-height
权重高于!important
,参考案例2-1。
div {
width: 200px !important;
max-width: 150px;
height: 200px !important;
min-height: 300px;
}
此时div宽150px,高300px。
min-width/max-width min-height/max-height
冲突时,取最大值,参考案例2-2。
div {
width: 200px !important;
max-width: 150px;
min-width: 300px;
height: 100px !important;
min-height: 200px;
max-height: 150px;
}
此时div宽300px,高200px。
内联元素
内联元素(inline-level elements),与display:inline
的元素不是一个概念,典型特征就是可以和文字在一行显示。因此,文字是内联元素,图片是内联元素,按钮是内联元素,输入框、下拉框等原生表单控件也是内联元素,内联元素的“内联”特指它的“外在盒子”为“内联盒子”。
幽灵空白节点
内联元素的所有解析和渲染表现就如同每个行框盒子的前面有一个“空白节点”一样。这个“空白节点”永远透明,不占据任何宽度,看不见也无法通过脚本获取,就好像幽灵一样,但又确确实实存在,这就是幽灵空白节点(strut),是一个存在于每个“行框盒子”前面,同时具有该元素的字体和行高属性的 0 宽度的内联盒。参考案例3。
div {
background-color: pink;
}
span {
display: inline-block;
}
<div><span></span></div>
span
标签没有高度,但是div
却有22px高度,背景色起作用了,证明了幽灵空白节点的存在。
盒模型四大属性
content
CSS的content
属性用于在元素的::before
和::after
伪元素中插入内容。使用content
属性插入的内容都是匿名的可替换元素。
根据元素内容是否可替换,可以把元素分为可替换元素和非可替换元素,常见可替换元素有img
,video
,iframe
。可替换元素内容不受当前文档的样式的影响,CSS 可以影响可替换元素的位置,但不会影响到可替换元素自身的内容。某些可替换元素,例如iframe
元素,可能具有自己的样式表,但它们不会继承父文档的样式。
替换元素的一些尺寸计算可见案例4。
padding
padding是给元素设置上下左右四个方向的内边距属性。CSS中box-sizing
默认是content-box
,所以使用padding会增加元素的尺寸,使用border-box
能保证元素尺寸就是width属性设置的宽度吗,案例5-1。
div {
width: 80px;
padding: 20px 60px;
box-sizing: border-box;
}
此时div
宽度为120px,如果padding值足够大,width则不生效,里面的内容表现为“首选最小宽度”(块状元素)。对于内联元素表现有些不同,其内容也占据了宽度。
内联元素padding既会影响水平方向也会影响垂直方向,案例5-2。
a {
padding: 50px;
background-color: pink;
}
此时a
链接的背景显示出来,通过padding,可以增大a
链接点击区域。
块状元素padding百分比都是相对宽度计算的,案例5-3。
div {
width: 300px;
height: 200px;
div {
padding: 20%;
}
}
子div
的padding都是60px。
内联元素的padding会断行,垂直padding会让幽灵空白节点显现,案例5-4。
margin
margin是给元素设置上下左右四个方向的外边距属性。和padding属性一样,margin的百分比值水平方向和垂直方向都是相对于宽度计算的。
margin合并
块级元素的margin-top
和margin-bottom
有时会合并为单个外边距,这种现象称为“margin合并”。
margin合并有两个要素:
- 块级元素,不包括浮动和绝对定位元素。
- 发生在垂直方向(文档流为水平方向的默认前提下)。
margin合并有三种情况,参考案例6:
- 相邻兄弟元素合并,第一行与第二行间距还是10px。
<p>第一行</p>
<p>第二行</p>
p {
margin: 10px;
}
- 父级和第一个/最后一个子元素合并,父div合并了子div的margin-top,也会下沉80px。
<div class="father">
<div class="son">son</div>
</div>
.father {
width: 100px;
background: pink;
}
.son {
margin-top: 80px;
}
- 空块级元素的margin合并,父div高度最终是10px。
<div class="father2">
<div class="son2"></div>
</div>
.father2 {
overflow: hidden;
background: pink;
}
.son2 {
margin: 10px 0;
}
margin:auto
margin:auto
的填充规则如下:
- 如果一侧定值,一侧 auto,则 auto 为剩余空间大小(案例7)。
- 如果两侧均是 auto,则平分剩余空间。
<div class="father">
<div class="son"></div>
</div>
.father {
width: 300px;
height: 200px;
background-color: gray;
}
.son {
width: 200px;
height: 200px;
margin-right: 80px;
margin-left: auto;
background-color: pink
}
auto具有强烈的计算属性,总间距100px,margin-right已经使用了80px,所以margin-left是20px。
如果想让某个块状元素右对齐,可以使用margin-left:auto,可以很好的实现块状元素左中右对齐,和内联元素使用text-align 控制左中右对齐正好遥相呼应!
border
border有很多不同的表现形式,可以巧妙的绘制一些图形,参考案例8。
基线
CSS元素排版、对齐等样式离不开基线,vertical-align
默认属性是baseline,字母x的下边缘就是基线。
vertical-align:middle
这里的 middle 是中间的意思,和上面的 median(中线)不是一个意思,middle 指的是基线往上 1/2 x-height 高度。middle并不是绝对的垂直居中对齐,只是一种近似效果,因为不同的字体在行内盒子中的位置是不一样的。
ex 是 CSS 中的一个相对单位,指的是小写字母 x 的高度,即 x-height。使用ex单位对齐,可以使文字和图标垂直居中,不受字体和字号影响(案例9)。
line-height与vertical-align
line-height
用于设置多行元素的空间量,如多行文本的间距。对于块级元素,它指定元素行盒(line boxes)的最小高度。对于非替换的内联(inline)元素,它用于计算行盒(line box)的高度(10-1)。
line-height
有一个特性,无论内联元素如何设置,最终父级元素的高度都是由数值大的line-height
决定(10-2)。
大家应该都有设置了vertical-align
却没起作用的时候,因为 vertical-align 起作用是有前提条件的:只能应用于内联元素以及 display 值为 table-cell 的元素。vertical-align 属性只能作用在 display 计算值为 inline、inline-block,inline-table 或 table-cell 的元素上。浮动和定位会让元素块状化,所以设置vertical-align不起作用。
两者关系:vertical-align
的百分比值是相对于line-height
计算的(10-3)。
float
float指定一个元素应沿其容器的左侧或右侧放置,使用了float的元素脱离了文档流,其原本的作用是为了实现文字环绕效果(11-1)。
float意味着使用块布局,它在某些情况下修改display值,所以使用float时再添加display:block
是没有必要的,试图用vertical-align:middle
使元素居中也是无效的,因为vertical-align
对块级元素无效。
float会引起父元素高度塌陷,需要清除浮动来解决,案例11-2。
<div class="parent">
<div class="child1"></div>
<div class="child2"></div>
</div>
.parent{
width:300px;
background:#ddd;
border:1px solid;
// display: inline-block;
// overflow: hidden;
// float: left;
}
.child1{
width:100px;
height:100px;
background:pink;
float:left;
}
.child2{
// clear: left;
width:200px;
height:50px;
background:red;
}
清除浮动有两种方案,一是用clear属性,二是创建BFC。
BFC
BFC 全称为 block formatting context,中文为“块级格式化上下文”。 如果一个元素具有 BFC,那么它的内部元素样式不会影响外部的元素。所以,BFC 元素不会发生 margin 重叠,因为 margin重叠是会影响外部元素的;BFC 元素也可以用来清除浮动的影响,因为如果不清除,子元素浮动则父元素高度塌陷,就会影响后面元素布局和定位。
BFC特点:
- 内部的Box会在垂直方向,一个接一个地放置。
- Box垂直方向的距离由
margin
决定。属于同一个BFC的两个相邻Box的margin
会发生重叠 - 每个元素的左外边缘(
margin-left
), 与包含块的左边(contain box left
)相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。除非这个元素自己形成了一个新的BFC。 - BFC的区域不会与
float box
重叠。 - BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
- 计算BFC的高度时,浮动元素也参与计算
触发BFC就不需要使用clear:both
去清除浮动的影响了,那么如何触发BFC?
<html>
根元素- float 的值不为 none
- overflow 的值为 auto、scroll 或 hidden
- display 的值为 table-cell、table-caption 和 inline-block 中的任何一个
- position 的值不为 relative 和 static
BFC除了清除浮动,防止margin合并,还可以实现自适应布局(案例11-3)。
position:absolute
position:absolute
与float
类似,都能使元素脱离文档流,触发BFC。两者共存的时候,float没有任何效果。
我们常常这样使用,凡是使用absolute绝对定位的地方,父容器一定会使用relative,同时用top/bottom/left/right设置四个方向的值。其实,absolute可以单独使用,它的样式和行为表现不依赖其他任何 CSS 属性就可以完成,且具有很好的兼容性(12-1,12-2)。
虽说position:absolute
能使元素块状化,但是其定位的位置和没有设置position:absolute
时候的位置相关(12-3)。
absolute对立方向同时发生定位的时候,元素具有流体特性,可以使用margin:auto使元素居中(12-4)。
position:relative
该关键字下,元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)。 relative是相对自身原始位置定位,当top/bottom,left/right同时使用时,绝对定位可以理解为尺寸拉伸,相对定位只有一个方向的定位属性会起作用,top > bottom, left > right(案例13)。
position:fixed
使用无依赖的固定定位,不用设置方向定位,可以实现在一个元素内部固定(案例14)。
z-index
css层叠顺序
z-index
属性设定了一个定位元素及其后代元素或 flex 项目的 z-order。 当元素之间重叠的时候, z-index 较大的元素会覆盖较小的元素在上层进行显示。大多场景下我们会简单的认为数值越大,元素顺序就会越大,其实是片面的,元素堆叠顺序由层叠上下文和层叠水平顺序共同决定。
层叠上下文:与BFC概念类似(块状格式化上下文),都是创建了一个独立的上下文,这个上下文里的元素层级比普通元素层级更高,与别的层叠上下文也是隔离的。
层叠水平:决定了同一个层叠上下文中元素在 z 轴上的显示顺序。
层叠准则:
- 谁大谁上:当具有明显的层叠水平标识的时候,如生效的 z-index 属性值,在同一个层叠上下文领域,层叠水平值大的那一个覆盖小的那一个。
- 后来居上:当元素的层叠水平一致、层叠顺序相同的时候,在 DOM 流中处于后面的元素会覆盖前面的元素(案例15)。
如何创建层叠上下文:
- 页面根元素
html
天生具有层叠上下文,称为根层叠上下文。 - z-index 值为数值的定位元素的传统“层叠上下文”。
- 其他 CSS3 属性(flex布局等)。
display与visibility
HTML中有很多标签和属性天然 display:none
,如<style>、<script>
等。
HTML5中新增了 hidden 这个布尔属性,可以让元素天生 display:none
隐藏。
如果一个元素display: none
,则该元素以及所有后代元素都隐藏,即使后代元素display不为none。
visibility:hidden
隐藏元素,但是其他元素的布局不改变,相当于此元素变成透明。要注意若将其子元素设为 visibility: visible
,则该子元素依然可见。若父元素设置visibility:hidden
,子元素也会看不见,这是visibility的继承性。
display:none
隐藏后的元素不占据任何空间,而 visibility:hidden
隐藏的元素空间依
旧保留。
visibility:hidden
不会影响计数器的计数,display:none
会影响(案例16)。