前言
《CSS揭秘》,由Lea Verou编著,由CSS魔法翻译,本篇主要记录阅读《CSS揭秘》过程中的一些要点及收获
第二章 背景与边框
box-shadow与outline
box-shadow
利用box-shadow
可以绘制多重边框,设置其前三个变量均为0(h-shadow、v-shadow、blur),然后使用spread
为边框宽度;这里需要注意的是默认是外边框的,那么比如hover、点击等在box-shadow
绘制的边框处是无法触发这些动作的;
为了解决该问题,可以设置box-shadow
的第五个变量inset
,使其变为内部阴影;
outline
outline (轮廓)是绘制于元素周围的一条线,
位于边框边缘的外围
,可起到突出元素的作用;
它有三个属性,包括outline-color
、outline-style
、outline-width
;另外,可以设置outline-offset
对边框进行偏移,支持负值;
可以结合W3School的demo理解;
条纹背景
利用linear-gradient()
函数可以实现。
linear-gradient() 简介
CSS
linear-gradient()
函数用于创建一个表示两种或多种颜色线性渐变的图片。其结果属于<gradient>
数据类型,是一种特别的<image>
数据类型。
/* 渐变轴为45度,从蓝色渐变到红色 */
linear-gradient(45deg, blue, red);
/* 从右下到左上、从蓝色渐变到红色 */
linear-gradient(to left top, blue, red);
/* 从下到上,从蓝色开始渐变、到高度 40% 位置是绿色渐变开始、最后以红色结束 */
linear-gradient(0deg, blue, green 40%, red);
/* 等同于180deg */
linear-gradient(0.5turn, red, green, blue);
线性渐变由一个轴 (梯度线) 定义,其上的每个点具有两种或多种的颜色,且轴上的每个点都具有独立的颜色。为了构建出平滑的渐变,linear-gradient() 函数
构建一系列垂直于渐变线的着色线
,每一条着色线的颜色则取决于与之垂直相交的渐变线上的色点
具有多个颜色停止的渐变
如果第一个颜色中间点没有<length>
或<percentage>
属性,那么它默认为 0%。如果最后一个颜色中间点没有<length>
或者<percentage>
属性,则默认为 100%。如果一个既不是起始也不是终止的颜色中间点,没有被明确声明位置,那么这个颜色就会从前后两个颜色的中间位置开始。
由于
background-size
可以定义背景大小,因此我们可以通过调整背景大小调整布局
background: linear-gradient(green 50%, red 50%);
background-size: 100% 30%;
background-repeat: no-repeat;
如果设置了background-repeat: repeat
,那就回得到一个重复填充的条纹背景了。
类似的,我们通过调整linear-gradient
函数作用的角度,就可以产生竖条纹、斜条纹等;
另外,我们可以通过
repeating-linear-gradient
和repeating-radial-gradient
函数实现循环式的渐变
下面的demo通过repeating-linear-gradient()
函数实现重复性条纹
background: repeating-linear-gradient(red, red 1em, green 0, green 2em);
复杂的背景图案
网格
借鉴上面的条纹背景的思路,我们可以将水平条纹和垂直条纹结合起来就可以得到网格背景;
width: 14em;
height: 8em;
background: white;
background-image: linear-gradient(rgba(200, 0, 0, .5) 50%, transparent 0),
linear-gradient(90deg, rgba(200, 0, 0, .5) 50%, transparent 0);
background-size: 30% 30%;
另外一些情况我们可以调整网格大小,但是网格线粗细会保持固定,demo如下:
background: orange;
background-image: linear-gradient(white 1px, transparent 0),
linear-gradient(90deg, white 1px, transparent 0);
background-size: 30% 30%;
波点
使用径向渐变我们可以创建圆形、椭圆或它们的一部分;径向渐变能够创建的最简单的图案是圆点的阵列;
background: rgb(188, 205, 0);
background-image: radial-gradient(orange 30%, transparent 0);
background-size: 50px 50px;
当然,可以通过两个渐变实现错位叠加,这里需要注意的是:第二个背景的偏移定位值必须是贴片宽高的一半
。
background: rgb(188, 205, 0);
background-image: radial-gradient(orange 30%, transparent 0),
radial-gradient(orange 30%, transparent 0);
background-size: 50px 50px;
background-position: 0 0, 25px 25px;
第三章 形状
自适应的椭圆
这里使用到的属性是border-radius
,我们可以先了解下它的属性
该属性是一个 简写属性,是为了将这四个属性
border-top-left-radius
、border-top-right-radius
、border-bottom-right-radius
,和border-bottom-left-radius
简写为一个属性
border-radius: 1em/5em;
/* 等价于 */
border-top-left-radius: 1em 5em;
border-top-right-radius: 1em 5em;
border-bottom-right-radius: 1em 5em;
border-bottom-left-radius: 1em 5em;
border-radius: 4px 3px 6px / 2px 4px;
/* 等价于 */
border-top-left-radius: 4px 2px;
border-top-right-radius: 3px 4px;
border-bottom-right-radius: 6px 2px;
border-bottom-left-radius: 3px 4px;
半椭圆
border-radius: 100% 0 0 100%/50%;
// 等价于
border-top-left-radius: 100% 50%;
border-top-right-radius: 0 50%;
border-bottom-right-radius: 0 50%;
border-bottom-left-radius: 100% 50%;
四分之一椭圆
border-radius: 100% 0 0 0;
// 等价于
border-top-left-radius: 100%;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
变形
border-radius: 100% 0;
// 等价于
border-top-left-radius: 100%;
border-top-right-radius: 0px;
border-bottom-right-radius: 100%;
border-bottom-left-radius: 0px;
带文本的平行四边形
这里最基本的思路是使用嵌套元素方案,可以在外层使用skew
,然后在内层使用一次反向的skew
对内容的形变效果进行还原。
这种方案的弊端是引入了额外的HTML元素,未保持HTML结构层的纯净度;
另一种思路是使用伪元素。
内容定义在外层,伪元素则进行形变处理;需要注意的是,伪元素生成的区域默认是重叠在内容之上的
,需要通过设置z-index: -1
进行调整;
<div class="wrapper">Click me</div>
.wrapper {
position: relative;
display: inline-block; // 设置为inline-block让其随大小文本内容变化;
padding: .5em 1em; // 文字周围留白调整
text-transform: uppercase; // text-transform: capitalize
}
.wrapper::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #66f;
z-index: -1; // 调整堆叠层次,让主题文本位于上层
transform: skew(-45deg);
}
菱形图片
基本思路是讲一个图片用div包裹起来,然后对其应用相反的rotate()
变形样式
<div class="pic">
<img src="*.jpg" alt="..." />
</div>
<style>
.pic {
width: 200px;
transform: rotate(45deg);
overflow: hidden;
}
.pic > img {
max-width: 100%; // 这里需要注意的是仅展示为max-width为100%是不足以撑起旋转后的容器的,旋转后的容器宽度为`width * 1.414213..`
transform: rotate(-45deg) scale(1.42); // 所以这里需要进行缩放铺满容器才能展示为菱形
}
</style>
与平行四边形的hack实现类似,这里我们实现菱形图片也使用了额外的HTML标签,不够简洁直观。
clip-path简介
现在我们引入一种新的方式实现——clip-path
。我们可以看看MDN中的相关定义:
The clip-path CSS property creates a clipping region that sets what part of an element should be shown. Parts that are inside the region are shown, while those outside are hidden.
大概意思就是说通过clip-path
属性可以创建一个裁剪区域,区域内部的部分可以展示,区域外部的内容会被隐藏,符合我们制作菱形图片的需求。
取值
<clip-source>
用url()
引用 SVG 的 元素<basic-shape>
inset
: 定义一个inset矩形circle
: 定义一个圆形(半径、圆心位置)ellipse
: 定义一个椭圆(半径、圆心位置)polygon
: 定义一个多边形(使用一个SVG填充规则和一组顶点)path
: 定义一个任意形状(使用一个可选的 SVG 填充规则和一个 SVG 路径定义)
<geometry-box>
margin-box
:border-box
padding-box
content-box
fill-box
stroke-box
:笔触边界框view-box
:使用最近的SVG视口作为引用框
- none
CSS计算值不为
none
时会创建新的层叠上下文
以下通过clip-path
实现菱形图片
img {
width: 300px;
height: 300px;
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%);
}
切角效果
三角形切角
一个三角形切角我们可以借助背景的线性渐变实现;
div {
background: #58a;
background: linear-gradient(-45deg, transparent 15px, #58a 0);
background-size: 100% 100%;
}
要实现2个角是三角形切角,那么需要使用两个线性渐变效果,同时设置background-size
为原来的一半50% 100%
,并且设置background-repeat: no-repeat
同理,可以实现四个角都是三角形切角的效果
background: #58a;
background: linear-gradient(-45deg, transparent 20px, #58a 0) bottom right,
linear-gradient(45deg, transparent 20px, #58a 0) bottom left,
linear-gradient(135deg, transparent 20px, #58a 0) top left,
linear-gradient(-135deg, transparent 20px, #58a 0) top right;
background-size: 50% 50%;
background-repeat: no-repeat;
弧形切角
类似地,我们可以通过radial-gradient(circle)
实现,弧形位置大小我们可以通过调整圆心位置实现不同的弧度;另外,我们也可以通过radial-gradient(ellipse)
实现;
background: #58a;
background: radial-gradient(circle at top left, transparent 30px, #58a 0) top left,
radial-gradient(circle at top right, transparent 30px, #58a 0) top right,
radial-gradient(circle at bottom right, transparent 30px, #58a 0) bottom right,
radial-gradient(circle at bottom left, transparent 30px, #58a 0) bottom left;
background-size: 50% 50%;
background-repeat: no-repeat;
裁切路径方案
使用clip-path
进行路径裁剪
background: #58a;
clip-path: polygon(
20px 0, calc(100% - 20px) 0,
100% 20px, 100px calc(100% - 20px),
calc(100% - 20px) 100%, 20px 100%,
0 calc(100% - 20px), 0 20px
);
梯形标签
三维世界中根据透视关系,旋转一个矩形,我们看到的二维图像往往是一个梯形,因此我们可以使用3D旋转模拟该效果
需要注意的是,这里3D变换时应用在整个元素的,如果内部有蚊文字,其也会产生形变,并且不可逆转
,这与2D变换是不同的; 因此更好的方式是在其伪元素上进行变换
/**
* Beveled corners — with clip-path
*/
div {
position: relative;
display: inline-block;
padding: .5em 1em .35em;
max-width: 12em;
color: white;
font: 150%/1.6 Baskerville, Palatino, serif;
}
div::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: -1;
background: #58a;
transform: perspective(1em) rotateX(4deg);
transform-origin: bottom; // 重设变换中心
// transform-origin: bottom left; // 单侧倾斜
}
简单的饼图
饼状图的日常应用比较广泛,比如日常的占比统计、进度指示器、定时器等等,但使用web直接绘制饼图并没有直接可用的现成方法。
基于transform的解决方案
基本思路是使用一个圆形,背景进行线性渐变,使得一半为基准色,另一部分为扇区颜色;然后通过伪元素的方式以基准色填充的矩形进行旋转,并对矩形以border-radius方式约束其在园内展示;这样,就可以通过旋转角度控制要展示的扇区的大小。
这样处理的优点是仅使用一个HTML元素作为容器,其他的通过伪元素和CSS渐变及变换实现。
// 首先使用以下样式展示一个黄绿色背景的圆,然后使用linear-gradient使其左半圆为恍惚色,右半圆使用
// #655填充
div {
position: relative;
display: inline-block;
margin: 2em;
width: 10em;
height: 10em;
background: yellowgreen;
border-radius: 50%;
background-image: linear-gradient(90deg, transparent 50%, #655 0);
}
于是得到了上面的图形,基于此,我们再借助伪元素实现对右半圆的部分遮盖,从而展示扇区;
为了使伪元素与圆形的切面是扇区,需要设定旋转中心为圆心,即伪元素的左边长的中点;
div::before {
content: '';
display: block;
margin-left: 50%;
height: 100%;
border-radius: 0 100% 100% 0 / 50%;
background-color: inherit;
transform: rotate(45deg);
transform-origin: left;
}
上面方案的局限性是最大角度只能是半圆,为了实现大于50%的扇区,可以对称操作;
/**
* Animated pie chart
*/
.pie {
width: 100px; height: 100px;
border-radius: 50%;
background: yellowgreen;
background-image: linear-gradient(to right, transparent 50%, currentColor 0);
color: #655;
}
.pie::before {
content: '';
display: block;
margin-left: 50%;
height: 100%;
border-radius: 0 100% 100% 0 / 50%;
background-color: inherit;
transform-origin: left;
animation: spin 3s linear infinite, bg 6s step-end infinite;
}
@keyframes spin {
to { transform: rotate(.5turn); }
}
@keyframes bg {
50% { background: currentColor; }
}
视觉效果
首先了解下box-shadow
绘制原理:
它是在原来元素的位置上绘制相同尺寸的矩形,然后根据第一和第二个参数进行指定方向偏移;然后使用高斯模糊算法进行模糊处理,这里注意实际发生模糊的区域宽度近似与模糊半径(第三个参数)的两倍;模糊后的矩形与原始元素的交集部分被切除;(这里需要注意阴影层级是在上方);
它排在
模糊半径参数之后, 称作扩张半径
。 这个参数会根据你指定的值去扩大或
(当指定负值时) 缩小投影的尺寸。 举例来说, 一个 -5px 的扩张半径会把投
影的宽度和高度各减少 10px(即每边各 5px)。
单侧投影
双边投影
不规则投影
当元素添加了一些伪元素或半透明的装饰之后, 它就有些力不从心了, 因为
border-radius 会忽视透明部分
,导致box-shadow
不能产生预期的效果。 这类情况包括:
- 半透明图像、 背景图像、 或者 border-image(比如老式的金质像框);
- 元素设置了点状、 虚线或半透明的边框, 但没有背景( 或者当
background-clip 不是 border-box 时);- 对话气泡, 它的小尾巴通常是用伪元素生成的;
- 我们在“切角效果”一节中见过的切角形状;
- 几乎所有的折角效果, 包括“折角效果”一节将提到的例子;
- 通过 clip-path 生成的形状, 比如“菱形图片”一节中提到的菱形
图像。
使用CSS3的新属性filter
可以完美解决该问题;
filter可以同时f支持多个滤镜效果,只需要使用空格将它们串联起来即可;
filter: blur() grayscale() drop-shadow();
drop-shadow()
支持和box-shadow()
基本一致的参数,除了扩张半径、inset关键字及逗号分割的多段阴影预发;
box-shadow(2px 3px 4px rgba(0, 0, 0, 0.5));
// 等价于
filter: drop-shadow(2px 3px 4px rgba(0, 0, 0, 0.5));
CSS 滤镜最大的好处在于, 它们可以平稳退化: 当浏览器不支持时, 不
会出现问题, 只不过没有任何效果而已。 如果你确实需要这个效果在尽可
能多的浏览器中显示出来, 可以同时附上一个 SVG 滤镜, 这样可以得到稍
微好一些的浏览器支持度。 你可以在滤镜效果规范( http://www.w3.org/TR/
filter-effects/) 中为每个滤镜函数找到对应的 SVG 滤镜版本
任何非透明的部分都会被一视同仁地打上投影, 包括文本( 如果背景是透明的)
text-shadow
并不能取消drop-shadow()
对文本加的阴影效果,因为两者的实现机制并不相干;另外,如果已经用text-shadow
给文本加阴影,drop-shadow
会给阴影再次加阴影,导致出现非预期效果;
染色效果
常见的一些filter介绍
blur()
Blurs the image.
接受长度px/rem等;
brightness()
Makes the image brighter or darker.
接受number/percentage. <100%-darker, >100%-brighter
contrast()
Increases or decrease the image’s contrast.
接受number/percentage. <100%-decrease, >100%-increase
grayscale()
Converts the image to grayscale
接受number/percentage. 0-100%表示grayscale程度
drop-shadow()
Applies a drop shadow behind the image
hue-rotate(angle)
Changes the overall hue of the image.
0-不改变,angle>0: increase the hue; angle<0: decrease the hue;
invert()
Inverts the colors of the image.
接受number/percentage. 0%-unchanged, 100%-completely invert
opacity()
Makes the image transparent.
saturate()
Super-saturates or desaturates the input image.
saturate(0); /* Completely unsaturated */
saturate(.4); /* 40% saturated */
saturate(100%); /* No effect */
saturate(200%); /* Double saturated */
sepia()
Converts the image to sepia.(转换图片为棕褐色)
接受number/percentage. 0%-unchanged, 100%-completely sepia
基于混合模式的方案
“混合模式”控制了上层元素的颜色与下层颜色进行混合的方式。 用它来实现染色效果时, 需要用到的混合模式是
luminosity
。 这种 luminosity 混合模式会保留上层元素的 HSL 亮度信 息
, 并从它的下层吸取色相和饱和度信息
。
混合模式相关的有两个属性:
- mix-blend-mode: 为整个元素设置混合模式; 是把整个元素向下进行混合,
而不管它的下层是什么 - background-blend-mode: 为每层背景单独指定混合模式;可以让每层背景跟它的下层背景进行混合, 但并不关心
元素之外是什么情况。
对应的,我们有两中选择:
- 第一种选择: 需要把图片包裹在一个容器中, 并
把容器的背景色设 置为我们想要的主色调
。 - 第二种选择: 不用图片元素, 而是用
元素——把这个元素的
第一层背景设置为要染色的图片, 并把第二层的背景设置为我们想
要的主色调。
<a href="">
<img src="xxx" alt="xxx" />
</a>
毛玻璃效果
背景
半透明颜色最初的使用场景之一就是作为背景。 将其叠放在照片类或其他花哨的背层1①之上, 可以减少对比度, 确保文本的可读性。 这种效果确实很有视觉冲击力, 但仍然可能导致文字很难阅读, 特别是当不透明度较低或背层图案太过花哨时。
增加背景色的 alpha 值(不透明度)可以改善文本可读性的问题,但同时也让整个设计变得无趣了
在传统的平面设计中, 这个问题的解决方案通常是把文本层所覆盖的那部分图片区域作模糊处理。
借助 blur() 滤镜, 我们在 CSS 中获得了对元素进行模糊处理的能力。我们在 SVG 中很早就可以使用模糊滤镜了, 而这个 CSS 滤镜本质上就是它的硬件加速对应版本。
不过, 如果我们直接在这个例子中使用 blur() 滤镜,整个元素都会被模糊, 文本反而变得更加无法阅读了。 有没有某种方法可以只对元素的背层(即被该元素遮住的那部分背景) 应用这个滤镜呢?
由于我们不能直接对元素本身进行模糊处理, 就对一个伪元素进行处理, 然后将其定位到元素的下层, 它的背景将会无缝匹配
<body>
的背景。
使用
blur()
滤镜基本实现了效果,但模糊效果在边缘处会逐渐消退,削弱了毛玻璃的视觉效果。这是因为模糊效果会削减实色像素所能覆盖的范围, 削减的幅度正是模糊半径的长度。
为了补偿这种情况, 我们需要让伪元素相对其宿主元素的尺寸再向外扩大至少 20px( 即它的模糊半径)。 可以通过 -20px 的外边距来达到目的, 由于不同浏览器的模糊算法可能存在差异, 用一个更大的绝对值( 比如 -30px) 会更保险一些。
Demo代码示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Static Template</title>
<style>
body,
main::before {
background: url("https://www.abercrombiekent.co.uk/-/media/abercrombieandkent/images/blog/2018/destinations/indian-subcontinent/india/travelogue-spotting-tiger-in-india/main-india-tiger.jpg?la=en&hash=E63B661921E2F25409526C30B8D7A316CE63FC45")
0 / cover fixed;
}
main {
position: relative;
background: hsla(0, 0%, 100%, 0.3);
width: 70%;
height: 300px;
margin: 0 auto;
border-radius: 8px;
overflow: hidden;
}
main::before {
content: "";
margin: -30px;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
/* background: rgba(255, 0, 0, 0.3); */
z-index: -1;
filter: blur(10px);
}
</style>
</head>
<body>
<main>
<blockquote>
"The only way to get rid of a temptation[...]"
<footer>-<cite>Oscar Wilde, The Picture of Dorian Gray</cite></footer>
</blockquote>
</main>
</body>
</html>
效果示意
查看demo效果
折角效果
背景
我们已经拥有了一些实用的纯 CSS 实现方案, 其中某些技巧早在 2010 年就由伪元素大师 Nicolas Gallagher( http://nicolasgallagher.com/pure-css-folded-corner-effect) 发表了。 这些方法的基本原理通常是在右上角增加两个三角形: 一个三角形用来体现折页的形状, 另一个白色的三角形遮住元素的一角, 用来模拟翻折所产生的缺口。 这两个三角形通常都是由经典的边框技巧来生成的
字体排印
连字符断行
使用新的CSS属性hyphens
,它有三个属性值:auto
`none\
manual`;
- manual: 默认值,表示可以手工插入软连字符实现断行;
- none: 禁止上述行为;
- auto: 自动实现断行效果;当然,最好在
HTML
标签的lang
属性中指定对应的语言;
新的CSS标准引入更多属性进行更细粒度的控制:
- hyphenate-limit-lines
- hyphenate-limit-chars
- hyphenate-limit-zone
- hyphenate-limit-last
- hyphenate-character
插入换行
实际上, 有一个 Unicode 字符是专门代表换行符的: 0x000A ①。 在 CSS 中,
这个字符可以写作 “\000A”, 或简化为 “\A”。 我们可以用它来作为 ::after
伪元素的内容, 并将其添加到每个元素的尾部
dd + dt::before {
content: '\A';
white-space: pre;
}
dd + dd::before {
content: ', ';
font-weight: normal;
}
文本行的斑马条纹
思考如何使用css实现以下效果
pre {
padding: .5em;
line-height: 1.5;
background: hsl(20, 50%, 95%);
background-image: linear-gradient(
rgba(120,0,0,.1) 50%, transparent 0);
background-size: auto 3em;
background-origin: content-box;
font-family: Consolas, Monaco, monospace;
}
code { font: inherit }
调整 tab 的宽度
属性tab-size
可以用来设置tab表示的字符宽度;
pre {
tab-size: 4;
}
自定义下划线
可以通过线性渐变的背景实现该效果
background: linear-gradient(gray, gray) no-repeat;
background-size: 100% 1px;
background-position: 0 1.15em;
使用渐变来实现下划线的高明之处在于, 这些线条极为灵活。 举例来
说, 如果要生成一条虚线下划线(参见图 5-26), 可以这样做:
background: linear-gradient(90deg,
gray 66%, transparent 0) repeat-x;
background-size: .2em 2px;
background-position: 0 1em;
然后, 就可以通过色标的百分比位置值来微调虚线的虚实比例, 还可以
通过 background-size 来改变虚线的疏密。
可以点击此处查看demo效果
波浪形下划线
未来的文本下划线
- text-decoration-color 用于自定义下划线或其他装饰效果的颜色。
- text-decoration-style 用于定义装饰效果的风格(比如实线、虚线、波浪线等)。
- text-decoration-skip 用于指定是否避让空格、字母降部或其他对象。
- text-underline-position 用于微调下划线的具体摆放位置。
text-decoration-style: wavy; // 波浪线;支持solid,
现实中的文字效果
凸版印刷效果
适用场景
这种效果尤其适用于
中等亮度背景配上深色文字
的场景; 但它也可用于
深色底、 浅色字
的场景, 只要文字不是黑色并且背景不是纯黑或纯白就行
原理
出现在
底部的浅色投影
(或者出现在顶部的暗色投影
) 会让人产生物体是凹进平面内的错觉。 同理, 出现在底部的暗色投影
(或者出现在顶部的浅色投影
) 会让人产生物体从平面上凸起的错觉。 这种方法之所以奏效, 是因为我们在现实世界中早已习惯了光源总是悬在头顶。 在这样的环境
里,凸起物的下方会产生阴影, 而凹陷的底部边缘则会被打亮
。
background: hsl(210, 13%, 60%);
color: hsl(210, 13%, 30%);
text-shadow: 0 1px 1px hsla(0, 0%, 100%, 0.8);
// 深色背景浅色文字
background: hsl(210, 13%, 40%);
color: hsl(210, 13%, 75%);
text-shadow: 0 -1px 1px black;
空心字效果
方案一:使用text-shadow分别为这些投影加上少量偏移
;
background: deeppink;
color: white;
text-shadow: 1px 1px black, -1px -1px black,
1px -1px black, -1px 1px black;
方案二:重叠多层轻微模糊的投影来模拟描边
。 这种方法不需要设置偏移量,但是这种方法并不总是可以得到完美的效果, 而且性能消耗较高。 没错, 这是因为用了模糊算法
text-shadow: 0 0 1px black, 0 0 1px black,
0 0 1px black, 0 0 1px black,
0 0 1px black, 0 0 1px black;
我们需要的描边越粗, 这两种方案产生的结果就越差
文字凸起效果
原理
主要思路就是
使用一长串累加的投影,不设模糊并以 1px 的跨度逐渐错开, 使颜色逐渐变暗, 然后在底部加一层强烈模糊的暗投影, 从而模拟完整的立体效果
。
background: #58a;
color: white;
text-shadow: 0 1px hsl(0,0%,85%),
0 2px hsl(0,0%,80%),
0 3px hsl(0,0%,75%),
0 4px hsl(0,0%,70%),
0 5px hsl(0,0%,65%),
0 5px 10px black;
另一种复古效果
color: white;
background: hsl(0,50%,45%);
text-shadow: 1px 1px black, 2px 2px black,
3px 3px black, 4px 4px black,
5px 5px black, 6px 6px black,
7px 7px black, 8px 8px black;
@function text-retro($color: black, $depth: 8) {
$shadows: (1px 1px $color,);
@for $i from 2 through $depth {
$shadows: append($shadows,
($i*1px) ($i*1px) $color, comma);
用户体验
扩大可点击区域
使用透明border
扩张热区最简单的办法是为它设置一圈透明边框, 因为鼠标对元素边框的交互也会触发鼠标事件, 这一点是描边和投影所不及的
border: 10px solid transparent;
这样的问题在于会影响元素位置,同时在需要真正使用border时影响其使用;
使用伪元素
我们放弃边框, 然后改用另外一个特性来实现:
伪元素同样可以代表其宿主元素来响应鼠标交互
我们可以在按钮的上层覆盖一层透明的伪元素, 并让伪元素在四个方向上都比宿主元素大出 10px:
button {
position: relative;
}
button::before {
content: '';
position: absolute;
top: -10px; right: -10px;
bottom: -10px; left: -10px;
}
这个基于伪元素的解决方案极为灵活, 我们基本上可以把热区设置为任何想要的尺寸、 位置或形状, 甚至可以脱离元素原有的位置!
交互式的图片对比控件
这个控件会把两张图片叠加起来, 允许用户拖动分割条来控制这两张图片的显露区域
打字效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Static Template</title>
<style>
@keyframes typing {
from {
width: 0;
}
}
@keyframes caret {
50% {
border-right: transparent;
}
}
h1 {
width: 15ch;
border-right: 0.05em solid;
overflow: hidden;
animation: typing 6s steps(15) infinite, caret 1s steps(1) infinite;
white-space: nowrap;
text-align: justify;
}
</style>
</head>
<body>
<h1>CSS is awesome!</h1>
<div class="bb"></div>
</body>
</html>