4. CSS揭秘——视觉效果

1. 单侧投影

1.1 单侧投影

box-shadow 的第四个长度参数——扩张半径。它排在第三个参数模糊半径之后,这个扩张半径会根据你指定的值去扩大(当指定负值时)缩小投影的尺寸。举例来说,一个 -5px 的扩张半径会把投影的宽度和高度各减少 10px(即每边各 5px)。

  • 如果我们使用一个负的扩张半径,而它的值刚好等于模糊半径,那么投影的尺寸就会与投影所属元素的尺寸完全一致。
  • 除非用偏移量(前两个长度参数)来移动它,否则我们将完全看不见任何投影。
  • 因此,如果给投影应用一个正的垂直偏移量,我们就会在元素的底部看到一道投影,而元素的另外三侧是没有投影的
box-shadow: 0px 5px 4px -4px black;

1.gif

1.2 邻边投影——在元素的两条相邻边上设置投影

  • 不应该把投影缩得太小,而是只需把阴影藏进一侧,另一侧自然露出就好。因此,扩张半径不应设为模糊半径的相反值,而应该是这个相反值的一半。
  • 投影在水平和垂直方向上同时移动。它们的值需要大于或等于模糊半径的一半,因为这样可以把投影藏进另外两条边之内
<!DOCTYPE html>
<html>
  <head>
    <style>
      .pie {
        width: 100px;
        height: 100px;
        background: yellow;
        box-shadow: 3px 3px 6px -3px black;
      }
    </style>
  </head>

  <body>
    <div class="pie"></div>
  </body>
</html>

image.png

1.3 双侧投影

把投影设置在元素的两条对边(比如左侧和右侧)

由于扩张半径在四个方向上的作用是均等的,唯一的办法是用两块投影(每边各一块)

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

image.png

2. 不规则元素的投影

image.png
CSS 滤镜——filter属性基本上就是 SVG 滤镜

  • 只需要blur()grayscale() 以及 drop-shadow()函数就可以很方便地指定滤镜效果
  • 可以把多个滤镜串连起来,用空格把它们分隔开
filter: blur() grayscale() drop-shadow();

drop-shadow() 滤镜可接受的参数基本上跟 box-shadow 属性是一样的,但不包括扩张半径,不包括 inset 关键字,也不支持逗号分割的多层投影语法

box-shadow: 2px 2px 10px rgba(0,0,0,.5);
filter: drop-shadow(2px 2px 10px rgba(0,0,0,.5));
<!DOCTYPE html>
<html>
  <head>
    <style>
      /**
      * 不规则投影
      */

      div {
        position: relative;
        display: inline-flex;
        flex-direction: column;
        justify-content: center;
        vertical-align: bottom;
        box-sizing: border-box;
        width: 5.9em;
        height: 5.2em;
        margin: 0.6em;
        background: #fb3;
        /*box-shadow: .1em .1em .3em rgba(0,0,0,.5);*/
        /* -webkit-filter: drop-shadow(0.1em 0.1em 0.1em rgba(0, 0, 0, 0.5)); */
        filter: drop-shadow(0.1em 0.1em 0.1em rgba(0, 0, 0, 0.5));
        font: 200%/1.6 Baskerville, Palatino, serif;
        text-align: center;
      }

      .speech {
        border-radius: 0.3em;
      }

      .speech::before {
        content: "";
        position: absolute;
        top: 1em;
        right: -0.7em;
        width: 0;
        height: 0;
        border: 1em solid transparent;
        border-left-color: #fb3;
        border-right-width: 0;
      }

      .dotted {
        background: transparent;
        border: 0.3em dotted #fb3;
      }

      .cutout {
        border: 0.5em solid #58a;
        border-image: 1
          url('data:image/svg+xml,\
                     <svg xmlns="http://www.w3.org/2000/svg"\
                 width="3" height="3" fill="%23fb3">\
              <polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\
     </svg>');
        background-clip: padding-box;
      }
    </style>
  </head>

  <body>
    <div class="speech">Speech bubble</div>
    <div class="dotted">Dotted border</div>
    <div class="cutout">Cutout corners</div>
  </body>
</html>

1.gif

使用drop-shadow() 滤镜,任何非透明的部分都会被一视同仁地打上投影,包括文本(如果背景是透明的)

image.png

3. 实现图片染色效果

纯 CSS 的方法能实现图片染色效果,比如为一幅灰度图片(或是被转换为灰度模式的彩色图片)增加染色效果

3.1 基于CSS滤镜实现——filter

把多个滤镜组合起来

  • 滤镜sepia(),它会给图片增加一种降饱和度的橙黄色染色效果,几乎所有像素的色相值会被收敛到 35~40
  • saturate() 滤镜来给每个像素提升饱和度
  • hue-rotate() 滤镜,把每个像素的色相以指定的度数进行偏移
filter: sepia() saturate(4) hue-rotate(295deg);
<!DOCTYPE html>
<html>
  <head>
    <style>
      img {
        max-width: 640px;
        transition: 1s filter, 1s -webkit-filter;
        /* -webkit-filter: sepia() saturate(4) hue-rotate(295deg); */
        /* filter: sepia();
        filter: sepia() saturate(4); */
        filter: sepia() saturate(4) hue-rotate(295deg);
      }

      img:hover,
      img:focus {
        -webkit-filter: none;
        filter: none;
      }
    </style>
  </head>

  <body>
    <img src="http://csssecrets.io/images/tiger.jpg" />
  </body>
</html>

1.gif

3.2 基于混合模式实现——luminosity

  • 当两个元素叠加时,“混合模式”控制了上层元素的颜色与下层颜色进行混合的方式。
  • luminosity 混合模式会保留上层元素的 HSL 亮度信息,并从它的下层吸取色相和饱和度信息。
  • 在下层准备好我们想要的主色调,并把待处理的图片放在上层并设置为这种混合模式

HSL 是 Hue(色调)、Saturation(饱和度)、Lightness(亮度)的缩写,它同样也是一种色彩模式,可以通过对色调、饱和度、亮度三个属性的调节来实现不同颜色的。CSS 中使用 HSL 模式需要借助 hsl() 函数,函数的语法格式如下:

hsl(hue, saturation, lightness)

  • mix-blend-mode 可以为整个元素设置混合模式,需要把图片包裹在一个容器中,并把容器的背景色设置为我们想要的主色调。
  • background-blend-mode 可以为每层背景单独指定混合模式。不用图片元素,而是用
    元素——把这个元素的第一层背景设置为要染色的图片,并把第二层的背景设置为我们想要的主色调。

3.2.1 采用 mix-blend-mode: luminosity

<!DOCTYPE html>
<html>
  <head>
    <style>
      a {
        display: inline-block; /*不加这个,染色不起效果*/
        background: hsl(335, 100%, 50%);
      }
      img {
        mix-blend-mode: luminosity;
      }
    </style>
  </head>

  <body>
    <a href="#something">
      <img src="http://csssecrets.io/images/tiger.jpg" alt="Rawrrr!" />
    </a>
  </body>
</html>

1.gif

滤镜是可动画的,而混合模式则不是。

  • mix-blend-mode 是把整个元素向下进行混合,而不管它的下层是什么。把这个属性设置为 luminosity 混合模式,那图片就总是会跟某些东西进行混合。
  • 此外,使用 background-blend-mode 属性可以让每层背景跟它的下层背景进行混合,但并不关心元素之外是什么。
  • 另外,当只有一个背景图像以及一个透明背景色时,不会出现任何混合效果!

3.2.2 采用background-blend-mode: luminosity;

<!DOCTYPE html>
<html>
  <head>
    <style>
      .tinted-image {
        width: 640px;
        height: 440px;
        background-size: cover;
        background-color: hsl(335, 100%, 50%);
        background-blend-mode: luminosity;
        transition: 0.5s background-color;
      }
      .tinted-image:hover {
        background-color: transparent;
      }
    </style>
  </head>

  <body>
    <div
      class="tinted-image"
      style="background-image:url(http://csssecrets.io/images/tiger.jpg)"
    ></div>
  </body>
</html>    

1.gif
缺点: 图片的尺寸需要在 CSS 代码中写死

4. 毛玻璃效果

只对元素的背层(即被该元素遮住的那部分背景)应用blur()滤镜,而不是直接对整个元素进行模糊处理。解决方案就是——对一个伪元素进行处理,然后将其定位到元素的下层,它的背景将会无缝匹配<body>的背景

image.png

  • 添加一个伪元素,将其绝对定位,并把所有偏移量置为 0,这样就可以将它完整地覆盖到<main>元素之上
  • 设置一层半透明的red 背景,yongyu调试透明的(即不可见的)元素
  • z-index: -1;将伪元素放置在内容元素之下
  • 把半透明红色背景换成跟背层完全匹配的背景
  • main 元素应用overflow: hidden;,就可以把多余的模糊区域裁切掉
 <!DOCTYPE html>
<html>
  <style>
    body {
      min-height: 100vh;
      box-sizing: border-box;
      margin: 0;
      padding-top: calc(50vh - 6em);
      font: 150%/1.6 Baskerville, Palatino, serif;
    }

    body, main::before {
      background: url("http://csssecrets.io/images/tiger.jpg") 0 / cover fixed;
    }

    main {
      position: relative;
      margin: 0 auto;
      padding: 1em;
      max-width: 23em;
      background: hsla(0,0%,100%,.25) border-box;
      overflow: hidden; /*多余的模糊区域裁切掉*/
      border-radius: .3em;
      box-shadow: 0 0 0 1px hsla(0,0%,100%,.3) inset,
                  0 .5em 1em rgba(0, 0, 0, 0.6);
      text-shadow: 0 1px 1px hsla(0,0%,100%,.3);
    }

    main::before {
      content: '';
      position: absolute;
      top: 0; right: 0; bottom: 0; left: 0; /*伪元素和main大小一致*/
      margin: -30px;
      z-index: -1; /*伪元素放置底层*/
      -webkit-filter: blur(20px);
      filter: blur(20px); /*模糊处理*/
    }

    blockquote { font-style: italic }
    blockquote cite { font-style: normal; }
  </style>

  <body>
    <main>
      <blockquote>“The only way to get rid of a temptation is to yield to it. Resist it, and your soul grows sick with longing for the things it has forbidden to itself, with desire for what its monstrous laws have made monstrous and unlawful.”</em>
      <footer>— <cite>Oscar Wilde, The Picture of Dorian Gray</cite></footer>
      </blockquote>
      </main>
  </body>
</html>

1.gif

5. 折角效果

通常是在右上角增加两个三角形:一个三角形用来体现折页的形状,另一个白色的三角形遮住元素的一角,用来模拟翻折所产生的缺口。这两个三角形通常都是由经典的边框技巧来生成的。

image.png

5.1 实现45°折角

  • 渐变方案实现一个右上角具有斜面切角的元素
  • 增加一个暗色的三角形来实现翻折效果。实现方法是增加另一层渐变来生成这个三角形并将其定位在右上角,这样就可以通过 background-size 来控制折角的大小。
  • 折页部分的三角形放在切角渐变之上
<!DOCTYPE html>
<html>
  <style>
    div {
      width: 12em;
      background: #58a; /* Fallback */
      background: linear-gradient(
            to left bottom,
            transparent 50%,
            rgba(0, 0, 0, 0.4) 0
          )
          100% 0 no-repeat,
        linear-gradient(-135deg, transparent 1.5em, #58a 0);
      background-size: 2em 2em, auto;

      padding: 2em;
      color: white;
      font: 100%/1.6 Baskerville, Palatino, serif;
    }
  </style>

  <body>
    <div>
      “The only way to get rid of a temptation is to yield to it.” — Oscar
      Wilde, The Picture of Dorian Gray
    </div>
  </body>
</html>    

1.gif

5.2 实现其他角度的折角

  • 折页三角形是需要微微旋转,由于我们无法旋转背景,需用到伪元素
  • 把折页三角形的 width 和 height 对调,以此改变它的方向,这样就可以得到跟折页缺口对称的三角形,而不是一个可以补足折页缺口的三角形。
  • 然后,我们再以逆时针 30°((90° – 30° ) –30°)来旋转这个折页三角形,这样可以让它的斜边与折线平行

image.png

<!DOCTYPE html>
<html>
  <style>
    div {
      position: relative;
      width: 12em;
      background: #58a; /* Fallback */
      background: linear-gradient(-150deg, transparent 1.5em, #58a 0);
      padding: 2em;
      color: white;
      font: 100%/1.6 Baskerville, Palatino, serif;
      border-radius: 0.5em;
    }

    div::before {
      content: "";
      position: absolute;
      top: 0;
      right: 0;
      width: 1.73em;
      height: 3em;
      background: linear-gradient(
          to left bottom,
          transparent 50%,
          rgba(0, 0, 0, 0.2) 0,
          rgba(0, 0, 0, 0.4)
        )
        100% 0 no-repeat;
      transform: translateY(-1.3em) rotate(-30deg);
      transform-origin: bottom right; /* 让折页三角形的右下角成为旋转的中心 */
      border-bottom-left-radius: 0.5em;
      box-shadow: -0.2em 0.2em 0.3em -0.1em rgba(0, 0, 0, 0.15);
    }
  </style>

  <body>
    <div>
      “The only way to get rid of a temptation is to yield to it.” — Oscar
      Wilde, The Picture of Dorian Gray
    </div>
  </body>
</html>

1.gif

5.2.1 封装——预处理器的 @mixin

 <template>
  <div class="note">
     “The only way to get rid of a temptation is to yield to it.” — Oscar
      Wilde, The Picture of Dorian Gray
  </div>
</template>

<script>
export default {
  name: "AboutView"
}
</script>
<style lang="scss" scoped>

@mixin folded-corner($background, $size, $angle: 30deg) {
    position: relative;
    background: $background; /* 回退样式 */
    background: linear-gradient($angle - 180deg, transparent $size, $background 0);
    border-radius: .5em;
    /* $x: $size / sin($angle); */
    /* $y: $size / cos($angle); */
    /*x, y需手动计算 Scss暂不支持三角函数计算; Stylus和LESS 原生内置了三角函数*/
    $x: 3.1em; 
    $y: 2.6em;
    &::before {
        content: '';
        position: absolute;
        top: 0; right: 0;
        background: linear-gradient(to left bottom,
          transparent 50%, rgba(0,0,0,.2) 0,
        rgba(0,0,0,.4)) 100% 0 no-repeat;
        width: $y; height: $x;
        transform: translateY($y - $x)
        rotate(2*$angle - 90deg);
        transform-origin: bottom right;
        border-bottom-left-radius: inherit;
        box-shadow: -.2em .2em .3em -.1em rgba(0,0,0,.2);
    }
}
/* 当调用时... */
.note {
  width: 12em;
  padding: 2em;
  margin: 50px auto;
  @include folded-corner(#58a, 2em, 40deg);
}
</style>

1.gif

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容