CSS新用法 - min()、max()、clamp()、:where()、:is()、:has()

这篇讲什么

CSS 这几年新增了一批函数式选择器,大幅简化了以前需要写一堆代码才能完成的需求。本文挑 6 个最常用的:min() / max() / clamp() 三个函数,:where() / :is() / :has() 三个选择器。

CSS新用法 - min()、max()、clamp()、:where()、:is()、:has()

min() - Chrome 79+ / 全浏览器支持

min() 函数取多个值中最小的,常用于"响应式宽度":想要某个最大宽度,但小屏幕时跟着屏幕缩。

/* 这个例子没什么意义,因为最小值永远都是200px */
div {
  width: min(400px, 200px, 300px);
}

这条 width: min(100%, 800px) 的含义:

  • 大屏幕(超过 800px):宽度 800px(800px 小)
  • 小屏幕(不到 800px):宽度 100%(100% 小)

替代了以前的写法 max-width: 800px; width: 100%;,一行搞定。

max() - 全浏览器支持

跟 min() 反过来,取最大。用于"最小宽度":

/* 如果100%比较小,那就是100%,如果800px比较小,则为800px */
/* 800px或者更小(比如100%代表700px,那就是700px),无最小宽度 */
div {
  width: min(100%, 800px);
}

/* 大概就是下面这个意思 */
div {
  width: 100%;
  max-width: 800px;
}

这条 width: max(50%, 300px):

  • 父容器宽度 > 600px 时(50% 也就是 300px+):用 50%
  • 父容器宽度 < 600px 时:固定 300px,不能再小

clamp() - 全浏览器支持

三参数,clamp(min, val, max)。"值在 min 和 max 之间,优先 val"。这是响应式字体的杀手锏。

/* 表示如果50vw小于300px,则width匹配300px,如果50vw大于 300px,则匹配50vw */
/* 300px或者更大,无最大宽度 */
div {
  width: max(300px, 50vw);
}

/* 大概就是下面这个意思 */
div {
  min-width: 300px;
  width: 50vw;
}

这条 font-size: clamp(16px, 4vw, 24px):

  • 正常情况:字体随 viewport 缩放,等于 4vw
  • 屏幕太小,4vw < 16px 时:固定 16px
  • 屏幕太大,4vw > 24px 时:固定 24px

这一招把"字体随屏幕缩放但有上下限"做成了一行,以前要写 media query 三段。

实际例子:

/* 宽度为90%,最小不会低于300px,最大不会高于700px */
div {
  width: clamp(300px, 90%, 700px);
}

/* 大概就是下面这个意思 */
div {
  width: 90%;
  min-width: 300px;
  max-width: 700px;
}

/* 当然你也可以写成这样让你的代码更加难以阅读 */
div {
  width: max(300px, min(90%, 700px));
}

:where() - Chrome 88+

选择器组合,但权重为 0。这是它的杀手特性 —— 等同于"语法糖,不增加 specificity"。

div {
  border: max(20px, calc(1vw + 10px)) solid;
}
/* 上面这样写,等价于下面这样 */
div {
  border: max(20px, 1vw + 10px) solid;
}

/* 或者使用变量 */
.var {
  --extra: 10px;
  border-width: max(20px, 1vw + var(--extra));
}

/* 纯算也是可以的 */
div {
  width: clamp(50px * 4 * 1.5, (100% / 2) * 2, 400px * 2);
}

对比传统写法:

/* 之前 */
input[type="text"],
input[type="email"],
input[type="url"],
input[type="tel"],
input[type="password"],
input[type="search"] {
  border: 2px solid;
}

/* 使用where */
input:where(
  [type="text"],
  [type="email"],
  [type="url"],
  [type="tel"],
  [type="password"],
  [type="search"]
) {
  border: 2px solid;
}

当你写 CSS reset 或者基础样式库时,用 :where() 包裹选择器,后续用户在自己代码里覆盖你的样式不需要额外提权重。

:is() - Chrome 88+

:where() 写法一样,但权重正常(取列表里最高那个的权重)。用作选择器简写:

/* 使用:is() */
a:is(:link, :visited) {
  color: green;
}

a:is(:hover, :focus) {
  text-decoration: none;
}

替代了:

/* 权重: 0 0 1 (0 id选择器, 0 类选择器, 1 标签选择器) */
button:where(.button1) {
  background-color: rebeccapurple;
}

/* 权重: 0 1 1 (0 id选择器, 1 类选择器,也就是is括号里的, 1 标签选择器,也就是最前面的button) */
button:is(.button2) {
  background-color: rebeccapurple;
}

需要权重时用 :is,不需要权重时用 :where

:has() - Chrome 105+ / 父选择器

这是 CSS 等了二十年的"父选择器" —— 根据子元素的存在 / 状态来匹配父元素。

/* 全部失效:因为并不存在touch,因为这个错误的touch,导致hover和focus即使写对了也无效 */
.button:hover,
.button:focus,
.button:touch {
  background-color: #09f;
}

/* 会忽略掉错误的,hover和focus可以正常生效,touch会被忽略 */
button:where(:hover, :focus, :touch) {
  background-color: #09f;
}

含义:"包含 img 子元素的 article",给它加上下 padding 24px。以前完全做不到,只能 JS。

更强大的组合:

<div class="box">
  <p class="children">
    <span>测试</span> 
  </p>
</div>

<div class="foo">
  
</div>

这种"表单里有 checkbox 被勾选时,改整个表单的样式"在 :has 出现前需要 JavaScript 介入。现在纯 CSS 搞定。

实际应用例子

结合多个新特性的实际场景:

/* 无关紧要的默认样式 */
.box,
.foo {
  width: 200px;
  height: 200px;
}

.foo {
  background-color: #000000;
}

/* 如果.box里面有.children的元素,则.box的颜色为#b5b7ff */
.box:has(.children) {
  background-color: #b5b7ff;
}

/* 但是has()不能嵌套使用 */
/* 下面的写法是无效的 */
.box:has(p:has(span)) {
  font-size: 14px;
}

/* 但是可以使用正常的选择器 */
/* 下面的写法是有效的 */
.box:has(p span) {
  font-size: 14px;
}

/* 甚至有更多的用法 */
/* .box的下边距为16px */
.box {
  margin-bottom: 16px; 
}

/* 如果.box的兄弟是.foo,则下边距为200px,文字大小变为32px */
.box:has(+ .foo) {
  margin-bottom: 200px; 
  font-size: 32px;
}

/* 无效:只适用于实际元素,不适用于伪元素 */
p:has(::before) {
  background-color: #f00;
}

浏览器兼容性总结

特性 Chrome Firefox Safari
min / max / clamp 79+ 75+ 13+
:where / :is 88+ 78+ 14+
:has 105+ 121+ 15.4+

2024+ 几乎所有浏览器都支持,放心写。

一句话总结

min/max/clamp 解决响应式数值;:where/:is 简化选择器语法;:has 给了 CSS 父选择器能力 —— 这一波更新让 CSS 直接跳过了一代写法,日常写代码值得用起来。

—— 别看了 · 2026
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理 邮箱1846861578@qq.com。
技术教程

CSS新用法 - :modal、::backdrop、:picture-in-picture、:placeholder-shown、inset、scrollbar-gutte、backdrop-filter

2024-6-6 11:35:14

技术教程

CSS 专业技巧

2024-6-6 11:46:08

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索