2024 年你可以安全地使用哪些 CSS 新特性?

开发 前端
gap 属性最先在网格布局(Grid Layout)和多列布局(Multi-column Layout)中实现(Chrome 66+),最终在弹性布局中也支持了,Chrome 84+ 兼容性足够我们放心使用了。

在过去的 4 年中,大量的 CSS 新特性涌现。不过对能在浏览器中安全使用的 CSS 特性我们要甄别,不然学过之后发现兼容性差得不行,那就有点得不偿失了。

这里总结了你可以在 2024 年可以安全使用的 CSS 特性。

1、CSS 逻辑属性

图片图片

兼容性:https://caniuse.com/css-logical-props

长期以来,许多 CSS 属性使用物理方向来设置值,如margin-top、padding-right、bottom、border-left 等。但在国际化(多语言环境)背景下,基于物理方位的设置无法适应不同书写模式下(writing-mode)一致的阅读、布局体验,于是便有了基于 Inline、Block 概念的逻辑属性(Logical properties)。

width: 40px; --> inline-size: 40px;
height: 20px; --> block-size: 20px;
margin-top: 12px; --> margin-block-start: 12px;
margin-bottom: 12px; --> margin-block-end: 12px;
margin-left: 14px; --> margin-inline-start: 14px;
margin-right: 14px; --> margin-inline-end: 14px;
margin-top: 12px; margin-bottom: 16px; --> margin-block: 12px 16px;
margin-left: 16px; margin-right: 16px; --> marign-inline: 16px;

2、容器查询

图片图片

兼容性:https://caniuse.com/css-container-queries

容器查询(Container queries)与媒体查询(Media queries)类似,不过媒体查询只支持使用浏览器宽度或高度作为查询条件,但容器查询则适用于任何容器,而不仅仅是浏览器。

容器查询根据功能又可以拆分成尺寸查询(Size Queries)和样式查询(Style Queries),其中样式查询支持有限,因此目前当我们谈论容器查询时,实际上是指容器查询中的尺寸查询。

.post {
  container: sidebar / inline-size;
  /*等同于 container-name: sidebar; container-type: inline-size;*/
}
@container sidebar (min-width: 700px) {
  .card {
    font-size: 2em;
  }
}

以上代码的含义:

  • 将类名为 .post 的元素声明为名为 sidebar 的容器,inline-size 表示这个容器的查询将基于它的内联尺寸(在默认文档流下 writing-mode: horizontal-tb;,效果等同于宽度 width)
  • container sidebar (min-width: 700px) {...} 则表示当名为 sidebar 的容器(即前面定义的 .post 元素)的内联尺寸(宽度)达到或超过 700p 时,其内部 .card 的元素的字体大小设置为 2em

3、:has()

图片图片

兼容性:https://caniuse.com/css-has

顾名思义,当需要根据元素内部是否某些特定元素来决定外部元素的样式时,就可以使用 :has 伪类。

理解 :has() 伪类最好的方式就是通过案例学习。

案例 1:当元素 <main> 内包含 <strong> 标签时,为 <main> 应用样式

main:has(strong) {
  /*... */
}

案例 2:当元素 <main> 内包含 p 和 <strong> 标签时,为 <main> 应用样式

main:has(p):has(strong) {
  /*... */
}

案例 3:当元素 <main> 内包含 p 或 <strong> 标签时,为 <main> 应用样式

main:has(p, strong) {
  /*... */
}

案例 4:当元素 <main> 内不含 <strong> 标签时,为 <main> 应用样式

main:not(:has(strong)) {
  /*... */
}

案例 5:当元素 <p> 后面是 <strong> 标签时,为 <p> 应用样式

p:has(+ strong) {
  /*... */
}

案例 6:当元素 <p> 后面有 <figure> 标签时,为 <p> 应用样式

p:has(~ figure) {
  /*... */
}

4、:is 和 :where

图片图片

:is 兼容性:https://caniuse.com/css-matches-pseudo

图片图片

:where 兼容性:https://caniuse.com/mdn-css_selectors_where

:is 和 :where 功能上完全一致,接受一个选择器列表作为参数,当列表中的任何一个选择器匹配时,就应用样式。

下面的写法是等价的:

ul li,
ol li {}

/* 等价于 */
:is(ul, ol) li {}
/* 或 */
:where(ul, ol) li {}

:is 和 :where 唯一不同之处在于,:where() 本身修改的选择器不算在权重计算,而 :is() 修改的选择器是算在权重计算的。

以下面的代码举例:

<div class="parent">
  <p class="child1">Child 1</p>
  <p class="child2">Child 2</p>
</div>

<style>
.parent p {
 color: blue;
}
:where(p.child1,p.child2) {
 color: green;
}
</style>

因为 :where 选择器权重为 0,因此 .parent p 的样式优先级更高,最终文本的颜色会是蓝色而不是绿色。

图片图片

如果把 :where 换成 :is,文本颜色就会是绿色,因为 :is 选择器会按照正常的选择器优先级规则来处理。

图片图片

CSS 权重计算工具:https://specificity.keegan.st/

5、CSS 嵌套

CSS 嵌套语法(CSS Nesting)允许在一个选择器内部嵌套另一个选择器,这样可以更好地提现 HTML 文档元素间的结构关系,这个语法最早是通过 SASS 这类 CSS 预处理器引入的,由于特别好用,最终成为 CSS 规范的一部分了!

图片图片

兼容性:https://caniuse.com/css-nesting

Chrome 从 112 版本开始支持 CSS 嵌套[2]。

借助 CSS 嵌套,你可以在某个选择器上下文中指定内部元素样式。

.parent {
  color: blue;

  .child {
    color: red;
  }
}

不过第一版本实现的 CSS 嵌套版本有一个限制,就是无法嵌套裸元素标记。

.card {
  h1 {
    /* Chrome 112 版本中这种写法是无效的! */
  }
}

/* 要写成带子引用前缀 & 的 */
.card {
  & h1 {
    /* Chrome 112 版本中这种写法才是有效的 */
  }
}

不过,这一限制在 Chrome 120 版本中修复了[3]。

.card {
  h1 {
    /* Chrome 120 版本开始这种写法是有效的! */
  }
}

这是我们在使用 CSS 原生嵌套语法时,唯一要注意的地方。

6、CSS 比较函数

CSS 比较函数(Comparison Functions)类似 if/else 判断,允许浏览器在你设定的多个值选择一个合适的值应用。这类比较函数共有 3 个:

  1. min(a, b):取 a 和 b 之间的最小值
  2. max(a, b):取 a 和 b 之间的最大值
  3. clamp(a, b, c) :取最小值 a、期望的值 b 和最大值 c 之间的最合适值

图片图片

兼容性:https://caniuse.com/css-math-functions

min、max 相对来说比较简单,因此我们略过直接讲 clamp。

以下面一段声明举例:

font-size: clamp(16px, 1vw + 1rem, 32px);

字体大小会根据视口宽度和根元素字体大小进行动态调整。

  1. 浏览器首先会尝试使用1vw + 1rem这个计算出来的值作为字体大小
  2. 如果这个值小于 16px,就会使用 16px
  3. 如果这个值大于 32px,就会使用 32px

这种方式可以在不同的设备(如手机、平板、桌面浏览器)上,提供一个相对合适的、自适应的字体大小,既保证了文本在小屏幕设备上字体足够大,又避免了在大屏幕设备上字体过大的问题。

7、级联层 @layer

图片图片

兼容性:https://caniuse.com/css-cascade-layers

级联层允许创建多个 CSS 级联并指定级联排序。

我们直接看案例:

<div class="overly" id="powerful">
  <div class="framework widget my-single_class">widget</div>
</div>

<style>
@layer framework {
  .overly#powerful .framework.widget {
    color: blue;
  }
}

@layer site {
  .my-single_class {
    color: red;
  }
}
</style>

以上,我们的“widget”文本最终会呈现红色。下面解释原因:

这段代码通过 @layer 将针对同一个元素的样式规则划分到了两个不同的层 framework 和 site 中。按照 @layer 的优先级规则,后声明的层优先级更高——也就是说,先看层级顺序,再看同层级内的权重。

图片图片

因此,“widget”文本最终会呈现红色。

当然,你还可以通过 @layer layer1, layer2..., layerN; 指定层级应用的顺序:

图片图片

可以看到,虽然书写顺序上 site 层级出现在 framework 之后,不过由于手动指定了层级次序:@layer site, framework;—— framework 在 site 之后,所以文本最终呈现蓝色。

8、子网格

图片图片

兼容性:https://caniuse.com/css-subgrid

子网格(Subgrid)的出现是为了解决传统的 CSS 网格布局(Grid Layout)在处理多层嵌套时的对齐问题。

直接听我说会比较抽象,我们先举一个例子进行说明:

<div class="wrapper">
  <div class="item">
    <div class="desc">short desc</div>
    <img src="https://picsum.photos/id/237/200/300" alt="" class="src">
  </div>
  <div class="item">
    <div class="desc">long desc long desc long desc</div>
    <img src="https://picsum.photos/id/237/200/300" alt="" class="src">
  </div>
</div>

<style>
.wrapper {
  display: inline-grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 1rem;
}

.item {
  width: 200px;
  grid-row: 1 / 4;
}
</style>

效果如下:

图片图片

可以看到,左右两边的描述文本由于长度不一样,导致最终渲染出来的元素视觉上不一样高。

这个时候,我们可以通过 subgrid 将父级网格行传递给内部项目。这里需要修改 .item 元素来实现。

.item {
  width: 200px;
  grid-row: 1 / 4;
+ display: grid;
+ grid-template-rows: subgrid;
}

这里增加了 2 行,首先明确网格项目本身也是一个网格容器,这是子网格生效的前提;接着,我们将 grid-template-rows 设定成一个特殊的关键字 subgrid。

再来看看效果:

图片图片

发现两个网格项目的描述文本对齐了!

grid-template-rows: subgrid; 的作用就是让网格项目继承父网格容器的行分配系统,或者说父子共用一套行分配系统,这样就能实现一致的对齐效果了。

更加使用案例可以参考 Ahmad Shadeed 的《Learn CSS Subgrid》[4] 这篇文章。

其他一些小而美的特性

text-wrap: balance

图片图片

兼容性:https://caniuse.com/css-text-wrap-balance

text-wrap: balance 让文本这行更好看,标题、内容元素皆可使用。兼容性不太好,但可以无脑用,作为渐进式特性还是很好的。

h1, h2, h3, h4, h5, h6, blockquote {
  text-wrap: balance;
}

效果:

图片图片

动态视口高度 dvh

图片图片

兼容性:https://caniuse.com/viewport-unit-variants

解决了 vh 单位不会考虑手机顶部地址栏、底部工具栏的问题。

图片图片

详情可以参考文章 The large, small, and dynamic viewport units[5]。

accent-color

图片图片

兼容性:https://caniuse.com/mdn-css_properties_accent-color

这个属性就比较牛了,可以用来设置某些用户界面控件元素的强调色。

图片图片

目前支持的元素包括单选框、复选框和进度元素(<input type=“range|checkbox|radio”>)。

媒体查询里的范围查询

图片图片

兼容性:https://caniuse.com/css-media-range-syntax

范围查询允许我们在媒体查询里使用使用 >、<、>= 或 <= 的数学比较运算符。其实旧语法也支持,不过不太直观。

我们直接举例说明范围查询的使用[6]:

/* 场景一:大于等于 400px 时应该样式 */

/* 旧语法 */
@media (min-width: 400px) {
}
/* 新语法 */
@media (width >= 400px) {
}

/* 场景二:小于等于 30em 时应用样式 */

/* 旧语法 */
@media (max-width: 30em) {
}
/* 新语法 */
@media (width <= 30em) {
}

/* 场景二:在 400px、600px 之间时(包含)应用样式 */

/* 旧语法 */
@media (min-width: 400px) and (max-width: 600px) {
}
/* 新语法 */
@media (400px <= width <= 600px )  {
}

弹性布局 gap 属性

图片图片

兼容性:https://caniuse.com/flexbox-gap

弹性布局中的 gap 属性可以让我们非常便捷的设置行/列间隔,替代了古早需要通过设置 margin/padding 属性来实现间隔效果的麻烦步骤。

值得注意的是,gap 属性最先在网格布局(Grid Layout)和多列布局(Multi-column Layout)中实现(Chrome 66+),最终在弹性布局中也支持了,Chrome 84+ 兼容性足够我们放心使用了。

参考资料

[1]New CSS that can actually be used in 2024: https://thomasorus.com/new-css-that-can-actually-be-used-in-2024.html

[2]Chrome 从 112 版本开始支持 CSS 嵌套: https://developer.chrome.com/blog/new-in-chrome-112?hl=zh-cn#nesting-rules

[3]这一限制在 Chrome 120 版本中修复了: https://developer.chrome.com/blog/css-nesting-relaxed-syntax-update?hl=zh-cn

[4]《Learn CSS Subgrid》: https://ishadeed.com/article/learn-css-subgrid/

[5]The large, small, and dynamic viewport units: https://web.dev/blog/viewport-units

[6]举例说明范围查询的使用: https://web.dev/articles/media-query-range-syntax

责任编辑:武晓燕 来源: 写代码的宝哥
相关推荐

2019-03-07 10:15:39

安全禁用Windows 10服务

2022-10-12 15:15:56

数字孪生物联网

2023-04-01 10:32:36

2020-04-24 11:00:08

数据泄露漏洞信息安全

2016-05-11 14:16:20

2018-03-21 07:08:40

2022-12-25 10:09:44

2022-03-09 08:14:24

CSS容器container

2014-06-06 14:33:29

BYOD移动安全

2022-07-04 10:11:33

云安全混合云云计算

2013-08-26 09:18:21

2023-12-11 09:02:27

CSS前端CSS 新特性

2012-03-24 21:02:41

iOS

2024-03-14 11:22:54

2021-12-03 00:02:01

通讯工具即时

2024-01-10 17:27:00

Python开发

2024-06-04 08:45:50

2024-07-19 08:13:00

2019-06-17 08:00:55

multipassbash脚本

2012-08-16 11:08:20

点赞
收藏

51CTO技术栈公众号