有趣的CSS 属性

178 阅读9分钟

1. writing-mode

image.png 在上图的右侧(滚动条附近),我们可以看到侧边竖直排列的文本,而这恰好就是一种显示附加信息的巧妙方法。

writing-mode 属性可以让我们实现这个效果。

该属性支持以下值:

  • sideways-rl:文本和其他内容从上到下垂直排列,并向右横向放置。
  • sideways-lr:和 sideways-rl 一样,文本和其他内容从上到下垂直排列,但向左倾斜。
  • vertical-rl:文本和其他内容从上到下垂直排列,从右到左水平排列。如果有两行或更多行,则这些行会被放置在前一行的左侧
  • vertical-lr:与 vertical-rl 不同,水平地将文本从左到右排列,并且如果有两行或更多行,则这些行会被放置在前一行的右侧。

horizontal-tb 属性则实现默认排列文本的效果。

image.png

2. clip-path

clip-path 非常有趣,它允许我们使用 CSS 创建不同类型的复杂形状(椭圆、圆形、多边形和其他不同的形状)。

该属性能够通过定义应显示元素的哪些部分来创建复杂的形状。clip-path 可以采用不同的值,例如形状函数和剪辑源。您可以在 MDN 文档上了解有关该属性的更多信息。

-webkit-clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);

image.png

-webkit-clip-path: polygon(10% 25%, 35% 25%, 35% 0%, 65% 0%, 65% 25%, 90% 25%, 90% 50%, 65% 50%, 65% 100%, 35% 100%, 35% 50%, 10% 50%);

image.png

.outer{
  width:100px;
  height: 100px;
  background:orange;
  clip-path: polygon(20% 0%, 80% 0%, 100% 20%, 100% 80%, 80% 100%, 20% 100%, 0% 80%, 0% 20%);
  transition:.5s clip-path;
}  
.outer:hover{
  clip-path:polygon(0 0,0 0,100% 0,100% 0,100% 100%,100% 100%,0 100%,0 100%);
}
<div class="outer"></div>

20190821174540858.gif

如果我们想使用属性 clip-path 轻松创建复杂的形状,我强烈建议使用名为 clip-path-maker 的工具。

它是 100% 免费的,允许我们使用拖放功能创建形状。创建形状后,该工具会自动为我们生成 CSS 代码。

3. writing-mode

CSS 的 writing-mode 属性允许我们定义文本行是垂直还是水平布局。除此之外,它还允许设置块的前进方向。

所有主流浏览器都支持该属性,并且可以采用以下值:

horizontal-tb, vertical-rl, vertical-lr, sideways-rl, and sideways-lr
<h1>Hello World!</h1>
<h2>Hello World!</h2>
}
body{
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
}
h1{
    writing-mode: vertical-lr;
    margin: 10px;
}
h2{
    writing-mode: horizontal-tb;
}

image.png

4. object-fit

object-fit 属性 允许我们设置或定义应如何调整替换元素的内容(img、video 等)以适应其容器。

所有主要浏览器都支持此属性。它可以采用以下值:fill、contain、cover、scale-down 和 none。如果你还想了解更多内容的话,可以到 MDN 文档(developer.mozilla.org/en-US/docs/…

下面的代码示例允许图像保持其纵横比并填充给定的尺寸。图像被剪裁以适合。

<div class="container">
    <h2>object-fit: cover</h2>
    <img id="img1" src="https://images.pexels.com/photos/1805053/pexels-photo-1805053.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" alt="car">
    <h2>Without Object-fit:</h2>
    <img id="img2" src="https://images.pexels.com/photos/1805053/pexels-photo-1805053.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" alt="car">
</div>
.container{
    display: flex;
    flex-direction: column;
    heigh: 100vh;
    align-items: center;
}
#img1{
    width: 250px;
    height: 180px;
    object-fit: cover;
}
#img2{
    width: 250px;
    height: 180px;
}

image.png

5. backface-visibility

CSS 中的 backface-visibility 属性设置当转向用户时元素的背面是否可见。

在创建具有悬停效果的翻转卡片时,通常会使用此属性。它可以采用以下两个值之一:visible(可见)或hidden(隐藏)。

div{
    backface-visibility: hidden;
}

演示

6. mix-blend-mode

CSS  的 mix-blend-mode 属性是另一个很多人不熟悉的有用属性, 甚至大多数 Web 开发人员都不知道它。

因此,该属性设置并定义了元素的内容,应如何与父元素的内容及其背景混合。让我们简单地说它定义了一个元素和它背后的另一个元素之间的混合。

这个属性有很多值,例如 normal 、 multiply 、 overlay 、 screen 等等。

<div class="blend">
  <img src="https://duomly.nyc3.digitaloceanspaces.com/articles/coding/alps-lake.jpg" />
   <h1>NATURE</h1>
</div>
.blend {
  width: 100vw;
  height: 500px;
  display: flex;
  align-items: center;
  justify-content: center;
} 

.blend img {
  position: absolute;
}

.blend h1 { 
  font-size: 150px;
  mix-blend-mode: overlay;
}

image.png

7. background-blend-mode

CSS 中的 background-blend-mode 属性是另一个有用的混合模式属性,它允许定义和设置元素的背景图像和背景颜色之间的混合。

该属性有许多值(正常、乘法、屏幕等),可让我们设置不同的混合模式。除旧版本外,所有主要浏览器都支持它。

div{
    background: url("tree.png"), url("paper.png");
    background-blend-mode: normal;
}

image.png

div{
    background: url("tree.png"), url("paper.png");
    background-blend-mode: overlay;
}

image.png

8. text-shadow

文字模糊效果

div{ 
    /*transparent:透明*/
    color: transparent;
    text-shadow: #111 0 0 5px;
}

image.png

9. 那些花里胡哨的效果

3df3777fd512dd0f3cc60ef6efb6985a.gif

  <div class="card">
    <div class="node" v-for="item in 100"></div>
  </div>

image.png 通过图片动画效果,我们大致得出动画变化的模式。

  • 有部分圆环变形成两个圆环的长度,并改变了底色。

    观察变长圆环的顺序,能发现“每逢三就变长”这种规律,推测使用了 :nth-child(3) 选择器。

 
.card {
    justify-content: flex-start;
    overflow: hidden;
    cursor: pointer;
 
    // 每逢三个元素,则执行动画,源代码和我们分析的动画的顺序相反,圆环是从长变短,不过不影响
    .node {
      border: solid 5px #F29338;
      border-radius: 50%;
 
 
      &:nth-child(3n) {
        width: 40px;
        flex-basis: 40px;
        background: #F8C798;
        animation: change-circle-width 2s ease alternate infinite;
      }
    }
  }
 
  @keyframes change-circle-width {
    from {
      width: 40px;
      flex-basis: 40px;
      background: #F8C798;
    }
    60% {
      width: 20px;
      flex-basis: 20px;
      background: transparent;
    }
    // 动画 60% - 100% 这段时间,属性没有变动,所以图案看起来像是静止的。
    to {
      width: 20px;
      flex-basis: 20px;
      background: transparent;
    }
  }

0b1035c8f6c56fbffe4826d740d98670.gif

三角形,好办,用伪元素画。至于颜色么,可以仿照上一张图片的 CSS 伪随机的思路。至于山的动画,不好确定是山在动还是说山在跟随其它元素动。

再看横线,欸不对,这图里怎么有这么多横线竖线,到底哪一个伪元素哪一个又不是,害...

猜测,横线竖线是格子的 Outline。不对,Outline 只能是正方形的。

那会不会是 Border 呢?能从观察得出,这些横线的边缘又半透明像素,再结合三角形可有 Border 绘制而成,推测,横线竖线是圆角矩形格子的 Border,被形成三角形的伪元素的白色 Border 遮挡而消失了一部分。

继续观察线条,发现有的横线会消失,有的横线只会缩短而不会消失,所有竖线都只会缩短不会消失。

根据竖线变长时,一定伴随着横线的缩短或消失,推测,格子在经历高度的变化,而不是位移。继续推测,三角形可能是跟随格子一起运动。

再根据垂直方向两座山之间的横线和山的运动趋势是一样的,推测,图中横线是格子的上边而不是下边,下边都被遮住了。

猜测山把格子的下边遮住了,但这与实际观察不符,因为,山在向上运动时,竖线的伸缩有伸缩。格子的边的一部分的消失并不是构成山的伪元素的 Border 遮挡而成的,而是另一个伪元素,大致也是矩形。

我们可以大概构成这副图案了:格子被束缚在了 align-items: center 的 Flex 布局中,三角形以及另一个类似矩形的伪元素随着格子的运动而运动。

还是看下面这张图构好了。这是去掉白色遮罩物的样子。

image.png

 
.card {
    cursor: pointer;
 
    // 横线与竖线并不是节点的 Border,而是背景色+遮罩形成的
    // 格子会根据动画在高度上变化
    .node {
      background: #A45963;
      border-radius: 90%;
      animation: card-1 .4s ease alternate infinite;
 
      // 格子动画延迟处理
      &:nth-child(2n) {
        animation-delay: .2s;
      }
      &:nth-child(3n) {
        animation-delay: .3s;
      }
      &:nth-child(4n) {
        animation-delay: .3s;
      }
 
      // 山的颜色处理
      &:nth-child(2n)::before {
        border-bottom-color: #F5CB6C;
      }
      &:nth-child(3n)::before {
        border-bottom-color: #F5856C;
      }
      &:nth-child(4n)::before,
      &:nth-child(5n)::before,
      &:nth-child(6n)::before,
      &:nth-child(7n)::before,
      &:nth-child(8n)::before,
      &:nth-child(9n)::before,
      &:nth-child(10n)::before {
        border-bottom-color: #D2F3BF;
      }
 
      // 山的构成
      &::before {
        left: 0;
        top: -5px;
        border: solid 10px transparent;
        border-bottom-color: #D2F3BF;
        z-index: 2;
      }
 
      // 白色遮罩
      &::after {
        left: 1px;
        top: 1px;
        width: 19px;
        height: 18px;
        background: white;
      }
 
      // 这是一个特殊处理,为了让白色遮罩长度减少1像素以显示每行格子的背景颜色的最后一列像素
      &:nth-child(10n)::after {
        width: 18px;
      }
    }
  }
 
  @keyframes card-1 {
    from {
      height: 19px;
    }
    to {
      height: 8px;
    }
  }

0cd17ebaa0dc0280d006dba835b6686a.gif

把这两个图案放到一起是因为思路是一样的。实话说,第一次见到这种花纹,我也对这莫名其妙的色彩变化一脸懵逼,所以这里就直接讲原理了。

两张图片都是用渐变画的,仔细观察能发现左边和右边的图案都是三层渐变的叠加。

不同的地方在于,左图最小的那层渐变是辐射渐变(Radial-Gradient),右图的则是圆锥渐变(英文叫 Conic-Gradient,饼图就可以用这玩意儿画)

莫名其妙的颜色变换(如左图中心点)使用的是 CSS 混合模式(CSS Blend-Mode)效果,它负责计算当两种色彩层叠在一起时最终显示的颜色,可以理解为滤镜。

背景移动之前看过,左图是变换 Background-Position,右图是变换 Background-Size

 
  // 右图的样式代码
  .card {
 
    // 这里使用了三层背景渐变,两层圆锥渐变和一层辐射渐变
    background-image:
      repeating-conic-gradient(red 50%, #E1F5C4 60%),
      repeating-conic-gradient(red 50%, #E1F5C4 60%),
      radial-gradient(
        gold 0%, gold 35%,
        red 35%, red 40%,
        orangered 40%, orangered 50%,
        gold 50%, gold 60%,
        yellowgreen 60%, yellowgreen 70%,
        skyblue 70%, skyblue 80%,
        steelblue 80%, steelblue 90%,
        violet 90%
      );
 
    // 对每一层被渐变分别设置混合模式
    background-blend-mode:
      lighten,
      overlay,
      lighten;
 
    // 对每一层被渐变分别设置背景大小(40px 是因为正好能被 200px 的盒子整除)
    background-size:
      40px 40px,
      6em 6em,
      8em 8em;
    background-position: 50% 50%;
    transition: .45s ease-in;
    cursor: pointer;
 
    // 鼠标悬浮时,变换渐变大小
    &:hover {
      background-size:
        40px 40px,
        4em 4em,
        12em 12em;
    }
  }

10. 眼球转动动态效果

ee7018a8b5c7429e82715acc8fc6ead1.gif 演示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Eye Ball Move on Mousemove</title>
    <link rel="stylesheet" href="css/EyeAnimation.css">
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        body{
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background: radial-gradient(#f2761e,#ef4921);
        }
        .box{
            display: flex;
        }
        .box .eye{
            position: relative;
            width: 120px;
            height: 120px;
            display: block;
            background: #fff;
            margin: 0 20px;
            border-radius: 50%;
            box-shadow: 0 5px 45px rgba(0,0,0,0.2),
            inset 0 0 15px #f2761e,
            inset 0 0 25px #f2761e;
        }
        .box .eye::before{
            content: '';
            position: absolute;
            top: 50%;
            left: 35%;
            transform: translate(-50%,-50%);
            width: 45px;
            height: 45px;
            border-radius: 50%;
            background: #000000;
            border: 10px solid #2196f3;
            box-sizing: border-box;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="eye"></div>
        <div class="eye"></div>
    </div>
    <script>
        document.querySelector('body').addEventListener('mousemove',eyeball);
        function eyeball(e) {
            const eye=document.querySelectorAll('.eye');
            eye.forEach(function (eye) {
                let x=(eye.getBoundingClientRect().left)+(eye.clientWidth/2);
                let y=(eye.getBoundingClientRect().top)+(eye.clientHeight/2);

                let radian=Math.atan2(e.pageX-x,e.pageY-y);
                let rotation=(radian*(180/Math.PI)*-1)+270;
                eye.style.transform="rotate("+rotation+"deg)"
            })
        }
    </script>
</body>
</html>