背景

本人一直对 CSS 很感兴趣,刚好我们团队有一位擅长CSS的大佬:COCO。

于是我找到他, 建议做一期关于CSS的分享, 于是就有了《CSS创意构想》。

分享的内容很棒,里面有很多技巧, 有的很实用, 有的很华丽。

听完之后, 我觉得十分受用, 就想结合自己的一些理解,再次整理一番加深印象, 二次吸收, 所以就有了今天的文章。

满满的干货,也分享给大家, 希望对大家有所启发。

PS: 文章内示例均来自coco的博客, 感兴趣的可以移步到这里


布局

平行四边形

先抛一个问题, 如何实现平行四边形布局效果?

  • transform
  • 叠加三角形

仅仅实现形状的话, 上面两种方式都是可以的。

但是, 如果图形内部还有文字,需要正常排布,transform 、叠加三角形 都不可行。

那怎么办呢? 答案就是: shape-outside.

  • shape-outside定义了一个可以是非矩形的形状,相邻的内联内容应围绕该形状进行排版
  • clip-pathCSS 属性可以创建一个只有元素的部分区域可以显示的剪切区域

clip-path 语法:

{
    clip-path: circle(50px at 0  100px);
    clip-path: ellipse();
    clip-path: inset(10px  10px  10px  10px);
    clip-path: polygon(10px  10px, 20px  20px, 30px  30px);
}

图文混排 Demo:

https://codepen.io/Chokcoco/p...

CSS Shapes Demo:

https://codepen.io/Chokcoco/p...

一个适用的场景: 适配 iPhone X刘海头

镂空

使用阴影,可以非常简单的模拟遮罩效果, 并且,圆角也是没有问题的。

box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .5);

垂直居中

抛出个问题: 最快的水平垂直居中方法是什么?

你首先想到的是不是: flex, center, center ?

其实margin也可以:

<div class="g-container">
    <div class="g-box"></div>
</div>

.g-container { display: flex; }
.g-box { margin: auto; }

原理:

在 flex 格式化上下文中,设置了 margin: auto 的元素,在通过 justify-content 和 align-self 进行对齐之前,任何正处于空闲的空间都会分配到该方向的自动 margin 中去。

Live Demo:

https://codepen.io/Chokcoco/p...

还有这种常见的左右布局, 也可以巧用margin来实现:

<ul class="g-nav">
    <li>导航A</li>
    <li>导航B</li>
    <li>导航C</li>
    <li>导航D</li>
    <li class="g-login">登陆</li>
    <li>注册</li>
</ul>

.g-nav { display: flex; }
.g-login { margin-left: auto; }

自动页脚

我们经常会遇到需要放置在页脚的元素, 高度超过一屏时, 自动顶下去:

这种效果也有很多种实现方式, 巧用margin可以快速实现:

<div class="g-container">
    <div class="g-real-box">
        ...
    </div>
    <div class="g-footer"></div>
</div>
.g-container {
    height: 100vh;
    display: flex;
    flex-direction: column;
}

.g-footer {
    margin-top: auto;
    flex-shrink: 0;
    height: 30px;
    background: deeppink;
}

阴影

  • 阴影分为外阴影和内阴影(inset)
  • 阴影可以是多重阴影
  • 阴影可以进行动画

使用阴影可以轻松得到图片本身,并且任意改变颜色及大小.

比如, 把发散半径设置为0:

code:

div {
    width: 80px;
    height: 80px;
    background: #fff;
    box-shadow:
        80px 80px 0 0 yellow,
        -80px 80px 0 10px green;
}

使用阴影模拟多重边框

代码实现:

{
  background: #fff;
  box-shadow:
    0 0 0 2px red,
    0 0 0 4px orange,
    0 0 0 6px yellow,
    0 0 0 8px green,
    0 0 0 10px cyan;
}

使用阴影画出一朵云:

其实是用不同的阴影叠加而成:

.bgShadowCloud {
    width: 100px;
    height: 100px;
    margin: 50px auto!important;
    background: #fff;
    border-radius: 50%;
    box-shadow: 120px 0px 0 -10px #795548, 95px 20px 0 0px #607D8B, 30px 30px 0 -10px green, 90px -20px 0 0px #FFC107, 40px -40px 0 0px #2196F3;
    animation: change 6s infinite;
}

内阴影

模拟圆月变月牙:

代码实现:

动态效果:
https://codepen.io/Chokcoco/p...

特殊阴影

有的时候,CSS 的 box-shadow 无法很好去实现一些特殊阴影,可以利用一些小技巧进行模拟。

长阴影

  • 借助两个伪元素的 transform: skew() 变换
  • 伪元素背景从实色到透明色的背景色变化

实现代码:

<div class="bgLongShadow"></div>

.bgLongShadow {
    position: relative;
    width: 268px;
    height: 269px;
    background: #fff;
    margin: 20px auto!important;
    background-size: contain;
    background-position: center;
    background-repeat: no-repeat;
}

.bgLongShadow::before {
    transform-origin: 0 50%;
    transform: translate(100%, 0) skewY(45deg) scaleX(.3);
    background: linear-gradient(90deg, rgba(255, 255, 255, .3), transparent);
    animation: shadowMoveY 5s infinite linear alternate;
}

.bgLongShadow::before, .bgLongShadow::after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: -1;
}

立体投影

以第一个为例, 其实是用了一点障眼法:

代码实现:

<div class="bgSolidShadow"></div>

div.bgSolidShadow {
    position: relative;
    width: 600px;
    height: 100px;
    margin: 50px auto;
    background: hsl(48, 100%, 50%);
    border-radius: 20px;
    box-shadow: 0 0 5px 2px hsl(48, 100%, 45%);
    cursor: pointer;
}

.bgSolidShadow::before {
    content: "";
    position: absolute;
    top: 40%;
    left: 5%;
    right: 5%;
    bottom: 0;
    border-radius: 10px;
    transform: translate(0, -15%) rotate(-2deg);
    transform-origin: center center;
    box-shadow: 0 0 10px 12px hsl(0, 0%, 0%);
    z-index: -1;
}

彩色阴影

  • 其实是借助了高斯模糊滤镜

{
    filter: blur(10px) brightness(90%) opacity(.85);
}

整体阴影

看下图:

这个的阴影如何实现? box-shadow ?

先看一下DOM结构:


<div class="flecha"></div>

// 三角
.flecha {
    position: relative;
    margin: 50px auto!important;
    width: 0;
    height: 0;
    border-top: 90px solid transparent!important;
    border-right: 90px solid #FFC000!important;
    transform: rotate(10deg);
    box-shadow: 0px 0px 10px rgba(255, 220, 0, .8);
}

// 尾巴

.flecha:after {
    content: "";
    position: absolute;
    border: 0 solid transparent;
    border-top: 30px solid #FFC000!important;
    border-radius: 200px 0 0 0!important;
    top: -119px;
    left: -98px;
    width: 120px;
    height: 120px;
    transform: rotate(45deg);
}

此时的效果:

加上box-shadow:

{
    box-shadow: 0px 0px 10px rgba(255, 220, 0, .8);
}

可见是不行的, 那该怎么办呢?

答案是: 使用 drop-shadow

{
  filter: drop-shadow(0px  0px  10px  rgba(255, 220, 0, .8));
}

完美~

利用drop-shadow单标签实现抖音 LOGO

代码实现:

div {
    position: relative;
    width: 37px;
    height: 218px;
    background: #fff;
    filter:drop-shadow(-10px -10px 0 #24f6f0) contrast(150%) brightness(110%);
    box-shadow: 11.6px 10px 0 0 #fe2d52;

    &::before {
        ....
        filter: drop-shadow(16px 0px 0 #fe2d52);
    }

    &::after {
        ....
        filter:drop-shadow(14px 0 0 #fe2d52);
    }
}

Live demo:

https://codepen.io/Chokcoco/p...

十分酷炫~

使用阴影的扩散半径实现内切圆角

Live Demo:

https://codepen.io/Chokcoco/p...

渐变

  • 渐变分为线性渐变、径向渐变、角向渐变(圆锥渐变)
  • 渐变可以控制各种角度
  • 渐变可以是多重渐变叠加
  • 渐变不能进行动画 (animation/transtion)

线性渐变

{ background: linear-gradient(45deg, #fff, #ffcc00); }

合理控制颜色百分比,可以让渐变颜色变成实色

{
    background: linear-gradient(45deg, #fff 50%, #ffcc00 50%);
}

某一段的颜色可以是透明的

{ background: linear-gradient(45deg, #fff  33%, transparent 33%, transparent 66%, #ffcc00  66% ); }

背景重复

  • 可以利用 repeating-linear-gradient、repeating-radial-gradient 进行重复
  • 也可以利用 background-size 和 background-repeat 进行重复控制

背景动画

可以不去改变颜色本身,而是利用其它元素进行动画

transform、filter、mix-blend-mode 等等

比如, 实现一个背景色持续变化的元素:

设置overflow: hidden 截断多余的部分, 使用动画不断改变背景块的位置, 即可实现效果。

<div class="g-linear-gradient-5"></div>

.g-linear-gradient-5 {
    width: 80px;
    height: 80px;
    border: 2px solid #fff!important;
    position: relative;
    overflow: hidden;
}

.g-linear-gradient-5::before {
    content: "";
    position: absolute;
    top: -100%;
    left: -100%;
    bottom: -100%;
    right: -100%;
    background: linear-gradient(45deg, #ffc700 0%, #e91e1e 50%, #6f27b0 100%);
    background-size: 100% 100%;
    animation: bgposition 8s infinite linear alternate;
    z-index: -1;
}

利用透明色,实现切角

{
    background:
        linear-gradient(135deg, transparent 15px, #ffcc00 0)
        top left,
        linear-gradient(-135deg, transparent 15px, #ffcc00 0)
        top right,
        linear-gradient(-45deg, transparent 15px, #ffcc00 0)
        bottom right,
        linear-gradient(45deg, transparent 15px, #ffcc00 0)
        bottom left;
    background-size: 60% 60%;
    background-repeat: no-repeat;
}

实现进度条效果

利用重复线性渐变 + transform 实现进度条效果

https://codepen.io/Chokcoco/p...

实现优惠券的边纹

{
    background-image:
        radial-gradient(circle at 1px 8px, transparent 6px, #ffcc00 6px, #ffcc00 0px),
        radial-gradient(circle at 199px 8px, transparent 6px, #ffcc00 6px, #ffcc00 0px);
    background-size: 200px 18px;
    background-position: 0 0, 200px 0;
    background-repeat-x: no-repeat;
}

多种渐变的组合

多种渐变的组合,还能创造出各种有意思的图形, 比如:

https://codepen.io/Chokcoco/p...

实现气泡按钮点击效果

使用了background-position+background-size

https://codepen.io/Chokcoco/p...

圆锥渐变

  • linear-gradient 线性渐变的方向是一条直线,可以是任何角度
  • radial-gradient 径向渐变是从圆心点以椭圆形状向外扩散

起始点是图形中心,然后以顺时针方向绕中心实现渐变效果


{ background: conic-gradient(deeppink, yellowgreen); }

实现颜色表盘

{ background: conic-gradient(red, #ff4d00, #ff9900, #ffe600, #ccff00, #80ff00, #33ff00, #00ff1a, #00ff66, #00ffb3, cyan, #00b3ff, #0066ff, #001aff, #3300ff, #8000ff, #cc00ff, #ff00e6, #ff0099, #ff004d, red); }

又或者是这种积分表盘:

https://codepen.io/alphardex/...

结尾

文章已经很长, 为了阅读上的方便, 剩余的一部分将会在下一篇文章里。

剩余内容包括:

  • 混合模式
  • 滤镜
  • 伪元素
  • 波浪效果
  • 滚动指示器
  • 滚动视差

部分示例缺少代码, 需要逐个准备, 比较耗时。

持续更新, 敬请期待,

关注我

如果你觉得这篇内容对你挺有启发,那就关注我吧~

更多精彩:

聊聊 ESM、Bundleless 、Vite 、Snowpack

记一次 「 无限列表 」滚动优化

「 面试三板斧 」之 代码分割(上)

「 面试三板斧 」之缓存 (上)

「 面试三板斧 」之缓存 (下)

「 面试三板斧 」之 HTTP (上)

「 面试三板斧 」之 HTTP (下)

「 面试三板斧 」之  this

03-05 14:05