从CSS盒模型谈起
1. 盒模型Box Model
- 盒模型由外而内是四部分:margin,border,padding,content。
- 盒模型有两种模型:标准模型和IE模型。
content-box
的宽高指定contentborder-box
的宽高指定border+padding+content的总宽高
/*标准*/
box-sizing: content-box;
/*IE*/
box-sizing: border-box;
2. JS获取宽高
dom.style.width
只能得内联样式getComputedStyle(dom).width
dom.offsetWidth
最常用dom.getBoundingClientRect().width
3. 边距折叠问题Collapsing Margins
- 父子或兄弟元素在垂直方向上margin遇见margin,以较大值为准。
- 毗邻:没有padding、border等隔断
4. 块级格式下文BFCBlock formatting context
- FC决定子元素如何定位,自身和其他元素的关系和相互作用
- IFC是行内格式化上下文,box一个接一个的水平排列
- BFC是一个独立的容器,内外元素互不影响
- BFC内部的box一个接一个的垂直放置
- 垂直方向的距离由margin决定,属于同一个BFC的相邻元素的margin会重叠
- 不与浮动元素重叠
- 计算BFC高度时,浮动元素也参与计算
- 作用:
- 消除垂直margin折叠
- 清除浮动
- 创建一个BFC:
position: absolute|fixed;
,display: inline-block;
- 根元素
- 浮动元素(float不是none)
- 绝对定位元素(position:absolute|fixed)
- 非块级元素具有display: inline-block|table-cell|table-caption|inline-flex;
- 块级元素具有overflow值非visible
inline-block元素内部是一个BFC,外部呈现为一个inline元素,可以和其他inline元素一起形成IFC
5. css优先级
!important
- 行内样式
- id选择器
- class选择器
- 标签选择器
权重相同时,后者覆盖前者
一种权重计算规则: 0.0.0.0 依次代表行内、id、class、标签选择器
.a.b
和.a .b
和.a,.b
的区别
写法 | 描述 |
---|---|
.a.b | 同时拥有两个类名 |
.a,.b | 相当于分别定义样式 |
.a .b | 父级a下的子级b |
.a | 分别定义 |
.b | 分别定义 |
<div class="a b">
你好|绿色
<div class="a b">你好|紫色</div>
</div>
<style>
/* .a.b 和 .a .b的顺序会有影响 */
.a.b{
color: green;
}
.a .b{
color: purple;
}
.a{
color: red;
}
.b{
color: blue;
}
</style>
6. position和display
6.1 position
值 | 描述 |
---|---|
absolute | 绝对定位,相对于static定位以外的第一个父元素进行定位 |
fixed | 固定定位,根据浏览器窗口定位 |
relative | 相对定位,相对于元素本来的正常位置进行偏移 |
static | 默认,出现在正常流中,忽略z-index等 |
inherit | 继承父元素 |
sticky | 粘性定位 |
- z-index属性,只在定位元素上起作用
- 必须有position不为static才起作用
- 水平垂直居中,绝对定位+偏移
- 绝对定位:父元素有position(不是static),子元素absolute
- 粘性定位sticky:实际上是在阈值之前相对定位,跨越阈值之后固定定位
<div class="container">
<div style="height: 200px;"></div>
<div class="content">把我留在你眼底</div>
</div>
<style>
.container {
height: 1500px;
}
.content {
position: sticky;
top: 0px;
color: red;
height: 20px;
}
</style>
6.2 display
值 | 描述 |
---|---|
none | 不显示 |
block | 块级元素,前后带有换行符 |
inline | 默认,行内元素,前后无换行 |
inline-block | 行内块 |
- 隐藏元素的三种方法
- display: none; 元素不出现文档流中
- visibility: hidden; 元素不显示
- opacity: 0; 元素显示但是透明度为0
- block和inline的区别
-
display: block;
- 块级元素会独占一行;前后都有换行符
- 块级元素默认宽度自动填充满父元素宽度
- 块级元素可以设置width和height
- 可以设置margin和padding
-
display: inline;
- 行内元素没有换行符,多个元素排在一行,直到排不下
- 行内元素设置宽高无效
- 行内元素仅支持水平方向的margin和padding,垂直方向无效
-
display: inline-block;
- 对外呈现为inline;对内作为block
- 具有block的宽高属性,又具有inline的同行属性
- 常见的块级元素和行内元素
元素 | 标签 |
---|---|
块级 | canvas,div,footer,form,h1,li,ol,ul,p,table,audio,hr,aside,header,section |
行内 | i,a,b,br,em,input,textarea,video,button,embed,label,q,strong,span |
7. 回流reflow和重绘repaint
- 浏览器渲染流程
- 讲解
- 解析HTML生成DOM树;CSS生成CSSOM树
- DOM和CSSOM结合生成渲染书Render tree
- 回流:计算节点几何信息
- 重绘:得到节点的绝对像素
- Display:将像素发送给GPU,展示页面
- 何时发生回流重绘:当页面布局和几何信息发生变化
- 添加、删除、移动可见的DOM
- DOM元素尺寸变化(margin、padding、border、width、height)
- 元素的content变化
- 初始渲染时
- 浏览器窗口尺寸变化
- 浏览器优化机制
回流需要大量计算消耗。浏览器通过队列化修改并批量执行来优化
浏览器将修改操作放入队列,直到一定时间或者操作达到一定阈值,才清空队列
获取布局信息的操作时,会强制队列刷新,这些操作有:
- offsetTop
- scrollLeft
- clientWidth
- getComputedStyle()
- getBoundingClientRect()
- 减少回流和重绘
let ele = document.getElementById('test');
/*最小化回流重绘次数*/
ele.style.padding = '5px';
ele.style.border = 'red 1px solid';
/*使用cssText*/
ele.style.cssText += 'padding: 5px;border: 1px red solid;';
/*修改CSS类名*/
ele.className += ' active';
// ele.classList.add("active");
- 批量修改DOM
对DOM做一系列修改的时候,通过以下步骤可以减少回流重绘次数
- 使元素脱离文档流
- 修改
- 放回文档
使脱离文档流的方法有:
- 浮动
float
- 绝对定位
- 固定定位