Skip to content

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 可以给四个角分别设置圆角,如果书写四个属性,设置圆角的顺序为左上-右上-右下-左下,上面的效果如图所示

6ed0f43891a24e53049746dbaf9ff99a_MD5

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

2854cf7b77ea9926b26c5623757cc1f5_MD5

注意这里的书写顺序,是先写上下,再写左右

我们这里还有更高级的用法,当我们写 border-top-left-radius:10px;,实际上写的是 border-top-left-radius:10px 10px;,二个我们一般都是默认省略掉的。

我们其实应该知道,圆角本质上是用一个圆切出来的,如图所示

d66de0c2d43072ebf211fb546219b4ed_MD5

如果两个值都填一样,或者只填一个值,例如 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;
}

9d70e0d2fb46c3386f895a5e181c34c6_MD5

此时下面两个角就是被椭圆切出来的,明显就和以前的圆角不一样。

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;
        }

当我们将一个角的半径拉到最大,我们就得到了一个四分之一圆。

b374d3cccbd6551aaa60110c73e62964_MD5

我们也可以用圆角来画半圆

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 轴上的偏移量。

0f804e4d0173bbe269522ffcf4687bcf_MD5

我们从这个变化过程可以得出以下结论

  • 方向和我们预期的一致,以右为 x 的正方向,以下为 y 的正方向,这是计算机中常见的坐标系。
  • 偏移量可以为负数,为负数表示向负方向偏移。

其实从这里也能感受到,阴影本质上就是一个和图像长得一模一样的色块,读者可以设置圆角试一下,设置圆角后阴影也会跟着被设上圆角。

这两个偏移量是必须要写的,inset 不写默认就是 outset ,也就是外阴影,写上 inset 才能表示内阴影,如果不写颜色默认也就是黑色。所以我们可以说 box-shadow 里面必须填上的有两个属性,分别是第一个是 x 轴偏移量,第二个是 y 轴偏移量。

如果在偏移量后面写上第三个长度单位,则表示模糊半径,如果再写第四个参数,则表示扩散范围。

d7caf2e9f8a9c0b9e5b5812cc9d5dba3_MD5

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

同时,模糊这个东西,是基于原来的位置,向边框两边同时扩散,我们可以这样验证

9cf80963566dbb684e55a48e8a83964d_MD5

读者通过这个例子可以看到,原来阴影和方块是完全对其的,模糊之后整个阴影的大小变大了。

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

f4b5fd98bd0a7c2190cb86a9a31acb9b_MD5

可以看到,扩散就是调整整个阴影的大小,随着扩散的增加,阴影的尺寸也会增加,扩散也可以为负数,当为负数的时候就是将原图形缩小。

扩散的增加是从四周增加,比如扩散了 10 像素,实际上整个阴影的大小是上下左右各增加了 10 像素,即上下增加了 20 像素,左右增加了 20 像素。

最后简要介绍内阴影

b276a249a380ea8c8c66b004c3d17d1a_MD5

这里把内阴影的四个值都给演示了一遍,说白了和外阴影差不多,前两个也是偏移量,第三个也是模糊,第四个也是扩散,用法一模一样,偏移量的方向也是一模一样。

阴影可以写多个

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;
        }

多个阴影中间用逗号隔开,此时就形成了四个不同方向的阴影

7a7a2720a7e5e46dec30d9f16274beab_MD5

如果设置多个阴影,是有层级次序的,最先设置的阴影是在逻辑的最上层的,也就是离我们最近,会把其他阴影覆盖掉。

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;
        }

我们通过这样设置多个阴影,就可以实现这样一个四个方向不同色阴影的效果

5334089ff1263150bf45be3d8cfe37c9_MD5

设置模糊会让边界变糊,这种糊其实是一种半透明的状态,如果我们写多个阴影,会让变糊部分的颜色加深。

有了阴影我们就可以作出一些非常好看的效果。

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>

343419cc380330b37dcbef19334b46d4_MD5

这里其实有一个层级关系,背景在最底层,阴影在背景之上,会盖住背景,文字在阴影之上,是最上层。

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);
        }

可以看到,此时这个边框就变成哈士奇了

48b9dbcbea469b71a54674e2cc4c7896_MD5

当我们设置了 border-image-source 之后,border-color 直接失效

但这里只有四个角变成图片了,这并不是我们希望的效果,这里就需要用到 border-image-slice 属性了

我们这里将一个实际的例子,设置背景颜色我们给的都是一个这个样子的图片

435f02d2544cd8b73fa3eb825f5920f1_MD5

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

1da87b06c38fe623c378bf52e24c7bfa_MD5

这张图会更加直观一点,可以看到这张图被四条线分成了 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 切割

2ffbab0c06f41d7df9ce259a4b4ef3c7_MD5

我们可以对比原图像

42c06c738b5325adf97eff899bbfc10a_MD5

正好就是把中间部分给他扣掉了,剩下的周围部分分别填入对应区域。并且上下左右都是按照 100 像素进行切割的。

我们可以使用正常的边框图像看一下

2a1f3884982ad1557a59ca70ee6e80d6_MD5

比如这个边框图像,

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;
        }

设置样式之后,效果就很不错了

5e9f1f8b37bae6c5bfe5a8e47400e6f5_MD5

border-image-slice 还可以填一个 fill 的可选属性,我们知道 CSS 会把边框图片分成九份,会把中间那一部分丢掉,如果填上这个 fill 属性,就会把中间那个丢弃的部分也填充上去,类似于一个背景图。

除此之外 border-image 还有一些附加属性,首先是 border-image-outset,这个属性可以让背景图片往外延伸。

df65418e0b00dbb7fb22a39650d53687_MD5

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

beccb29a1c0dc1fec421aa4ee6e2401c_MD5

可以看到,这里两个盒子同时设置 outset,只有显示上的往外扩展,第二个盒子并没有被向下顶,所以这也能说明这种延伸只是显示上的延伸,盒子大小并没有改变。

如果我将图像设置为非正方形,那效果就会是这样

7b76d8bea8ca710e8799789353b2ece9_MD5

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

3271ea66e8f81344867623809df4d354_MD5

可以看到虽然比例保持不变,但是图片直接被切割了,实际上如果高度再增加,会用多个图形填充。同样可以设置为 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 则表示边框中用于显示图片的宽度,也就是说我的边框里不一定所有区域都用于显示边框,我们用这样一个例子来验证。

941061aea26fbef11d2a8e6fa6ca0290_MD5

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

973358438a8be60f70e78c70d6cfe91a_MD5

可以看到,随着 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。

同样,这里不能为负值,动图中也演示了负值无效

以笔记为镜,可以知得失