看完了 2021 CSS 年度报告,我学到了啥?
大家好,我是 ConardLi,一年一度的 CSS年度报告 如期而至,我挑了一些我感兴趣的部分,和我一起来看看吧~
这篇文章用了很久,因为平时 CSS 写的实在少,其实看报告的主要目的除了了解CSS技术趋势,更重要的是顺便学习了下之前没用过的一些特性和库 😄

布局
弹性盒子(Flex)布局
相信大多数人都用过,就不多说了。

CSS 网格(GRID)布局
用的人越来越多了,只有 0.7% 的受访者没了解过,我在平时中也用过,不过用的不多,大多数场景下 Flex 就能满足需求,你们呢?

子网格(Subgrid)布局
用过的人比去年多一些,不过没用过或者没了解过的仍然是大多数。

说实话,我也是没用过,特意学习了一下,故名思议,除了操纵同级别的网格,它拥有操纵子网格的能力,它可以实现比 Grid 更复杂的布局,比如下面的例子:
.grid {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  grid-template-rows: repeat(4, minmax(100px, auto));
  gap: 20px;
}
.item {
  display: grid;
  grid-column: 2 / 7;
  grid-row: 2 / 4;
  grid-template-columns: subgrid;
  grid-template-rows: subgrid;
  row-gap: 0;
}
.subitem {
  grid-column: 3 / 6;
  grid-row: 1 / 3;
}

多列布局(Multi-Column)
又是个我没用过的,不过好像这几年趋势变化也不大,大部分人还是没用过。

查了下,还挺好用的,之前这样的事我都是用 display:inline-block 去搞,现在一个属性就搞定了。
<div class="container">
  <h1> code秘密花园 h1>
  <p> ConardLi p>
  <p> 一些文本 ... p>
div>
.container {
  column-count: 3;
}
比如上面的 container 容器中有三个块级元素,给 container 指定 column-count: 3 后就可以让浏览器自动分成三列,并且计算出每一列分配多少空间。

position: sticky
这个就是我们平时所谓的吸顶布局,相信大多数小伙伴都用过或者了解过了。

逻辑属性(Logical Properties)
逻辑属性,是 CSS 新引入的的一项变革性能力,它的属性与值能做从逻辑角度控制布局,而不是从物理、方向或维度来控制。

目前调查来看,用过的人也不是很多,我们来简单介绍一下。
传统的 CSS 属性大多是采用物理属性来定义的,比如元素的尺寸,偏移和边距等属性。但是随着业务的发展,越来越多的web应用需要考虑到国家化,必须适配不同的语言。
大部分国家的语言排版都是从左到右,即LTR(left to right),但是仍然有一部分语言采用的是从右到左,即RTL(right to left)的版本布局,比如阿拉伯语和希伯来语等。

图片展示了拉丁文,希伯来文和日语三种不同的书写方式。
逻辑属性 不仅可以让前端的布局在逻辑上更加严谨,而且能让开发者以更少的代码写出兼容性更好的页面。我们来看个简单的例子:
html
    <h3>物理布局h3>
    <div class="container" id="">
        <div class="box">codediv>
        <div class="box">秘密花园div>
    div>
    <h3>逻辑布局h3>
    <div class="container" id="logic">
        <div class="box">codediv>
        <div class="box">秘密花园div>
    div>
css
        :root {
            --size: 100px;
        }
        .container {
            display: flex;
            margin-top: 20px;
            padding: 10px;
            border: 1px solid #000;
            /* direction: rtl; */
        }
        .box {
            width: var(--size);
            height: var(--size);
            line-height: var(--size);
            text-align: center;
            background-color: rgb(170, 231, 71);
        }
        .container:nth-of-type(1) .box:last-child {
            margin-left: 10px;
        }
        .container:nth-of-type(2) .box:last-child {
            margin-inline-start: 10px;
        }
当页面布局是正常的从左到右排列时,效果是一样的:

现在我们把容器的排列方式改成:direction: rtl;,我们会发现物理布局出了问题:

在这段 CSS 里,margin-inline-start 就是一条逻辑属性,它可以让 margin 随着排版方向的变化而变化,而不是固定死的某一个方向。
向这样的逻辑属性还有很多:

aspect-ratio
用于指定图片的纵横比,调查中大概 37% 的人用过。

我在之前很多篇文章中都提到过,是一个很好用的属性:
给定图片的纵横比后,浏览器可以自动计算图片尺寸,可以用来提升 CLS 指标。
aspect-ratio: 1 / 1;
/* 全局值 */
aspect-ratio: inherit;
aspect-ratio: initial;
aspect-ratio: unset;
content-visibility
一个可以控制页面元素渲染的强大 CSS 属性,使用度今年好像和去年变化不大。

之前专门写过一篇文章来介绍它:
浏览器在接收到服务端返回的 HTML 之后,需要把这段数据渲染成用户看到的页面,在开始渲染第一个元素之前可能还需要经过很多步骤。这个过程会适用于整个页面,包括当前不可见的内容。
所以在首屏渲染时,是有很大一部分时间花费在用户不可见的内容上,实际上这部分数据我们没必要在首屏就把它们渲染出来。
content-visibility: auto 可以告诉浏览器暂时跳过该元素的布局和渲染工作,直到这个元素滚动到当前视口,从而可以加快整个页面的初始渲染,并且缩短用户和页面可交互需要花费的时间。
不过目前兼容性还比较差,慎重使用:

Container Queries
容器查询,目前还是一个在实验中的 CSS 特性,只有 5% 的人用过。

在我们要写一个响应式页面时,一般会试用媒体查询(@media)根据不同的页面尺寸进行不同的布局。
但是,@media 针对的是整个页面的显示大小,然而对于一些特定页面结构中的组件(例如在左右分栏的页面结构中的卡片),明明我们只是想根据组件的大小来调整布局,然而却得考虑整个网页的布局,以推测在不同页面大小下这个组件能够拥有的空间。
比如说,在下面这个布局中,组件可能是横向展示的,也可能是纵向展示的。如果宽度空间够的话,它显示为两列,如果没有空间,将会上下堆叠显示。

这时候我们就可以用到容器查询:
@container (min-width: 400px) {
  .c-article {
    display: flex;
    flex-wrap: wrap;
  }
}
@container (min-width: 700px) {
  .c-article {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 350px;
  }
  .card__thumb {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}
目前兼容性感人:

如果想试用,还要开启一个实验配置:chrome://flags/#enable-container-queries
图形和图像
CSS 图形 (Shape)
CSS Shape 描述了在 CSS 中使用的几何形状的方式,它可以实现不规则的文字环绕效果,发展得真不咋地,没了解过的居然越来越多了 ...

比如,我们左侧有个圆形的图片,我们想把右侧的文字环绕效果也改成圆形:

这时,我们就可以用到 shape-outside,它是不规则形状环绕布局的核心,有下面几个值:
circle()– 圆ellipse()– 椭圆inset()– 内矩形(包括圆角矩形)polygon()– 多边形
我们将它指定为 circle(50%),就可以实现圆形文字环绕效果。
img {
  float: left;
  shape-outside: circle(50%);
}
    
object-fit
object-fit 是个比较常用的 CSS 属性,它可以指定可替换元素的内容应该如何适应到其使用的高度和宽度确定的框。

简单的说,通过这个属性我们可以让一个元素自适应外部容器:

object-fit 有下面五个值:
fill替换的内容正好填充元素的内容宽,替换内容拉伸填满整个content box,不保证保持原有的比例。contain保持原有的尺寸比例。保证替换内容尺寸一定可以在容器里面放得下。因此,此参数可能在容器内一下空白。cover保持原有的尺寸比例。保证替换内容尺寸一定大于容器尺寸,宽度和高度至少有一个和容器一致。因此,此参数可能会让替换内容部分区域不可见。none保持原有的尺寸比例。同时保持替换内容原始尺寸大小。scale-down内容的尺寸与none或contain中的一个相同,取决于它们之间谁得到的对象尺寸会更小。
clip-path
这个做动画的同学应该平时也用的比较多,我们可以用它来裁剪出一个元素的可视区域,从调查来看使用者也越来越多。

clip-path 是 clip 的升级版,它们的作用都是对元素进行 “剪裁”,不同的是 clip 只能作用于 position 为 absolute 和 fixed 的元素且剪裁区域只能是正方形,而 clip-path 更加强大,可以以任意形状去裁剪元素,且对元素的定位方式没有要求。

混合模式 (Blend Modes)
,是一种 CSS 数据类型,也就是我们常说的混合模式,可以用来描述当元素重叠时,颜色应当如何呈现。

当元素重叠时,混合模式是计算像素最终颜色值的方法,每种混合模式采用前景和背景的颜色值,执行其计算并返回最终的颜色值。最终的可见层是对混合层中的每个重叠像素执行混合模式计算的结果。
简单点说,就是有两张不同颜色的图片叠加时,中间重合的部分应该怎么展示。我们来看个简单的例子:
        body {
            text-align: center;
            color: #000;
            background-image: linear-gradient(90deg, #fff 49.9%, #000 50%);
        }
        h1 {
            font-size: 100px;
        }
网页的两边分别有不同的两种颜色,我们在网页中间添加了个文本,文本的颜色和右边的网页颜色重合,所以右边啥也看不到:

这时,我们该动一下文班的混合模式:
        h1 {
            font-size: 100px;
            color: #fff;
            mix-blend-mode: difference;
        }
就可以实现下面的效果:

mix-blend-mode: difference 的意思就是重合部分取两种颜色的差值,除了difference,另外还有 darken(变暗)、lighten(变暗)、screen(滤色) 等等。
CSS 滤镜效果
调查报告里使用最广的 CSS 属性之一,相信大多数小伙伴也都用过。

一张图看懂它的主要用途:

color-gamut
99% 的人都没用过 ... 恭喜荣登本报告中知道的人最少的特性。

一个非常高级的用法,可以让我们根据输出设备的支持色域分类应用不同的样式,涨姿势了 ... 。
@media (color-gamut: srgb) {
  p {
    background: #f4ae8a;
  }
}
perspective
顾名思义,就是透视的意思,可以让我们实现一些简单的 3D 效果,不过现在用纯 CSS 写 3D 效果的少了,所以这个特性也用的越来越少了:

perspective 其实本质上是指定观察者与 z=0 平面的距离,从而让有三维位置变换的元素产生透视效果。z>0 的三维元素比正常大,而 z<0 时则比正常小,大小程度由该属性的值决定。

Intrinsic Sizing
Intrinsic Sizing,即内在尺寸,今年第一次参加调查,但是大部分人都了解或者用过了,但是据我了解国内的网页里这个属性用的不错,因为对中文不太友好。

CSS 中存在两种尺寸:内在尺寸(intrinsic)和外在尺寸(extrinsic)。元素的 width、height 设置的固定属性值,就是指外部尺寸。而内部尺寸,则是由元素包含的内容决定的。
我们来看洗面这个例子,两个 P 标签分别用两种内容的内在尺寸决定它本身的宽度。
        h1 {
            border: 1px solid red;
            width: min-content;
        }
        .min {
            width: min-content;
        }
        .max {
            width: max-content;
        }
min-content:宽度等于最长单词的宽度min-content:宽度等于整条内容的宽度(大概相当于display:inline-block+white-space:nowrap)

这个章节其实还提到了 backdrop-filter、conic-gradient()、color()、accent-color,我没啥兴趣,所以就直接略过了。
交互
CSS 滚动捕捉
CSS 滚动捕捉可以让用户完成滚动之后将视口锁定到某个元素的位置,这种效果经常出现在某些官网的网站里。

实现滚动捕捉主要依靠两个属性:容器元素的 scroll-snap-type 属性,以及子元素的  scroll-snap-align 属性。
scroll-snap-type:mandatory告诉浏览器,在用户停止滚动时,浏览器必须滚动到一个捕捉点。scroll-snap-align可以指定元素的哪一部分吸附到容器上,start指的是元素的顶部边缘。如果你水平滚动,它指的是左边缘。center和end属性值与此同理。
来个简单的 Demo:
    <div class="slider">
        <section id="s1">
            <h1>你好啊h1>
        section>
        <section id="s2">
            <h1>ConardLih1>
        section>
        <section id="s3">
            <h1>code秘密花园h1>
        section>
    div>
        .slider {
            font-family: sans-serif;
            scroll-snap-type: x mandatory;
            display: flex;
            -webkit-overflow-scrolling: touch;
            overflow-x: scroll;
        }
        section {
            border-right: 1px solid white;
            padding: 1rem;
            min-width: 100vw;
            height: 100vh;
            scroll-snap-align: start;
            text-align: center;
            position: relative;
        }
        h1 {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            text-align: center;
            color: white;
            width: 100%;
            left: 0;
            font-size: calc(1rem + 3vw);
        }
你可以实现下面的效果:

overscroll-behavior
可以控制,滚动条到达滚动区域的边界时的行为。

比如我们在网页的右下角放了个机器人聊天窗口,我们在滚动聊天消息的时候,如果滚动到了底部,页面的其他部分也会跟着滚,这时候就可以用 overscroll-behavior-y: contain; 来设置在当前区域已经滚动到底部时,不会带动其他区域滚动。
touch-action
touch-action 可以用于设置触摸屏用户如何操纵元素的区域(平滑、缩放、单指平移手势、手指平移和缩放等等),一般我们会在适配移动端操作的网站上会用到,变化趋势也不大,不再多说。

pointer-events
pointer-events 是个老属性了,可以用来控制特定元素和场景下的鼠标事件。

比如,我们想禁用一个元素的点击事件,就可以用 pointer-events:none,这不仅仅会禁用元素的 hover 效果,而是真正的移除了 click 事件。
另外还有一些就是针对 SVG 元素的特定属性了,比如 pointer-events: fill;:

scroll-timeline
scroll-timeline 是一个可以更灵活的控制滚动动画的属性,在被采访者中只有 2.5% 的人用过。

scroll-timeline 还是一个比较早期的提案,属于 Scroll-Linked Animations 规范的一部分:

像让页面滚动条滚动到某个位置、标题固定在顶部、面顶部展示你页面进度、或者是一些我们所说的视差滚动效果等等,在以前我们可能要借助 JavaScript 才能实现,现在我们可以使用 @scroll-timeline,比如下面的代码:
@scroll-timeline scroll-in-document-timeline {
  source: auto;
  orientation: vertical;
  scroll-offsets: 0%, 100%;
}
source表示滚动的元素,默认情况下就是documentorientation确定应当触发动画滚动方向。默认情况下是verticalscroll-offsets用于描述动画应处于活动状态的范围,它可以是相对、绝对值或者基于元素的偏移。
然后,我们将上面声明的时间轴动画的名称设置给 animation-timeline 属性,就可以和 CSS 动画关联上了。
#progressbar {
  animation: 1s linear forwards adjust-progressbar;
  animation-timeline: scroll-in-document-timeline;
}
排版
font-variant
font-variant 代表的其实是一组控制字体的 CSS 属性,从调查来看,用的人越来越少了 ...

我们平时在开发里用的最多的可能就是 font-variant:small-caps; 了,它可以把所有小写字母转成大写。

其实除了 font-variant-caps ,它还包括下面几个子属性:
font-variant-numeric: 控制数字的展示形式font-variant-alternates: 控制备用字体的使用font-variant-ligatures: 控制是否连字展示
initial-letter
initial-letter 可以控制首字母的展示形式,比如上升、下沉等效果,不过兼容性极差,也是用的人越来越少了。

line-clamp
line-clamp 可以用来限定一个块级容器中展示内容的行数,这个平时应该用的比较多。

比如,我们要限定一个容器中最多展示两行,文字,超过两行的内容用省略号替代:
        .box {
            width: 300px;
            height: 100px;
            border: 1px solid red
        }
        p {
            display: -webkit-box;
            -webkit-box-orient: vertical;
            -webkit-line-clamp: 2;
            text-overflow: ellipsis;
            overflow: hidden;
            -webkit-box-orient: vertical;
            word-wrap: break-word;
            word-break: break-all;
        }

Variable fonts
可变字体(Variable Fonts),今年第一次参与调查,大概 20% 的人有用过。

一般来说,字体的不同格式,比如斜体、粗细、拉伸存储在分开的单个文件内,而现在,你可以存储多种字体格式在一个 openType 可变字体文件内,所以,这种文件相对来说体积会更小。

另外,我们可以借助 Variable Fonts 为网站提供更丰富、更灵活、更细粒度的的自定义字体能力(比如说 font-weight:550 就是属于细粒度的字体控制),以适应不同风格和主题的变化。

其他特性
CSS 变量(自定义属性)
CSS 变量,使用率已经高达 84%,没听过的仅有 2.8%。

用法很简单,声明变量的时候,变量名前面要加两根连词线(--),相信大多数小伙伴也都用过,不再多说:
:root {
    --bg-color: red;
}
.title {
    background-color: var(--bg-color);
}
.desc {
    background-color: var(--bg-color);
}
特征查询(Feature Support Queries)
特征查询也就是 @supports,是条件规则的一种,可以用来检测当前浏览器是否支持某个CSS属性,这个确实挺实用的,使用率逐年增长。

用法广泛,比如下面几种:
检测是否支持指定的 CSS 属性
@supports (animation-name: test) {
    @keyframes { 
      …
    }
}
检测是否不支持指定的CSS属性
@supports ( not ((text-align-last:justify) or (-moz-text-align-last:justify) ){
    … /* 这里的CSS代码用来模拟text-align-last:justify */
}
测试是否支持某个自定义属性
@supports (--foo: green) {
  body {
    color: var(--varName);
  }
}
测试浏览器否支持某个选择器
@supports not selector(:is(a, b)) {
  /* 不支持 :is() 时的备选方案 */
  ul > li,
  ol > li {
    … /* 以上给不支持 :is(...) 的浏览器展开了 CSS 选择器规则 */
  }
}

不过,作为一个用来做兼容性检测的特性,居然在 IE 下全跪,只能说 IE 牛逼!
CSS 约束 (Containment)
CSS contain 属性允许开发者声明当前元素和它的内容尽可能的独立于 DOM 树的其他部分,这是个性能优化利器,居然只有不到 10% 的人用过。

contain 属性的主要目的是隔离指定内容的样式、布局和渲染。开发人员可以使用这个 contain 属性来限制指定的 DOM 元素和它的子元素同页面上其它内容的联系;我们可以把它看做一个 iframe 。跟 iframe 很相似,它能建立起一个边界,产生一个新的根布局;保证了它和它的子元素的 DOM 变化不会触发父元素重新布局、渲染等。
这个属性在包含大量独立组件的页面非常实用,它可以防止某个小部件的 CSS 规则改变对页面上的其他东西造成影响,contain 属性有以下七个值:
none无layout开启布局限制style开启样式限制paint开启渲染限制size开启size限制content开启除了size外的所有限制strict开启 layout, style 和 paint 三种限制组合
对于页面上的一些独立的小部件,都推荐使用 contain: strict;,对页面性能很有帮助,目前使用度还比较低,强烈推荐!
will-change
will-change 也是一个用来做性能优化的属性,相比上面的 contain,它的使用度要高一点。

当我们通过某些行为(点击、移动或滚动)触发页面进行大面积绘制的时候,浏览器往往是没有准备的,只能被动使用 CPU 去计算与重绘,由于没有事先准备,应付渲染够呛,于是掉帧。
will-change 可以在行为触发之前告诉浏览器我们要进行一些什么样的变化操作,让浏览器好有个准备,启动 GPU 为你渲染动画。
当然,用好这个属性也有点难度,一般直接写在 CSS 的默认状态中是没用的,下面我们举两个简单的例子:
结合 JavaScript 用:
var el = document.getElementById('element');
// 当鼠标移动到该元素上时给该元素设置 will-change 属性
el.addEventListener('mouseenter', hintBrowser);
// 当 CSS 动画结束后清除 will-change 属性
el.addEventListener('animationEnd', removeHint);
function hintBrowser() {
  // 填写上那些你知道的,会在 CSS 动画中发生改变的 CSS 属性名们
  this.style.willChange = 'transform, opacity';
}
function removeHint() {
  this.style.willChange = 'auto';
}
在 CSS 里用:
.will-change {
 transition: transform 0.3s;
}
.will-change:hover {
 will-change: transform;
}
.will-change:active {
 transform: scale(1.5);
}
如果用好的话,也是性能优化的一大利器。
calc()
计算属性,使用率已经高达 93%,相信大多数同学都用过了。

不多说了, 在布局和动画中都是非常常用的,比如 height: calc(100vh - 80px);。
Houdini
Houdini 是个非常强大的能力,可以扩展 CSS 的跨浏览器绘制能力,木过的人只有 3%。

Houdini 通过 Typed Object Model 启用更多的语义化 CSS 。开发者可以通过属性和值 API 定义具有语法、默认值和继承的高级 CSS 自定义属性。

我之前专门写了一篇文章介绍 Houdini ,感兴趣的话可以看:
CSS 比较函数 (Comparison Functions)
CSS 中的 min,max 函数都是属于比较函数,作用类似于 js 函数中的 min,max,用于取多个属性中的最小值或者最大值,属性之间用逗号分隔,比如(width: min(100px,200px,300px);)

预处理
在开始之前,我们先对常用的几大预处理框架做个简单的对比:
Sass/Scss:sass分为sass和scss两个语法分支,scss是兼容 css 的写法,很容易上手,同时继承了sass的优点,用的比较多的是scss,sass的语法则是用缩进来代替花括号、省略了结尾分号。sass速度更快且易安装,因为scss兼容 css 写法,写起来更容易上手,像bootstrap、Element也在使用 scss 作为 css 预处理器使用。Less:日常开发Less和Scss差不多,都是偏原生语法,比较容易接纳,less有个优势就是可以“不用编译”,为啥加引号呢,因为它确实可以做到不手动编译,在引入less的后面引入less.js即可,但是作为最佳实践,你始终应该去编译它,因为大多数情况下,编译它并不会花掉你太多时间。stylus采用了sass类似的缩进来表示层级,以及省略了分号等等,声明变量也不再需要 $ 或者 @ 符号,变量名和变量值之间使用 = 作为分隔,同时stylus允许传统css语法和stylus语法混用。因为其精简的太多,代码量可以更少,但是阅读起来可能不是那么美妙。PostCSS一个使用JS插件来转换样式的工具,它跟CSS预处理器的定位其实不同,它的作用主要有lint css,支持CSS Next语法,自动添加前缀等等功能,通过插件,基本上可以覆盖 CSS 预处理器的功能,同时可以实现很多预处理器实现不了的功能。优势在于其丰富的插件生态,能够覆盖开发中的方方面面,我们又能够很容易的开发自己的插件。
满意度
PostCSS 常年第一,不过今年新参加的 Assembler CSS 好像有点惨,关注度还行,不过无论是使用度还是满意度都比较差。

使用度
Sass 使用度仍然第一,PostCSS 反超 Less。

随着时间变化的体验
这个比较有意思,Less、Sass 的满意度随时间推移都是有所下降的,而 PostCSS 在逐步上升。

积极和消极程度

CSS 框架
框架就不做过多介绍了,使用过的基本上都知道。
满意度
这里的亮点是 Ant Design,满意度逐年增长,国货之光啊!

使用度
没想到 Bootstrap 还能占据第一,我 5 年前就放弃了,另外老外用的比较多的还是 Tailwind CSS ,增长率非常快,Ant Design 还是我们用的比较多,整体使用度只有 16% 。

CSS-in-JS
我个人也在用 CSS-in-JS ,第一个它解决了命名的痛点,传统的 css 方案,因为 class name是全局的,你就要保证它的唯一性,你要把你的组件名等各种 namespace 作为 class name 的前缀,以保证唯一性,css in js 就解决了这一点。另外,使用 CSS-in-JS 使用 js 动态控制样式会更简单。
满意度
大部分 CSS-in-JS 框架的满意度都有所下降...

这个也比较正常,因为它的缺点也比较明显,一直没得到解决:
运行时消耗:于大多数的 CSS-in-JS的库都是在动态生成CSS的,一般都会有些性能损耗,而且包体积会稍大一些。代码可读性差:大多数 CSS-in-JS实现会通过生成唯一的CSS选择器来达到CSS局部作用域的效果,这些自动生成的选择器会大大降低代码的可读性。没有统一的业界标准 CSS-in-JS只是一种技术思路而没有一个社区统一遵循的标准和规范,所以不同实现的语法和功能可能有很大的差异。
使用度
这个没啥变化,Styled Components 的使用率是最高的。

通过 Styled Components ,你可以使用 ES6 的标签模板字符串语法为需要 styled 的 Component 定义一系列 CSS 属性,当该组件的JS代码被解析执行的时候, Styled Components  会动态生成一个 CSS 选择器,并把对应的 CSS 样式通过 style 标签的形式插入到 head 标签里面。动态生成的 CSS 选择器会有一小段哈希值来保证全局唯一性来避免样式发生冲突。
我个人用的是 Emotion CSS ,它和 Styled Components 基本上差不多,不过它对  sourcemap 的支持会更好一点。
import { css, jsx } from '@emotion/react'
const color = 'darkgreen'
render(
  <div
    css={css`
      background-color: hotpink;
      &:hover {
        color: ${color};
      }
    `}
  >
    Hello ConardLi
  div>
)
CSS-in-JS Playground 是一个可以快速尝试不同 CSS-in-JS 实现的网站,如果你想做技术选型,可以去看看:

大奖
使用度采用最多的特性: CSS 比较函数,相比去年增长了15.5%。最高满意度: PostCSS再次以 91% 的满意度位居榜首。最受关注: CSS Modules再次以74%的比例引起了 CSS 开发人员的最大兴趣。
调查范围

最后吐槽一下这个报告的调查范围,中国这么多开发者居然只调查了 75 个人,占所有受访者的 0.9% ,差评!
最后
本文中只节选一些报告中我感兴趣的内容,并非报告全文,想要了解更多请查看报告原文:https://2021.stateofcss.com/
我的书 「《算法通关之路》」 已经出版了,想要突破算法面试的朋友不要错过,京东淘宝当当亚马逊等均有出售,电子版也有哦~
后台回复:typescript,获取我写的 typescript 系列文章,绝对精品 后台回复:电子书,自动获取我为大家整理的大量经典电子书,省去你筛选以及下载的时间 后台回复:不一样的前端,自动获取精选优质前端文章。 后台回复:算法,自动获取精选算法文章。另外也可关注我的另外一个专注算法的公众号力扣加加。 后台回复:每日一荐,自动获取我为大家总结的每日一荐月刊,内含精品文章,实用技巧,高效工具等等 

