border-radius
border-radius 是用来设置圆角的,这个相信读者肯定也用过,这里需要拓展。
css
div {
width: 100px;
height: 100px;
background-color: skyblue;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 10px 20px 30px 40px;
}border-radius 可以给四个角分别设置圆角,如果书写四个属性,设置圆角的顺序为左上-右上-右下-左下,上面的效果如图所示

border-radius 也是一个速写属性,是由 4 个属性共同构成的,可以在 chrome 的调试工具中找到

注意这里的书写顺序,是先写上下,再写左右
我们这里还有更高级的用法,当我们写 border-top-left-radius:10px;,实际上写的是 border-top-left-radius:10px 10px;,二个我们一般都是默认省略掉的。
我们其实应该知道,圆角本质上是用一个圆切出来的,如图所示

如果两个值都填一样,或者只填一个值,例如 border-top-left-radius:10px 10px;,本质上是一个半径 10 px 的正圆在角上切出来的,但我们有时候可能希望使用椭圆来切,就如图中第三种情况,这种情况就需要把两个参数设为不同的值。
这两个参数中,第一个参数表示椭圆的横向半径,第二个参数则表示纵向半径。
css
div {
width: 100px;
height: 100px;
background-color: skyblue;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-bottom-left-radius: 80px 40px;
border-bottom-right-radius: 80px 40px;
}
此时下面两个角就是被椭圆切出来的,明显就和以前的圆角不一样。
css
div {
width: 100px;
height: 100px;
background-color: skyblue;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-bottom-left-radius: 100px 100px;
}当我们将一个角的半径拉到最大,我们就得到了一个四分之一圆。

我们也可以用圆角来画半圆
css
div {
width: 200px;
height: 100px;
background-color: skyblue;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-bottom-left-radius: 100px 100px;
border-bottom-right-radius: 100px 100px;
}这样就画出来了一个半圆。
如果我们要对每一个角设置椭圆去切,没有必要一个角一个角去切,可以使用简写
css
div {
width: 200px;
height: 100px;
background-color: skyblue;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 10px 20px 30px 40px / 20px 30px 40px 50px;
}这个中间写斜线的写法,相当于左上角设置 (10px,20px),右上角设置 (20px,30px), 右下角设置 (30px,40px),左下角设置 (40px,50px),相信这个也不难理解,相当于前后一一匹配。
box-shadow
box-shadow 用于设置阴影。
阴影又分为两个,分别是外阴影和内阴影,也就是说这个阴影可以加载盒子外面,也可以加在盒子里面。
这个 box-shadow 最多可以填六个东西,分别是颜色,内外,偏移量(两个方向),模糊,扩散
这里一一解释,首先内外阴影这个很好解释,如果参数里填上 inset 则表示内阴影,不写的话默认是外阴影,颜色也很好理解,就是阴影颜色是什么。
剩下的四个,偏移量,模糊和扩散,都是长度单位,这四个必须写在一起,中间不能有其他的东西,而 inset 和颜色可以写在这四个前面,也可以写在这四个后面,这个无所谓,一般来说,我们会把 inset 和颜色写在这四个值前面。
这四个值至少给出两个。如果给出两个,则表示 x 和 y 轴上的偏移量。

我们从这个变化过程可以得出以下结论
- 方向和我们预期的一致,以右为 x 的正方向,以下为 y 的正方向,这是计算机中常见的坐标系。
- 偏移量可以为负数,为负数表示向负方向偏移。
其实从这里也能感受到,阴影本质上就是一个和图像长得一模一样的色块,读者可以设置圆角试一下,设置圆角后阴影也会跟着被设上圆角。
这两个偏移量是必须要写的,inset 不写默认就是 outset ,也就是外阴影,写上 inset 才能表示内阴影,如果不写颜色默认也就是黑色。所以我们可以说 box-shadow 里面必须填上的有两个属性,分别是第一个是 x 轴偏移量,第二个是 y 轴偏移量。
如果在偏移量后面写上第三个长度单位,则表示模糊半径,如果再写第四个参数,则表示扩散范围。

接下来来看第三个参数,我先用偏移量把阴影给他单独挪到右边来,然后调整它的第三个参数,随着第三个参数的升高,阴影越来越糊了,或者说叫越来越模糊,所以这个其实就是用来调整其模糊度的。同时我们还可以发现,当我把阴影调整为负数的时候,阴影直接没了,所以模糊度是不能为负数的。
同时,模糊这个东西,是基于原来的位置,向边框两边同时扩散,我们可以这样验证

读者通过这个例子可以看到,原来阴影和方块是完全对其的,模糊之后整个阴影的大小变大了。
接下来是最后一个属性,也就是扩散,扩散其实很好理解,其实阴影就是一个和原来图像长得一模一样的纯色块,大小也是一模一样的,那如果我希望它变大一点,这个时候就需要扩散这个属性了,我们将偏移量和模糊都设为 0,看一下扩散的变化。

可以看到,扩散就是调整整个阴影的大小,随着扩散的增加,阴影的尺寸也会增加,扩散也可以为负数,当为负数的时候就是将原图形缩小。
扩散的增加是从四周增加,比如扩散了 10 像素,实际上整个阴影的大小是上下左右各增加了 10 像素,即上下增加了 20 像素,左右增加了 20 像素。
最后简要介绍内阴影

这里把内阴影的四个值都给演示了一遍,说白了和外阴影差不多,前两个也是偏移量,第三个也是模糊,第四个也是扩散,用法一模一样,偏移量的方向也是一模一样。
阴影可以写多个
css
div {
width: 100px;
height: 100px;
background-color: skyblue;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
box-shadow: #f40 200px 0px 0px 0px, #f40 0px 200px 0px 0px, #f40 -200px 0px 0px 0px, #f40 0px -200px 0px 0px;
}多个阴影中间用逗号隔开,此时就形成了四个不同方向的阴影

如果设置多个阴影,是有层级次序的,最先设置的阴影是在逻辑的最上层的,也就是离我们最近,会把其他阴影覆盖掉。
css
div {
width: 100px;
height: 100px;
background-color: skyblue;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
box-shadow:
#ff0 3px 0px 5px 0px,
#0ff 0px -3px 5px 0px,
#f0f -3px 0px 5px 0px,
#0f0 0px 3px 5px 0px;
}我们通过这样设置多个阴影,就可以实现这样一个四个方向不同色阴影的效果

设置模糊会让边界变糊,这种糊其实是一种半透明的状态,如果我们写多个阴影,会让变糊部分的颜色加深。
有了阴影我们就可以作出一些非常好看的效果。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
background-color: black;
}
div {
width: 300px;
height: 300px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;
box-shadow:
/* 在黑色背景发亮,添加白色阴影 */
inset 0px 0px 50px #fff,
0px 0px 50px #fff,
/* 外阴影 */
-10px 0px 80px #f0f,
10px 0px 80px #0ff,
/* 内阴影 */
inset 10px 0px 80px #f0f,
inset -10px 0px 80px #0ff;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
这里其实有一个层级关系,背景在最底层,阴影在背景之上,会盖住背景,文字在阴影之上,是最上层。
border-image
border-image 由以下一组属性组成
- border-image-source
- border-image-slice
- border-image-width
- border-image-outset
- border-image-repeat
border-image 这个属性是简写属性,但并不建议直接使用这个简写属性,更建议使用每一个单独拆开的属性。
border-image 顾名思义就是允许我们给边框添加背景图片。
css
div {
width: 100px;
height: 100px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: 10px solid black;
border-image-source: url(http://5b0988e595225.cdn.sohucs.com/images/20180412/ab16cd8ce4af4f54a1de54be0914bf7f.jpeg);
}可以看到,此时这个边框就变成哈士奇了

当我们设置了
border-image-source之后,border-color直接失效
但这里只有四个角变成图片了,这并不是我们希望的效果,这里就需要用到 border-image-slice 属性了
我们这里将一个实际的例子,设置背景颜色我们给的都是一个这个样子的图片

当然原图里没有这个线,这个线是作为辅助线后加的,CSS 会按照这个辅助线将图片分成 9 个区域,同时边框部分也会被分成 9 个区域,从图片中也能看到,这个矩形如果把 9 挖掉剩下的正好就是一个边框的样子,CSS 将这个图片分成这样的九块后,就会把边上的八块依次放到对应的区域中去。

这张图会更加直观一点,可以看到这张图被四条线分成了 9 部分,我们把这四条线分别称为 top,right,bottom,left,切割完成之后,top 和 left 所划出来的区域会被放到边框的左上角,left,right,top 划出来的区域会被放到边框的上面,right 和同 top 划出来的区域会被放到边框的右上角,其他部分也同理,这个在图片中也显而易见。
我们可以通过设置 border-image-slice 来设置这四条线,这个属性填入四个值,分别对应 top, right, bottom, left,这个顺序和我们其他地方的顺序都一样,比如 margin,都是按照上右下左的顺序书写的,第一个填入 top 距离顶部的距离,第二个填入 right 距离右边的距离,第三个填入 bottom 距离下面的距离,第四个填入 left 距离左边的距离。这个属性只能填入纯数字或百分比(也可以填入一些关键字),如果填入纯数字,那么单位是像素,注意,不能填 100px,只能填 100,只能填纯数字。
如果填入百分比,就是基于这个图像宽高的百分比。border-image-slice 的默认值为 100%,也就是 top 在最底部,left 在最右边,right 在最左边,bottom 在最上边,这就可以解释为什么前面只有四个角上有哈士奇了,默认情况下 left 在最右边,bottom 在最上面,这两条线此时切割出来的部分就是整张图片,而这两条线切割出来的部分正好也是边框的左上角,所以左上角就是整张图片。而边框上面的部分,left 和 right 这两条线错位了,left 跑到最右边了,right 跑到最左边了,这样错位的情况是啥也切割不出来的,所以顶部就是啥也没有。
css
div {
width: 100px;
height: 100px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: 10px solid black;
border-image-source: url(http://5b0988e595225.cdn.sohucs.com/images/20180412/ab16cd8ce4af4f54a1de54be0914bf7f.jpeg);
border-image-slice: 100;
}写上了 border-image-slice 之后,border 四周就都有图像了,这里 border-image-slice 设置单独的属性 100,就是指四条线都以 100px 切割

我们可以对比原图像

正好就是把中间部分给他扣掉了,剩下的周围部分分别填入对应区域。并且上下左右都是按照 100 像素进行切割的。
我们可以使用正常的边框图像看一下

比如这个边框图像,
css
div {
width: 100px;
height: 100px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: 80px solid black;
border-image-source: url(https://bpic.588ku.com/element_origin_min_pic/19/03/07/52dd3e5e356d44083759f545e6afba8e.jpg);
border-image-slice: 200;
}设置样式之后,效果就很不错了

border-image-slice还可以填一个fill的可选属性,我们知道 CSS 会把边框图片分成九份,会把中间那一部分丢掉,如果填上这个fill属性,就会把中间那个丢弃的部分也填充上去,类似于一个背景图。
除此之外 border-image 还有一些附加属性,首先是 border-image-outset,这个属性可以让背景图片往外延伸。

可以看到随着这个属性的增加,边框是会往外延伸的,同时也可以看到这个属性如果设置为负数是无效的,并且这里只是显示上的往外扩展,实际的盒模型大小并没有发生变化。

可以看到,这里两个盒子同时设置 outset,只有显示上的往外扩展,第二个盒子并没有被向下顶,所以这也能说明这种延伸只是显示上的延伸,盒子大小并没有改变。
如果我将图像设置为非正方形,那效果就会是这样

很显然,这里图片被自动拉伸了,这个拉伸就是由 border-image-repeat 属性设置的,我们将其设置为 space,效果就如下图

可以看到虽然比例保持不变,但是图片直接被切割了,实际上如果高度再增加,会用多个图形填充。同样可以设置为 repeat,也就是平铺,这张图片比较特殊,平铺和拉伸效果一样,这里就不放图了。这个 border-image-repeat 一共就这几个值:repeat, stretch, round, space
round 和 space 用的会更多,round 可以看做是 stretch 和 repeat 的升级版,宽度不够就拉伸,宽度够了就会新增一个进来。space 就是会拿多个图像填充,如果距离不够塞下两个图形,就会在中间留空。
border-image-repeat支持传两个参数,第一个参数表示水平,第二个表示垂直
还有一个易混的属性,border-image-width,这个属性和 border-width 很像,这里做辨析。
border-width 表示整个边框的宽度,也就是盒模型中边框的宽度,border-image-width 则表示边框中用于显示图片的宽度,也就是说我的边框里不一定所有区域都用于显示边框,我们用这样一个例子来验证。

我们可以使用这个动图理解

可以看到,随着 border-image-width 的增加,边框中用于显示边框图片的区域也跟着增加了,一般情况下我们都希望 border-image-width 和 border-width 相等,在这种情况下,整个边框都会被用于显示边框图片,当 border-image-width 超过 border-width 的时候,边框图片的显示范围会突破边框的盒模型,侵入到内容区,这里也是显示上的侵入,并不会导致实际内容区变小,一般来说我们也不会让它超过边框大小。border-width 还可以取值为 auto,当取值为 auto 的时候,其值会取 border-image-slice 看齐,比如 border-image-slice 值为 100,那么 border-image-width 的值就是 100px。
同样,这里不能为负值,动图中也演示了负值无效