ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] > 部分文章内容来源:《CSS SECRETS》 > 配套 demos:[http://play.csssecrets.io/](http://play.csssecrets.io/) # Part 1 背景与边框、形状、视觉效果 ## 背景与边框 <span style="color: MediumOrchid;font-size: 20px; font-family: 楷体; font-weight: bold;">使用 background-clip 属性控制背景的绘制区域</span> - border-box:背景被裁剪到边框盒 - padding-box:背景被裁剪到内边距盒(默认) - content-box:背景被裁减到内容框 这个属性的初始值是 border-box,意味着背景会被元素的 border-box (边框的外沿框)裁切掉。如果不希望背景侵入边框所在的范围,我们要做的就是把它的值设为 padding-box(使用内边距的外沿框来裁切背景)。 你可以通过下面这个半透明边框的例子来理解这个属性的使用: [http://dabblet.com/gist/012289cc14106a1bd7a5](http://dabblet.com/gist/012289cc14106a1bd7a5) <span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">多重边框</span> - box-shadow 方案:利用第四个参数(扩张半径)让投影面积增大或减小,box-shadow 支持逗号分隔语法,我们可以创建任意数量的投影; 有如下一些注意事项: 1.投影不会影响布局,也不受 box-sizing 属性的影响。 2.这种方法创建出的假 “边框” 不会响应鼠标事件,如果这一点非常重要,你可以给 box-shadow 属性加上 inset 关键字,来使投影绘制在元素的内圈。 3.box-shadow 是层层叠加的 ```css background: yellowgreen; box-shadow: 0 0 0 10px #655, 0 0 0 15px deeppink; ``` ![](https://box.kancloud.cn/3b6c2ae70261d9a13b1fec46abe26b49_434x425.png =200x) - outline 方案:在某些情况下,你可能只需要两层边框,那就可以先设置一层常规边框,再加行 outline(描边)属性来产生外层的边框。这种方式的优点是边框样式十分灵活(不像 box-shadow 只能模拟实线边框);另外,可以通过 outline-offset 属性来控制它跟元素边缘之间的间距。 ```css background: #333; border-radius: 5px; outline: 2px dashed white; outline-offset: -20px; ``` ![](https://box.kancloud.cn/75663f9148cd5b325807249b8b6ab3e6_270x146.png =200x) ***** 蚂蚁行军效果:[展示](http://dabblet.com/gist/f26dddc71730c3847153) 分析:[https://www.jianshu.com/p/04b69172ab9e](https://www.jianshu.com/p/04b69172ab9e) <span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">灵活的背景定位</span> 如果我们想针对容器某个角对背景图片做偏移定位,有如下一些解决方案 - background-position:该属性允许我们指定背景图片距离任意角的偏移量 举例来说,如果我们想让背景图片跟右边缘保持 20px 的偏移量,同时跟底边保持 10px 的偏移量,可以这样做: ```css background: url(code-private.svg) no-repeat #58a; background-position: right 20px bottom 10px; ``` demo 地址:[http://dabblet.com/gist/0f226e63595d1bef88cb](http://dabblet.com/gist/0f226e63595d1bef88cb) - background-origin:有时候我们希望偏移与容器的内边距一致,就可以利用这个属性,其规定了 background-position 的偏移是以什么为基准(边距还是内容) ![](https://img.kancloud.cn/bc/95/bc9544d9ae33674bfbd4200c25ef3f22_498x316.png =300x) 我们也许写过这样的代码:`background-position: top left;`,那么这个 top、left 到底是哪个左上角?每个元素都存在如上图的三个矩形框:content box(内容区的外沿框)、padding box(内边距的外沿框)、border box(边框的外沿框),默认情况下,background-position 是以 padding-box 为准的,这样边框才不会遮住背景图片。因此,top left 默认指的是 padding box 的左上角。 现在,你可以用 background-origin 属性来改变这个默认行为,它的默认值是 padding-box,如果修改为 content-box,那么 background-position 属性中使用的边角关键字将会以内容区的边缘作为基准。 <span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">渐变</span> 渐变就是一种代码生成的图像,先设置一个最基础的: ```css background: linear-gradient(#fb3, #58a); ``` ![](https://box.kancloud.cn/32fbc61f791d8c3c2cf9c79a9037504c_271x263.png =150x) 然后我们试着把这两个色标拉近一点: ```css background: linear-gradient(#fb3 20%, #58a 80%); ``` ![](https://box.kancloud.cn/d81e8dadfec5f29c7dbf49ca6db2c5c6_275x267.png =150x) 现在容器顶部的 20% 区域被填充为 #fb3 实色,而底部 20% 区域被填充为 #58a 实色,真正的渐变只出现在容器 60% 的高度区域。 >[success] 是否可以这么理解?把色标位置值想成在距离顶部多少位置画一条线,只有这两条线之间的部分才有渐变。且最后一个色标位置之后都是该色标颜色。 如果我们把两个色标重合在一起会发生什么? ```css background: linear-gradient(#fb3 50%, #58a 0); /* 第二个色标的位置值设置为 0,那么它的位置就和前一个色标的位置值相同 */ ``` ![](https://box.kancloud.cn/586b891ec428a0595de73d6162fa7772_271x268.png =150x) 可以看到:已经没有任何渐变效果了,只有两块实色,各占据 background-image 一半的面积。 <span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">水平条纹</span> 因为渐变是一种由代码生成的图像,所以我们能像对待其他任何背景图像那样对待它,而且还可以通过 background-size 来调整其尺寸: ```css /* 左图-没有平铺的情况 */ background: linear-gradient(#fb3 50%, #58a 0) no-repeat; background-size: 100% 30px; /* 右图 */ background: linear-gradient(#fb3 50%, #58a 0); background-size: 100% 30px; ``` ![](https://box.kancloud.cn/3cdb8b445d99bf2b876f05f6a4041c2c_651x274.png) 我们还可以创建多种颜色、不等宽的条纹: ```css background: linear-gradient(#fb3 33.3%, #58a 0, #58a 66.6%, yellowgreen 0); background-size: 100% 45px; ``` ![](https://box.kancloud.cn/91e973e149da1b10e4a5319cf2812892_266x263.png =200x) <span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">垂直条纹</span> 对于垂直条纹,我们需要在开头加上一个额外的参数来指定渐变的方向(默认 to bottom),然后,还需要把 background-size 的值颠倒一下: ```css background: linear-gradient(to right, /* 或 90deg*/ #fb3 50%, #58a 0); background-size: 30px 100%; ``` ![](https://box.kancloud.cn/e0d7d4e6e92cdd7347e055c985d79843_267x270.png =150x) <span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">斜向条纹</span> 对于斜向条纹,我们可以利用 repeating-linear-gradient() 和 repeating-radial-gradient() 这两个 linear-gradient() 和 radial-gradient() 的循环式加强版,它们的工作方式与之前的类似,只有一点不同:**色标是无限循环重复的,直到填满整个背景**。(这里我就不记为啥只用 linear-gradient() 不好实现斜向渐变了,感兴趣的自己尝试) ```css background: repeating-linear-gradient(45deg, #fb3, #58a 30px); ``` 它相当于下面这样: ```css background: linear-gradient(45deg, #fb3, #58a 30px, #fb3 30px, #58a 60px, #fb3 60px, #58a 90px, #fb3 90px, #58a 120px,...) ``` ![](https://box.kancloud.cn/ceaac8b4a251711a61563a1e8d13809c_267x267.png =150x) <span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">灵活的同色系条纹</span> 大多数情况下,我们想要的条纹图案并不是由差异极大的几种颜色组成的,这些颜色往往属于同一色系。我们可以把最深的颜色指定为背景色,同时把半透明白色的条纹叠加在背景色之上来得到浅色条纹: ```css background: #58a; background-image: repeating-linear-gradient(30deg, hsla(0, 0%, 100%, .1), hsla(0, 0%, 100%, .1) 15px, transparent 0, transparent 30px); ``` ![](https://box.kancloud.cn/799f7d94ed255c6f5ee8736ccdfa2f84_266x147.png =150x) ### 实现常用的图案 只使用一个渐变时,我们能创建的图案并不多,当我们把多个渐变图案组合起来,让它们透过彼此的透明区域显现时,神奇的事情就发生了。 <span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">网格</span> 我们让水平和垂直的条纹叠加起来,就能得到各式各样的网格: ```css background: white; background-image: linear-gradient(90deg, rgba(200, 0, 0, .5) 50%, transparent 0), linear-gradient( rgba(200, 0, 0, .5) 50%, transparent 0); background-size: 30px 30px; ``` ![](https://box.kancloud.cn/20c743ba0e0a17879b329d1d69f2d5a1_200x208.png =150x) <span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">图纸效果</span> ```css background: #58a; background-image: linear-gradient(white 1px, transparent 0), linear-gradient(90deg, white 1px, transparent 0); background-size: 30px 30px; ``` ![](https://box.kancloud.cn/9091269c185dd1e58012a6e6996328c0_201x207.png =150x) <span style="color: MediumOrchid;font-size: 20px;font-family: 楷体; font-weight: bold;">波点</span> 径向渐变允许我们创建圆形、椭圆,或是它们的一部分。 ```css background: #655; background-image: radial-gradient(tan 30%, transparent 0), radial-gradient(tan 30%, transparent 0); background-size: 30px 30px; background-position: 0 0, 15px 15px; /* 让背景定位错开 */ ``` ![](https://box.kancloud.cn/69b7f027a109f76fa89d1ff7ec434276_205x205.png =150x) 为了达到效果,第二层背景的偏移定位值必须是贴片宽高的一半,这意味着如果要改动贴片的尺寸,需要修改四处。这样代码就很难维护,我们可以写一个 mixin: ```css @mixin polka($size, $dot, $base, $accent) { background: $base; background-image: radial-gradient($accent $dot, transparent 0), radial-gradient($accent $dot, transparent 0); background-size: $size $size; background-position: 0 0, $size / 2 $size / 2; } // 在创建波点图案时,我们就可以这么调用它 @include polka(30px, 30%, #655, tan); ``` ## 形状 ### border-radius 四个属性值:border-radius:10px   20px   30px  40px; 表示左上角、右上角、右下角、左下角的圆角大小(**顺时针方向**) ![](https://img.kancloud.cn/9b/ca/9bca20db5976ea3581b7ac6bb74d7700_350x269.png =200x) <br/> 三个属性值:border-radius:10px   30px  60px; 第一个值表示左上角,第二个值表示右上角和左下角(对角),第三个值表示右下角。 ![](https://img.kancloud.cn/37/20/37208f9a1f09121523dc9a759be36739_369x278.png =200x) <br /> 两个属性值:border-radius:20px  40px; 第一个值表示左上角和右下角,第二个值表示右上角和左下角。 ![](https://img.kancloud.cn/f2/44/f244e06cd8d4297ce8e6a0b6f33dba1f_332x273.png =200x) 斜杠二组值:第一组值表示水平半径,第二组值表示垂直半径,每组值也可以同时设置1到4个值,规则与上面相同。 ```css border-radius: 2em 1em 4em / 0.5em 3em; ``` 等价于: ```css border-top-left-radius: 2em 0.5em; border-top-right-radius: 1em 3em; border-bottom-right-radius: 4em 0.5em; border-bottom-left-radius: 1em 3em; ``` 一个沿纵轴劈开的椭圆: ```css border-radius: 100% 0 0 100% / 50%; ``` 四分之一椭圆: ```css border-radius: 100% 0 0 0; ``` 鸡蛋: ```css .egg { width: 120px; height: 160px; background: #EC0465; border-radius: 60px 60px 60px 60px/100px 100px 60px 60px; } ``` 花瓣: ```css .flower { width: 120px; height: 120px; background: #EC0465; border-radius: 60px 60px 0 60px; } ``` ![](https://box.kancloud.cn/f81ca538670b4cdf6e59b524ae0f66e1_1131x209.png) ### 平行四边形 我们可以通过 skew() 的变形属性来对元素进行斜向拉伸,但是这会导致该元素的内容也斜向变形,有没有办法只让容器的形状倾斜,而保持其内容不变呢? 1.嵌套元素方案 我们可以对内容再应用一次反向的 skew() 变形,从而抵消容器的变形效果,不过这意味着我们需要添加额外的 HTML 元素。 ```html <a href="#" class="button"> <div>Click me</div> </a> .button { transform: skewX(-45deg); } .button > div { transform: skewX(45deg); } ``` 2.伪元素方案 我们把所有的样式(背景、边框等)应用到伪元素上,然后再对伪元素进行变形。 我们希望伪元素保持良好的灵活性,可以自动继承其宿主元素的尺寸,甚至当宿主元素的尺寸是由其内容来决定时仍然如此。一个简单的办法就是给宿主元素应用 position:relative 样式,并为伪元素设置 position:absolute,然后把所有偏移量设置为零,以便让它在水平和垂直方向上都被拉伸至宿主元素的尺寸。 ```css .button { position: relative; /* 其他的文字颜色、内边距等样式 */ } .button::before { content: ''; position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: -1; /* 防止遮住内容 */ background: #58a; transform: skew(45deg); } ``` ![](https://box.kancloud.cn/4d171bda2788ee8804d2d472a39ec0a2_216x88.png =150x) ### 菱形图片 裁切路径方案:使用 clip-path 属性,它允许我们使用一系列以逗号分隔的坐标点来指定任意的多边形,百分比值会被解析为元素自身的尺寸。 ```css clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%); ``` 我们甚至可以利用这个属性来实现动画效果: ```css img { clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%); transition: 1s clip-path; } img:hover { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); } ``` ![](https://box.kancloud.cn/33c52fb43812bbd3a2429904ea766788_320x236.gif) 相关属性值介绍:[https://www.jb51.net/css/601746.html](https://www.jb51.net/css/601746.html) ## 视觉效果 ### 投影 ```css { box-shadow: none| [inset? && [ <offset-x> <offset-y> <blur-radius>? <spread-radius>? <color>? ] ] } ``` 以 `box-shadow: 1px 2px 3px 4px #333` 为例,4 个数值的含义分别是,x 方向偏移值、y 方向偏移值 、模糊半径、扩张半径。 >扩张半径是以阴影的外边界向外扩展(为正数)或者向内抵消原来的阴影(为负数),当负数绝对值大于等于某方向的阴影偏移量时,该方向的阴影消失。 <iframe height="300" style="width: 100%;" scrolling="no" title="阴影属性" src="//codepen.io/chenmingk/embed/Bgazpw/?height=265&theme-id=0&default-tab=css,result" frameborder="no" allowtransparency="true" allowfullscreen="true"> See the Pen <a href='https://codepen.io/chenmingk/pen/Bgazpw/'>阴影属性</a> by 陈明康 (<a href='https://codepen.io/chenmingk'>@chenmingk</a>) on <a href='https://codepen.io'>CodePen</a>. </iframe> 如果我们想实现双侧投影呢?(比如左侧和右侧),可以把 “单侧投影” 运用两次: ```css box-shadow: 5px 0 5px -5px black, -5px 0 5px -5px black; ``` <span style="font-family: 楷体; font-size: 20px; color: #007fff; font-weight: bold;">不规则投影</span> 难题:当我们想给一个矩形或其他能用 border-radius 生成的形状加投影时,box-shadow 的表现都堪称完美。但是,当元素添加了一些伪元素或半透明的装饰之后,它就有些力不从心了,因为 border-radius 会忽视透明部分。这类情况包括: - 半透明图像、背景图像、或者 border-image - 元素设置了点状、虚线或半透明的边框,但没有背景(或者当 background-clip 不是 border-box 时) - 对话气泡,它的小尾巴通常是用伪元素生成的 - 几乎所有的折角效果 - 通过 clip-path 生成的形状 解决方案:(不完全支持所有浏览器) [滤镜效果规范](http://w3.org/TR/filter-effects) 为这个问题提供了一个解决方案。它引入了一个叫作 filter 的新属性,这个属性也是从 SVG 那里借鉴过来的。尽管 CSS 滤镜基本上就是 SVG 滤镜,但我们并不需要掌握任何 SVG 知识,只需要一些函数就可以很方便地指定滤镜效果了,比如 blur()、grayscale()、以及我们需要的 drop-shadow()。我们甚至可以把多个滤镜串连续起来,如下: ```css filter: blur() grayscale() drop-shadow(); ``` drop-shadow() 滤镜可接受的参数基本上跟 box-shadow 属性是一样的,但不包括扩展半径,不包括 inset 关键字,也不支持逗号分隔的多层投影语法。 ![](https://img.kancloud.cn/11/3e/113ec62b8c1ebe246403842c930c8614_844x235.png) demo 地址:[http://dabblet.com/gist/d8a2376c79906d68f3d1](http://dabblet.com/gist/d8a2376c79906d68f3d1) <br/> CSS 滤镜最大的好处在于,它们可以平稳退化:当浏览器不支持时,不会出现问题,只不过没有任何效果而已。 # Part2 字体排印、用户体验、结构与布局、过渡与动画