1. 定位和层叠上下文
1.1 定位常见值及原理
position属性用来指定一个元素在网页上的位置,一共有五种定位方式:static(默认值)relative(相对定位)、fixed(固定定位)、absolute(绝对定位)、sticky(粘性定位,2017年浏览器才支持)
1.1.1 static(默认值)
static是position属性的默认值,如果省略position属性,浏览器就认为该元素是static定位- 这时浏览器会按照源码的顺序,决定每个元素的位置,这称为“正常的页面流”(
normal flow)。每个块级元素占据自己的区块(block),元素与元素之间不产生重叠,这个位置就是元素的默认位置 - 该关键字指定元素使用正常的布局行为,即元素在文档常规流中当前的布局位置。此时
top、right、bottom、left和z-index属性无效
1.1.2 relative(相对定位)
- 表示相对于默认位置(即
static时的位置)进行偏移 - 即定位基点是元素的默认位置
- 它必须搭配
top、right、bottom、left这四个属性一起使用,用来指定偏移的方向和距离
1.1.3 absolute(绝对定位)
- 表示相对于上级元素(一般是父元素)进行偏移,即定位基点是父元素
- 它有一个重要的限制条件:定位基点(一般是父元素)不能是
static定位,否则定位基点就会变成整个网页的根元素HTML - 另外
absolute定位必须搭配top、right、bottom、left这四个元素一起使用 absolute定位的元素会被“正常页面流”忽略,即在“正常页面流”中,该元素所占空间为零
1.1.4 fixed(固定定位)
- 表示相对于视口(
viewport,浏览器窗口)进行偏移,即定为基点是浏览器窗口。这会导致元素的位置不随页面滚动而变化,好像固定在网页上一样 fixed定位必须搭配top、right、bottom、left这四个元素一起使用,表示元素的初始位置是基于视口计算的,否则初始位置就是元素的默认位置
1.1.5 sticky(粘性定位)
-
- 跟前面四个属性值都不一样,它会产生动态效果,很像
relative和fixed的结合:有些时候是relative定位(定位基点是自身默认位置),有些时候自动变成fixed定位(定位基点是视口)
- 跟前面四个属性值都不一样,它会产生动态效果,很像
- 因此它能够形成“动态固定”的效果。比如网页的搜索工具栏,初始加载时在自己的默认位置(
relative定位) sticky生效的前提是,必须搭配top、right、bottom、left这四个属性一起使用,不能省略,否则等同于relative定位,不产生“动态固定”的效果。原因是这四个属性用来定义“偏移距离”,浏览器把它当做sticky的生效门槛。- 它的具体规则是,当页面滚动时,父元素开始脱离视口时(即部分不可见),只要与
sticky元素的距离达到生效门槛,relative定位自动切换为fixed定位;等到父元素完全脱离视口时(即完全不可见),fixed定位自动切换回relative定位 - 页面向下滚动滚动时,工具栏变成固定位置,始终停留在页面头部(
fixed定位) - 等到页面重新向上滚动回到原位,工具栏也会回到默认位置
除了已经被淘汰的IE浏览器以外,其他浏览器目前都支持
sticky。但是Safari浏览器需要加上浏览器前缀:
position: -webkit-sticky; /** Safari浏览器 */
position: sticky; /** 其他浏览器 */
1.1.6 小结
是否脱离正常文档流:
- 脱离:
absolute、fixed - 不脱离:
relative、sticky
参照物(基点):
relative参照物是自己原本的位置absolute子绝父相,直到HTML为止fixed参照物直接就是浏览器窗口
相同点:
- 都可以和方位属性一起使用(
top/right/bottom/left),static除外 - 都可以和
z-index一起使用,static除外
技巧:
- 为了
top/right/bottom/left/z-index起作用,这个时候我们就可以选用相对定位(relative) - 模块固定在浏览器窗口的某个位置可以选用固定定位(
fixed) - 给遮盖+叠加的容器,可以选用绝对定位(
absolute)
1.2 postition fixed 和 sticky
position: fixed和position: sticky
都可以在拖动滚动条的时候,将元素固定在指定位置,但是两者的区别很大:
1.2.1 position: fixed
- 元素可以被固定于页面指定位置,始终固定于此位置
- 定位位置可以通过
top、right、bottom、left属性设置 - 如果属性同时设置,那么
top的优先级高于bottom,left的优先级高于right top、right、bottom、left无需显示设置,fixed定位也会生效- 元素的定位参考对象是当前窗口
- 元素脱离文档流
- 当前所有主流浏览器都支持此定位方式
1.2.2 position: sticky
- 元素可以被固定于页面指定位置,但并不一定始终固定于此位置
- 定位位置可以通过
top、right、bottom、left属性设置,但是此位置是一个临界值,也就是说元素只有达到设置的这个临界值才会固定,其他位置并不会固定 - 如果属性同时设置,那么
top的优先级高于bottom,left的优先级高于right - 必须至少显示设置
top、right、bottom、left其中某一个属性值,sticky定位才会生效 - 元素的定位参考对象距离其最近的
overflow属性值为visible的具有滚动条的祖先元素,如果是以body或者body的父元素为参考对象,那么定位参考对象是窗口 - 元素不会脱离文档流
- 浏览器兼容性较差
1.3 层叠上下文和层叠顺序
1.3.1 层叠上下文含义
- 层叠上下文,是HTML中一个三维的概念。在CSS2.1规范中,每个盒模型的位置都是三维的,分别是平面画布上的X轴,Y轴以及表示层叠的Z轴。一般情况下,元素在页面上沿X轴或者Y轴平铺,我们察觉不到他们的Z轴上的层叠关系。而一旦元素发生堆叠,这时就能发现某个元素可能覆盖了另一个元素或者被另一个元素覆盖
- 如果一个元素含有层叠上下文,我们可以理解为这个元素在Z轴上就“高人一等”,最终表现就是它离屏幕观察者更近了
1.3.2 层叠等级含义
- 层叠等级也叫做“层叠级别”或者“层叠水平”
- 在同一个层叠上下文中,他描述定义的是该层叠上下文中的层叠上下文元素在Z轴上的上下顺序
- 在其他普通元素中,他描述定义的是这些普通元素在Z轴上的上下顺序
- 普通元素的层叠等级优先由其所在的层叠上下文决定
- 层叠等级的比较只有在当前层叠上下文元素中才有意义,不同层叠上下文中比较层叠等级是没有意义的
1.3.3 层叠顺序
“层叠顺序”表示元素发生层叠时按照特定的顺序规则在Z轴上垂直显示。由此可见,前面所说的“层叠上下文”和“层叠等级”是一种概念,而这里的“层叠顺序”是一种规则
1.3.4 同一层叠上下文元素在Z轴的排列
- 创建层叠上下文的元素的背景和边框
- 层叠级别(
z-index)为负值的层叠上下文 - 常规流非定位的块盒
- 非定位的浮动盒子
- 常规流非定位行盒
- 任何
z-index是auto的定位子元素,以及z-index是0的层叠上下文 - 层叠等级为正值的层叠上下文
通俗理解:
- 当两个元素类型一样时,默认情况下后一个元素层级比前一个元素层级高
- 在没有设置背景的情况下,元素的背景是透明的,并且允许后面的元素头上来
- 块级元素和其他任意除定位元素以外,文字层级比背景层级高
- 浮动和块级元素,浮动层级高
- 浮动和行内块元素,行内块元素层级高
- 浮动和行内元素,行内元素层级高
- 定位和定位,后一个元素层级高
- 定位比所有元素层级高
背景和边框 < 小于0的z-index < 块级元素 < 浮动 < 行内块元素 < 行内元素 < 定位 < 大于0的z-index
1.3.5 固定定位(position: fixed)的特殊性
- 单纯是绝对/相对定位元素是无法创建一个层叠上下文的,需要同时满足
z-index值不为auto的条件。然而,固定定位元素就不需要满足这个条件,显得比较特殊 - 固定定位元素无需满足
z-index值不为auto的条件就可以创建层叠上下文;同样的,设置z-index: auto并不能撤销固定定位元素所创建的层叠上下文 - 正常情况下,固定定位是相对于浏览器视口进行定位的,但是当其祖先元素中存在符合以下任意一个条件的元素时,固定定位元素会相对于该元素进行定位
transform属性值不为nonetransform-style: preserve-3dperspective属性值不为notewill-change属性指定了上面3个CSS属性中的任意一个
通过对层叠上下文和层叠顺序的了解,我们知道要控制元素间的层叠关系除了使用
z-index属性外还有很多途径,而且比使用z-index要优雅的多。滥用z-index往往只会把层叠关系复杂化,造成代码难以维护
1.3.6 层叠准则
- 谁大谁上:当具有明显的层叠水平标识的时候,如识别的
z-index值,在同一个层叠上下文领域,层叠水平值大的那个覆盖层叠水平小的那个 - 后来居上:当元素的层叠水平一致、层叠顺序相同时,在DOM流中处于后面的元素会覆盖前面的元素
1.4 层叠上下文形成条件
- 层叠上下文是一块区域,这块区域有某个元素创建,它规定了该区域中的内容Z轴上排列的先后顺序
- 凡是拥有层叠上下文的元素,将离用户最近,也就是越靠近Z轴前面。默认情况下只有根元素HTML会产生一个层叠上下文,并且元素一旦使用了一些属性也将产生一个层叠上下文,如我们常用的定位属性。如果两个层叠上下文相遇,总是后一个层叠前一个,除非使用
z-index来改变 - 文档流中的层叠上下文由满足以下任意一个条件的元素形成:
- 文档根元素HTML
position值为absolute(绝对定位)或者relative(相对定位)且z-index值不为auto的元素position值为fixed(固定定位)或者sticky(粘性定位)的元素flex容器的子元素,且z-index值不为autogrid容器的子元素,且z-index值不为autoopacity属性值小于1的元素- 以下任意属性值不为none的元素:
transform、filter、perspective、clip-path、mask/mask-image/mask-border isolation属性值为isolate的元素-webkit-overflow-scrolling属性值为touch的元素will-change值设定了任意属性而该属性在non-initial值时会创建层叠上下文的元素contain属性值为layout、paint或者包含它们其中之一的合成纸(比如contain:strict、contain:content)的元素
在层叠上下文中,子元素同样也按照上面解释的规则进行层叠。重要的是,其子级层叠上下文的z-index值只在父级中才有意义。子级层叠上下文被自动视为父级层叠上下文的一个独立单元
- 层叠上下文可以包含在其他层叠上下文中,并且一起创建一个层叠上下文的层级
- 每个层叠上下文都完全独立于它的兄弟元素:当处理层叠式只考虑子元素
- 每个层叠上下文都是自包含的:当一个元素的内容发生层叠后,该元素将被作为整体在父级层叠上下文中按照顺序进行层叠
1.5 层叠上下文对z-index的影响
z-index属性设置元素的层叠顺序,拥有更高层叠顺序的元素总会处于层叠顺序较低的元素的前面。该属性设置一个定位元素沿z轴的位置,z轴定义为垂直延伸到显示区的轴。如果是正数,则离用户更近,负数则表示离用户更远
- 层叠上下文并不只是
z-index才能创建,还有很多其他元素也可以创建层叠上下文 - 在存在层叠上下文的情况下,
z-index的大小决定了层叠等级,即谁在谁上面 - 层叠等级的比较只有在同一级别的DOM节点的层叠上下文中才有意义
- 在同一DOM节点,并且层级水平一样的情况下,在HTML文档中写在后面的元素会遮住前面的元素
2. CSS布局模型
2.1 流动模型(Flow)
- 流动(Flow)是默认的网页布局模式。也就是说网页在默认状态下是HTML网页元素都是根据流动模型来分布网页内容的
- 块级元素都会在所处的包含元素内自上而下按照顺序垂直眼神分布,因为在默认状态下,块级元素的宽度都是100%。实际上,块级元素都会以行的形式占据位置
- 在流动模式下,内联元素都会在所处的包含元素内从左到右水平分布显示
2.2 浮动模型(Float)
- 通过CSS的float属性可以将元素设置为浮动元素。元素浮动之后不再占据原来的位置,它们会尽可能的往包裹它们的父元素的左边框或者右边框靠近,并会在它们元素所处位置的下面产生浮动流,影响下面的元素定位
- 浮动元素并没有完全脱离文档流,它只是从包裹它的盒子中浮动起来并尽可能远的往左侧或者右侧进行移动
- 浮动设计的初衷是为了实现文字在图片周围的环绕效果
2.3 层模型(Layer)
- 层布局模型就像是图像软件PhotoShop中非常流行的图层编辑功能,每个图层能够精准定位操作,但在网页设计领域,由于网页大小的活动性,层布局没能受到热捧。但是在网页上局部使用层布局还是有其方便之处的
- 层模式有三种形式:
- 相对定位(
position: relative) - 绝对定位(
position: absolute) - 固定定位(
position: fixed)
- 相对定位(
3. BFC及IFC原理
3.1 BFC的原理和功能
BFC是上面三种布局方式中的普通流,BFC会产生一个独立的容器,该容器内部的元素不会在布局上影响到外部的元素,在外部的普通流看来它和其他普通流元素无差别,文档最终会按照上面说的普通流计算布局
3.1.1 BFC的含义
- MDN的定义:块格式化上下文(Block Formatting Context,BFC)是web页面的可视化CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域
- BFC块级格式化上下文,它是页面中的一块渲染区域,并且有一套属于自己的渲染规则,它决定了元素如何对齐内容进行布局,以及与其他元素的关系和相互作用。当涉及到可视化布局的时候,BFC提供了一个环境,HTML元素在这个环境中按照一定规则进行布局
- 具有BFC特性的元素可以看做是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且BFC具有普通容器所没有的一些特性
- BFC是一个独立的布局环境,BFC内容的元素布局与外部互不影响
3.1.2 BFC的布局规则
- 内部的盒子会在垂直方向上逐个放置
- 盒子垂直方向的距离由
margin决定,属于同一个BFC的两个相邻盒子的上下margin会发生重叠 - 每个元素的左边,与包含的盒子的左边相接触,即使存在浮动也是如此
- BFC的区域不会与
float盒子重叠 - BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外部的元素,反之也是如此
- 计算BFC的高度时,浮动元素也参与计算
3.1.3 触发BFC的条件
只要元素满足以下任意条件即可触发BFC特性:
- HTML根元素或其他包含它的元素
float的属性不为noneoverflow为auto、scroll、hiddendisplay为inline-block、table-cell、table-caption中的任何一个position为absolute或者fixed
3.1.4 BFC的用处
案例一:让浮动内容和周围的内容等高
overflow:auto创建一个会包含这个浮动的BFC,通常的做法是设置父元素overfloaw:auto或者设置其他的非默认的overflow:visible的值。overflow:auto或者设置其他的非默认的overflow:visible的值- 使用
display:flow-root一个新的display属性的值,它可以创建无副作用的BFC。在父级块中使用display:flow-root可以创建新的BFC
案例二:外边距折叠
- 原因:盒子垂直方向的距离用margin决定。属于同一个BFC的两个相邻盒子的
margin会发生重叠 - 解决方法:给上盒子或者下盒子任意一个包裹的新的盒子合并开启BFC
- 原理:BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之也是如此
案例三:清除浮动
- 解决方法:给父元素开启BFC
- 原理:计算BFC的高度时,浮动子元素也参与计算
案例四:自适应的两列布局(左图右文)
- 解决方法:给父元素开启BFC
- 原理:BFC的区域不会与浮动盒子重叠
3.2 IFC的原理和功能
存在块级格式化上下文BFC,则对应存在内联格式化上下文IFC、网格格式化上下文GFC、自适应格式化上下文FFC,这些都可以统称为格式化上下文:
3.2.1 IFC的含义
- IFC(inline Formatting Context)叫做“内联格式化上下文”
- 内部的元素从包含块的顶部开始,从左至右排列成一行形成的一个矩形盒子叫做line box
3.2.2 IFC的布局规则
- 盒子是水平一个接一个的排列,水平的
margin、内边距、边框都是可以有的 - 垂直方向的对齐,可能是底部对齐、顶部对齐,也可能是基线对齐(默认)
- 行框中的内联盒子的高度小于行框的高度时,内联盒子的垂直方向的对齐方式取决于
vertical-align属性 - 当一个行框水平不能容纳内联盒子时,它们将会在垂直方向上产生多个行框,它们上下一个挨着一个,但是不会重叠
- 一般来说,行框的左边界紧挨着包含容器的左边界,行框的右边界紧挨着包含容器的右边界(两个边都是紧挨着的)。然而,浮动盒子可能存在于包含边框边界和行框边界之间
- 多个内联盒子的宽度小于包含它们的行框时,它们在水平方向的分布取决于
text-align属性
3.2.3 IFC的作用
- 水平居中:当一个块要在环境中水平居中时,设置其为
inline-block则会在外层产生IFC,通过text-align:center则可以使得其水平居中 - 垂直居中:创建一个IFC,用其中一个元素撑开父元素的高度,然后设置其
vertical-align:middle,其他行内元素则可以在此父元素下垂直居中
3.3 理解font-size、line-height、vertical-align
图片下面默认的留白:
- 让
vertical-align失效-图片设置display或者浮动、绝对定位 - 使用其他
vertical-align值(bottom/middle/top) - 直接修改
line-height值 line-height为相对单位,font-size间接控制
4. CSS渲染和解析原理
- 浏览器接收到服务器返回的HTML页面
- 浏览器开始构建DOM树(DOM TREE),遇到CSS样式会构建CSS规则树(CSS RULE TREE)
- 遇到JavaScript会通过DOM API和CSSDOM API来操作DOM TREE和CSS RULE TREE,解析完成后
- 浏览器引擎会通过DOM TREE和CSS RULE TREE来构建Rendering Tree(渲染树)
- 最后熏染树构建完成后就是布局处理,也就是每个节点在屏幕上的确切显示位置
- 下个步骤,开始绘制,遍历渲染树,将每个节点绘制出来
4.1 CSS渲染规则
CSS渲染规则,是从上到下,从右到左渲染的:
.main h4 a { font-size: 14px; }
首先找到所有的a标签,沿着a标签的父元素查找h4标签,然后再沿着h4,查找.main。中途找到了符合匹配规则的节点就加入结果集,如果找到根元素的HTML都没有匹配,则这条路径不再遍历。下个a标签开始重复这个查找匹配,直到没有a标签继续查找。
浏览器的这种查找规则是为了尽早过滤掉一些无关的样式规则和元素。
5. CSS性能优化
5.1 CSS 常见性能优化方法汇总
- 尽量避免类似
.a .b {}、.list a {}以及其他一些复杂选择器,以提高网站整体CSS渲染 - 避免某些表达式,避免IE6的透明滤镜,可以试试使用火狐生成png8 alpha透明
- 适当定高
- 图片设定不响应重回的尺寸,如果你的
img标签不设定尺寸,同时外部容器没有定死高度,则图片在首次载入的时候,占据空间会从0到完全出现,左右上下都可能位移,发生大规模的重绘。可以使用width/height控制,或者在CSS中国你设置 <textarea>或者使用<script type="text/html">存储动态载入HTML或者模板HTML,降低首屏加载的渲染时间- 具有复杂动画的元素绝对定位-脱离文档流,避免强烈的回流。现代浏览器可以渐进使用CSS3
transition实现动画效果,比改变像素值来的高性能 - 不使用
iframe,开销最大的DOM元素 - 不要使用类选择器和ID选择器修饰元素标签
- 保持简单,不要使用嵌套过多过于复杂的选择器,避免深层次、嵌套层级不要超过三级
- 通配符和属性选择器效率最低,需要匹配的元素最多,尽量避免使用
- 通常将浏览器前缀置于前面,将标准样式属性置于后面
- 减少CSS文件体积:移除空的CSS规则、值为0不需要单位,复合属性使用缩写、属性值为浮点数可以省略小数点的0、不给
h1-h6元素定义过多的样式 - 把CSS放在HTML页面头部,不要使用
@import - 减少使用昂贵的属性,如
box-shadow/border-radius/filter/ 透明度等 - 优化重排与重绘:减少重排、避免不必要的重绘
- 小图片的处理方案:
sprite、字体图标、base64编码