在重新回顾一遍CSS之后,我认为CSS有三大难点,分别为float平均布局、层叠上下文定位、浏览器渲染原理,先从第一个讲起。
float 平均布局
假设有这么一个需求,在800px宽度的屏幕里,使用float浮动定位以4幅图片平均布局的方式放置若干幅图片,HTML如下:
<div class="imageList clearfix">
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
</div>
我们容易想到,设图片宽度为x,间距为y,有4x + 3y = 800,且尽量满足x,y为整数,可以得到x = 191,y = 12,我们写一下CSS
.imageList{
width: 800px;
}
.clearfix:after{
content: '';
display: block;
clear: both;
}
.imageList .image{
width: 191px;
height: 191px;
background: #000;
border: 10px solid red;
float: left;
margin-bottom: 10px;
margin-right: 12px;
}
写完发现似乎有些不对劲,图片并没有按照我们设想的方式排布,一排只有3张,这是为什么呢?
原来是一排放不下了,一张图片191+12 = 203,203 * 3 = 609,只剩下191,而第四张图片依然有12px的margin-right... 浏览器发现空间不够,就只能把第四张图片移到下一行了。
怎么解决这个问题呢?
给图片加一个父类,样式设为margin-right: -12px;,HTML更新为
<div class="imageList">
<div class="x clearfix">
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
</div>
</div>
CSS加入一条
.imageList > .x{
margin-right: -12px;
}
bingo!神奇的事情发生了!
究竟是什么原理呢?开发者工具可以帮助我们一探究竟。
由于4张图片的总宽度是812px,父元素只有800px是容纳不下的,但是-12px的margin-right使得父元素向右“撑胖”了12px,这样就刚好容纳这4张图片了。
CSS的奥妙之处还远大于此。
层叠上下文定位
有这样一个问题,z-index=10的元素一定在z-index=5元素的上面吗?
答案是不一定。
看一个例子,HTML:
<body>
<div class="container">
<div class="a">1
<div class="a1">10</div>
</div>
<div class="b">
<div class="b1">5</div>
</div>
</div>
</body>
CSS
.container{
border: 1px solid red;
height: 200px;
position: relative;
}
.a{
position: relative;
z-index: 1;
border: 1px solid blue;
}
.a1{
z-index:10;
height: 50px;
width: 50px;
background: red;
}
.b1{
position: relative;
z-index: 5;
height: 50px;
width: 50px;
background: blue;
top: -20px;
color: white;
}
实际效果
5居然在10上面?
其实是5在1中的10上面(a1父元素a的z-index=1)。
这又是为什么呢?
这就是CSS中的层叠上下文,每一个层叠上下文都是一个小世界,这个小世界里面的z-index与外界无关,只有同一个小世界的z-index才能比较大小。
那么哪些CSS属性会创建这个小世界呢?
权威回答在这里,层叠上下文的形成。
其中我认为比较重要的几个,分别是:
- z-index不为默认的auto(只要设置了z-index,且值不为auto)
- 根元素HTML
position: fixed/sticky;
讲完了前两个重难点,还有一个就是浏览器的渲染原理。
浏览器的渲染原理
讲一下浏览器的渲染过程:
- 根据HTML构建HTML树
- 根据CSS构建CSS树
- 根据HTML和CSS构建渲染树,render tree
- Layout布局(文档流、盒模型、计算大小和位置)
- Paint绘制(边框颜色、文字颜色、阴影等)
- Composite合成(根据层叠关系展示画面)
重点在后三步,每一步都会消耗一定的性能,所以js更新样式,有三种方式:
- 三步全走,如div.remove()当前元素消失,其他元素relayout
- 走后两步,如改变背景颜色,只repaint+composite,不改变layout
- 只走最后一步,如transform,所以这就是为什么动画用transform而不改变left之类定位属性的原因,更节能
CSS动画的实现
有两种实现方法,分别是transition和animation
transition作用是补充中间帧,语法为:
transition: 属性名 时长 动画效果 延迟;
#heart{
display: inline-block;
position: relative;
transition: all 1s;
}
#heart:hover{
transform: scale(1.2);
}
animation的重点是写好中间的关键帧,
语法为:
animation: 时长 过渡方式 延迟 重复次数 方向 填充模式 是否暂停 动画名
@keyframes 动画名:关键帧百分比1{} 关键帧百分比2{} 关键帧百分比3{}../
#heart{
display: inline-block;
position: relative;
margin: 100px;
animation: .5s infinite 3s alternate-reverse beating;
}
@keyframes beating {
0%{
transform: scale(1.0);
}
100%{
transform: scale(1.2);
}
}