《CSS揭秘》第4章-视觉效果

单侧投影

box-shadow

难题

在问答网站上,最常被问到的box-shadow问题,就是如何只在元素的一侧(偶尔是两侧)设置投影。

单侧投影

大多数人使用box-shadow的方法是,指定三个长度值和一个颜色值:

1
box-shadow: 2px 3px 4px rgb(0,0,0,.5);

接下来的4个步骤很好地(虽然在技术上还不够严谨)以图形化的方式讲解了投影是如何绘制的:

  1. 以该元素相同的尺寸1①和位置,画一个 rgba(0,0,0,.5) 的矩形。
  2. 把它向右移 2px,向下移3px。
  3. 使用高斯模糊算法(或类似算法)将它进行4px的模糊处理。这在本质上表示在阴影边缘发生阴影色和纯透明色之间的颜色过渡长度近似于模糊半径的两倍(比如在这里是 8px)
  4. 接下来,模糊后的矩形与原始元素的交集部分会被切除掉

使用 4px 的模糊半径意味着投影的尺寸会比元素本身的尺寸大,因此投影的最外圈会从元素的四面向外显露出来,确切地说,我们将在顶部看到1px的投影(4px-3px)、在左侧看到2px(4px-2px)、在右侧看到6px(4px+2px)、在底部看到7px(4px+3px)。

最终的解决方案来自box-shadow的第四个长度参数。它排在模糊半径参数之后,称作扩张半径。这个参数会根据你指定的值去扩大或(当指定负值时)缩小投影的尺寸。
如果我们应用一个负的扩张半径,而它的值刚好等于模糊半径,那么投影的尺寸就会与投影所属元素的尺寸完全一致。除非用偏移量(前两个长度参数)来移动它,我们将完全看不见任何投影。

1
box-shadow:0 5px 4px -4px black;

双侧投影

唯一的办法是用两块投影(每边各一块)来达到目的。然后基本上就是把“单侧投影”中的
技巧运用两次:

1
2
box-shadow:5px 0 5px -5px black,
-5px 0 5px -5px black;

不规则的投影

染色效果

毛玻璃效果

折角效果

CSS变形、CSS渐变、“切角效果”

难题

把元素的一个角(通常是右上角或右下角)处理为类似折角的形状,再配上或多或少的拟物样式,这种效果已经成为一种非常流行的装饰手法。
2010年一些技巧方法的基本原理通常是在右上角增加两个三角形:
一个三角形用来体现折页的形状,另一个白色的三角形遮住元素的一角,用来模拟翻折所产生的缺口。这两个三角形通常都是由经典的边框技巧来生成的。
在今天看来却有一些局限性,而且在以下场景中还会暴露出明显的缺陷:

  • 当折角元素之下的背景不是纯色,而是一幅图案、一层纹理、一张照片、一幅渐变或其他任何一种背景图像时,
  • 当我们想要一个45°以外的(旋转的)折角时

45°折角的解决方案

  1. 第一步
    我们会从一个右上角具有斜面切角的元素开始,这个切角是由“切角效
    果”一节中的渐变方案实现的。要用这个技巧在右上角创建一个大小为 1em
    的斜面切角:

    1
    2
    3
    background: #58a; /* 回退样式 */ 
    background:
    linear-gradient(-135deg, transparent 2em, #58a 0);
  2. 第二步
    接下来所需要做的就是增加一个暗色的三角形来实现翻折效果。
    实现方法是增加另一层渐变来生成这个三角形并将其定位在右上角,这样就可以通过 background-size来控制折角的大小。

    1
    2
    3
    4
    background: 
    linear-gradient(to left bottom,
    transparent 50%, rgba(0,0,0,.4) 0)
    no-repeat 100% 0 / 2em 2em;
  3. 第三步
    简单的把两者背景组合会导致尺寸不匹配。

原因在于第二层渐变中的 2em 折角尺寸是写在色标中的,因此它是沿着渐变轴进行度量的,是对
角线尺寸。另一方面,在background-size中的2em长度是背景贴片的宽度和高度,是在水平和垂直方向上进行度量的。

为了将这两者对齐,我们需要选择以下任意一项进行调整,选择哪一项取决于我们最终想保留哪一方的尺寸设置。

  • 如果要保留对角线的 2em 长度,就要将background-size乘以根号2。
  • 如果要保留水平和垂直方向上的 2em 长度,就要用切角渐变的角标位置值除以根号2。

由于 background-size 需要把这个长度重复两次,而且绝大多数的CSS度量都不是在对角线上进行的,因此第二种方案更加合适。根号2取整为1.5。

1
2
3
4
5
6
7
background: #58a; /* 回退样式 */ 
background:
linear-gradient(to left bottom,
transparent 50%, rgba(0,0,0,.4) 0)
no-repeat 100% 0 / 2em 2em,
linear-gradient(-135deg,
transparent 1.5em, #58a 0);

其他角度的解决方案

为这一点小效果,却花费巨大精力,暂时不管

liborn wechat
欢迎您扫一扫上面的微信二维码,订阅我的公众号!