此篇博客是学习《CSS 揭秘》一书的学习笔记。
1. 单侧投影
尝试实现单侧投影的代码如下: HTML
1
<div class="box-100 bg-red-4 bottom-shadow-4-1"></div>
CSS
1
2
3
.bottom-shadow-4-1 {
box-shadow: 0 5px 4px black;
}
效果如下:
第三个值阴影模糊半径 4px
会导致模糊后的阴影显示在两侧,多出来的长度大约为 4px
。
我们可以使用第四个长度参数 —— 阴影扩散半径来消除两侧的阴影。当我们设置负的扩散半径时,阴影会根据指定的值缩小。
CSS
1
2
3
.bottom-shadow-4-1 {
box-shadow: 0 5px 4px -4px black;
}
注:前后几个值分别为 x偏移量 | y偏移量 | 阴影模糊半径 | 阴影扩散半径 | 阴影颜色
。
最终效果如下:
邻边投影
HTML
1
<div class="box-100 bg-red-4 sides-shadow-4-2 margin-btm-14"></div>
CSS
1
2
3
.sides-shadow-4-2 {
box-shadow: 4px 4px 6px -3px black;
}
注:
- 扩张半径(-3px)为模糊半径(6px)的相反值的一半。
- 偏移值要大于等于模糊半径(6px)的一半,这样投影才能被藏进另外两条边之内。
双侧投影
box-shadow
支持使用逗号分隔多个阴影效果。因此我们可以使用两个投影来实现双侧投影。
HTML
1
<div class="box-100 bg-red-4 opposite-sides-shadow-4-3 margin-btm-14"></div>
CSS
1
2
3
4
.opposite-sides-shadow-4-3 {
box-shadow: 5px 0 5px -5px black,
-5px 0 5px -5px black;
}
2. 不规则投影
在某些情况下, box-shadow
会忽略掉元素的一部分。如下面三种情况:
给这几个元素添加 box-shadow
后效果如下:
HTML
1
2
3
<div class="box-4-2 shadow-4-2 speech-bubble">对话气泡</div>
<div class="box-4-2 shadow-4-2 dotted-border">虚线边框</div>
<div class="box-4-2 shadow-4-2 cutout-corners">切角效果</div>
CSS
1
2
3
.shadow-4-2 {
box-shadow: 2px 2px 6px rgba(0, 0, 0, .5);
}
我们可以使用 filter
属性,并使用 drop-shadow()
方法,它接受和 box-shadow
属性一样的参数,但不包括扩张半径和 inset
关键字。
注: IE 浏览器不支持该属性。
CSS
1
2
3
.filter-4-2 {
filter: drop-shadow(2px 2px 6px rgba(0, 0, 0, .5));
}
注: 任何非透明的部分都会被打上投影,例如虚线边框效果中的文字。
3. 毛玻璃效果
filter
属性有一个 blur()
方法可以设置高斯模糊。
HTML
1
2
3
4
5
6
7
8
9
10
11
12
<div class="frosted-glass">
<div>
<p>
由于我们不能直接对元素本身进行模糊处理,但可以对伪元素进行模糊处理,
然后将其定位到元素的下面,它的背景将会无缝匹配宿主元素的父元素的背景。
</p>
<p>
在使用负的 z-index 来把一个子元素移动到他的父元素下层时,请务必小心;
如果父元素的上级元素也有背景,则该子元素将出现在它们之后。
</p>
</div>
</div>
CSS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
* {
margin: 0;
padding: 0;
}
.frosted-glass {
width: 100%;
height: 500px;
overflow: hidden; /* 防止子元素的 margin-top 影响此元素的定位 */
}
.frosted-glass div {
position: relative;
margin: 150px auto;
width: 60%;
padding: 20px;
border-radius: 5px;
overflow: hidden; /* 防止高斯模糊效果弱化元素边界 */
background: hsla(0, 0%, 100%, .3);
color: white;
text-shadow: black 0.1em 0.1em 0.2em;
z-index: 1;
}
.frosted-glass,
.frosted-glass div::after {
background: url('/images/2019-06-01-css-secrets/book.jpg') 0 / cover fixed;
}
.frosted-glass div::after {
content: "";
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
filter: blur(4px); /* 高斯模糊效果 */
z-index: -1; /* 让伪元素位于内容之后 */
}
注:
由于为了使 div.frosted-glass
和 div.frosted-glass div::after
两个元素的背景无缝匹配, 我们把 background-attachment
设为了 fixed
:
1
2
3
4
.frosted-glass,
.frosted-glass div::after {
background: url('/images/2019-06-01-css-secrets/book.jpg') 0 / cover fixed;
}
这会让背景不会随着元素的内容滚动。其中 /
前面的 0
为 background-position
,当只设置了一个值时,Y
方向的值为 center
。
为了不让图片在滚动的时候,出现背景和文字相对移动的情况,上图使用 <iframe>
标签内嵌了一个 HTML
页面,否则就会出现如下情况。
由于我们不能直接对元素本身进行模糊处理,但可以对伪元素进行模糊处理, 然后将其定位到元素的下面,它的背景将会无缝匹配宿主元素的父元素的背景。
在使用负的 z-index 来把一个子元素移动到他的父元素下层时,请务必小心; 如果父元素的上级元素也有背景,则该子元素将出现在它们之后。
4. 折角效果
45°折角效果
我们可以利用 3.4 切角效果 一节中的渐变方法去实现此效果。
先实现缺角效果:
CSS
1
2
3
.folded-corner-4-4.step-1 {
background: linear-gradient(-135deg, transparent 1.42em, #ff7873 0);
}
再实现折角效果:
CSS
1
2
3
.folded-corner-4-4.step-2 {
background: linear-gradient(45deg, rgba(0, 0, 0, .4) 1.42em, transparent 0) top right / 2em 2em no-repeat;
}
最后重叠:
CSS
1
2
3
4
.folded-corner-4-4.step-3 {
background: linear-gradient(45deg, rgba(0, 0, 0, .4) 1.42em, transparent 0) top right / 2em 2em no-repeat,
linear-gradient(-135deg, transparent 1.42em, #ff7873 0);
}
注: 折角效果要放在切角效果后面。
其他角度折角效果
我们可以改变角度和折角背景的宽和高,就能形成如下 30° 折角效果:
CSS
1
2
3
4
5
.folded-corner-4-4.step-4 {
background: linear-gradient(30deg, rgba(0, 0, 0, .4) 1.42em, transparent 0)
top right / 2.84em 1.64em no-repeat,
linear-gradient(-150deg, transparent 1.42em, #ff7873 0);
}
我们发现折角效果并不真实,折角和缺角应该是沿着斜边对称的。
由于背景无法旋转,我们可以旋转伪元素。
HTML
1
2
3
<div class="folded-corner-4-4 margin-btm-14 step-5">30°折角(伪元素)</div>
<div class="folded-corner-4-4 margin-btm-14 step-5 step-6">30°折角(旋转伪元素)</div>
<div class="folded-corner-4-4 margin-btm-14 step-5 step-6 step-7">30°折角(最终效果)</div>
CSS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.folded-corner-4-4.step-5 {
display: inline-block;
position: relative;
margin-right: 14px;
background: linear-gradient(-150deg, transparent 1.42em, #ff7873 0);
border: none;
}
.folded-corner-4-4.step-5::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 2.84em;
height: 1.64em;
background: linear-gradient(-30deg, rgba(0, 0, 0, .4) 50%, transparent 0);
}
.folded-corner-4-4.step-6::before {
transform: rotate(60deg);
}
.folded-corner-4-4.step-7 {
border-radius: .4em;
}
.folded-corner-4-4.step-7::before {
background: linear-gradient(-30deg,
rgba(0, 0, 0, .4) 0,
rgba(0, 0, 0, .2) 50%,
transparent 0);
border-bottom-right-radius: inherit;
box-shadow: .2em .2em .3em -.1em rgba(0, 0, 0, .15);
}
重点:
- 切角效果放在
div
元素上,折角效果放在div::before
伪元素上; - 伪元素的宽高为之前折角效果背景的宽高;
- 伪元素的背景的线性角度由
30deg
变为-30deg
(左图); - 最后把伪元素旋转
60deg
(右图)。