前端必看!6 个主流浏览器已支持的 CSS 原生交互特性

AI 概述
近年CSS多项新特性可替代大量JS交互,性能更佳。文章介绍6个主流浏览器已支持的能力::has()选择器实现父元素监听子状态;@container容器查询完成组件级响应式;滚动驱动动画实现高性能滚动动画;@starting-style支持display切换动画;field-sizing:content让textarea自适应高度;锚点定位原生实现气泡弹窗,简化前端开发,减少JS代码。
目录
文章目录隐藏
  1. :has() 选择器 —— 让父元素感知子元素
  2. @container 容器查询
  3. 滚动驱动动画 —— 彻底干掉 scroll 事件监听
  4. @starting-style —— 原生实现 display: none 的入场动画
  5. field-sizing: content——自动撑高的 textarea
  6. CSS Anchor Positioning —— 原生的气泡定位
  7. 结语

前端必看!6 个主流浏览器已支持的 CSS 原生交互特性

最近几年 CSS 的更新真的颠覆了很多老前端开发的固有认知。以前写页面,但凡涉及状态响应、组件自适应、滚动动画、弹窗气泡这类需求,第一反应就是上 JS。但不少人还没意识到,大量过去必须手写脚本才能完成的交互,如今只用 CSS 就能实现,而且是跑在浏览器渲染底层,性能远优于 JS 方案。下面整理了 6 个已经得到主流浏览器支持,但国内很多前端还没用起来的 CSS 新特性。

:has() 选择器 —— 让父元素感知子元素

在 CSS 长达 20 多年的历史里,有一个让所有前端痛彻心扉的缺陷:你永远无法根据子元素的状态,去反向控制父元素的样式。

:has() 选择器 —— 让父元素感知子元素

比如一个极其常见的表单场景:当输入框获得焦点时,让它的外层容器高亮。过去你必须用 JavaScript 监听 focus 和 blur 事件,手动给父元素切换 class。

JavaScript 手动监听

// 为了让父容器感知子元素的焦点状态,被迫写一坨事件监听🤷‍♂️
const input = document.querySelector('.form-input');
const wrapper = document.querySelector('.form-wrapper');

input.addEventListener('focus', () => {
  wrapper.classList.add('is-focused');
});


input.addEventListener('blur', () => {
  wrapper.classList.remove('is-focused');
});

CSS

.form-wrapper.is-focused {
  border-color: #3b82f6;
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3);
}

现在是一行 CSS 直接秒杀

/* 父元素直接感知内部 input 的焦点状态,零 JavaScript */
.form-wrapper:has(input:focus) {
  border-color: #3b82f6;
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3);
}

:has()选择器的威力远不止如此。你可以用.card:has(img)来区分有图和无图的卡片布局;用form:has(:invalid)来在表单存在校验错误时,直接禁用提交按钮的视觉样式;甚至用body:has(.modal-open)来在弹窗打开时锁定背景滚动。

这一个选择器,干掉了过去无数的状态切换 JavaScript。更多推荐阅读《CSS 无比强大的:has 伪类的使用技巧

@container 容器查询

传统的@media媒体查询,响应的是整个视口的宽度。但在组件化开发的时代,同一个卡片组件可能被放在宽度 300px 的侧边栏里,也可能被放在宽度 800px 的主内容区里。视口宽度根本不能反映组件自身的实际空间。

过去为了实现组件级响应式,你不得不引入ResizeObserver,写一大段 JavaScript 去监听容器尺寸变化,然后手动切换布局。

@container 容器查询

ResizeObserver 的手动监听

// 为了让卡片组件根据自身容器宽度切换布局,被迫引入 JS 观察者
const observer = new ResizeObserver(entries => {
  for (const entry of entries) {
    const width = entry.contentRect.width;
    if (width < 400) {
      entry.target.classList.add('compact');
      entry.target.classList.remove('wide');
    } else {
      entry.target.classList.add('wide');
      entry.target.classList.remove('compact');
    }
  }
});

observer.observe(document.querySelector('.card-container'));

纯 CSS 容器查询

/* 声明容器 */
.card-container {
  container-type: inline-size;
}

/* 组件根据自身容器的宽度自动切换布局,零 JavaScript */
.card {
  display: grid;
  grid-template-columns: 1fr;
}

@container (min-width: 400px) {
  .card {
    grid-template-columns: 200px 1fr;
  }
}

组件不再需要关心自己被放在了页面的哪个位置,它会根据自身的物理空间自动适配布局。这是 CSS 有史以来最接近智能组件的能力跃迁。

滚动驱动动画 —— 彻底干掉 scroll 事件监听

过去,凡是和滚动相关的动画效果(进度条、视差、淡入淡出),你都必须监听 scroll 事件。而 scroll 事件是浏览器中触发频率最高的事件之一,处理不好极其容易导致主线程卡顿和掉帧。

滚动驱动动画 —— 彻底干掉 scroll 事件监听

JavaScript 监听滚动

// 为了实现一个顶部阅读进度条,被迫疯狂监听 scroll 事件
window.addEventListener('scroll', () => {
  const scrollTop = document.documentElement.scrollTop;
  const scrollHeight = document.documentElement.scrollHeight - window.innerHeight;
  const progress = (scrollTop / scrollHeight) * 100;
  document.querySelector('.progress-bar').style.width = `${progress}%`;
});

这段代码在用户快速滚动时,每秒会触发几十次甚至上百次回调,直接榨干主线程的算力。
纯 CSS 滚动驱动动画

/* 顶部阅读进度条,完全由浏览器渲染引擎在合成层驱动,零 JS 零卡顿 */
.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  height: 3px;
  background: #3b82f6;
  width: 0%;

  /* 绑定到页面的滚动进度,浏览器底层自动计算 */
  animation: grow-progress linear;
  animation-timeline: scroll();
}

@keyframes grow-progress {
  from { width: 0%; }
  to { width: 100%; }
}

整个动画被完全交给了浏览器底层的合成线程(Compositor Thread) 去驱动,根本不会占用主线程的一丝算力。这种性能差距,不是优化几行 JavaScript 能弥补的,是架构层面的降维打击。

@starting-style —— 原生实现 display: none 的入场动画

这个特性解决了一个困扰前端十几年的深水区痛点:你无法对display: nonedisplay: block的切换做过渡动画。

过去,为了实现一个弹窗的淡入效果,你要么引入 Framer Motion 这种动画库,要么用 JavaScript 先把元素设为display: block,然后在下一帧再切换opacity,极其丑陋。

@starting-style —— 原生实现 display: none 的入场动画

JavaScript 双帧 Hack

// 为了让弹窗从 display:none 淡入,被迫写出这种恶心的双帧 hack
function showModal(el) {
  el.style.display = 'block';
  // 强制浏览器重排,否则 transition 不会触发
  el.offsetHeight; // 这行看起来毫无意义,但删掉动画就失效
  el.classList.add('visible');
}

纯 CSS 原生入场动画

.modal {
  display: none;
  opacity: 0;
  transition: opacity 0.3s ease, display 0.3s ease allow-discrete;
}

.modal.open {
  display: block;
  opacity: 1;

  /* 告诉浏览器:从 display:none 切换过来时,opacity 从 0 开始 */
  @starting-style {
    opacity: 0;
  }
}

浏览器原生支持了离散属性(如 display)的过渡动画。不需要任何 JavaScript,不需要任何动画库,一个弹窗的淡入淡出就被几行 CSS 完美解决了🤷‍♂️。

field-sizing: content——自动撑高的 textarea

过去,为了让一个多行输入框根据内容自动调整高度(而不是固定一个死板的高度),你需要用 JavaScript 去监听 input 事件,动态计算scrollHeight并赋值给style.height

field-sizing: content——自动撑高的 textarea

JavaScript 手动撑高

const textarea = document.querySelector('textarea');
textarea.addEventListener('input', () => {
  textarea.style.height = 'auto'; // 先重置,否则只会越来越高
  textarea.style.height = textarea.scrollHeight + 'px';
});

现在是一行 CSS

textarea {
  field-sizing: content; /* 浏览器根据内容自动撑高,零 JavaScript */
}

一行 CSS,干掉了一个在前端圈流传了十几年的经典 JavaScript Hack 🖐️。

相关推荐《CSS 新增 field-sizing 属性,如何让文本输入框根据输入内容动态调整大小?》、《CSS 新特性之表单尺寸属性 field-sizing

CSS Anchor Positioning —— 原生的气泡定位

过去,只要你需要实现一个 点击按钮弹出气泡提示框,且气泡自动贴在按钮旁边 的效果,你几乎必须引入 Popper.js 或 Floating UI 这种定位库。因为手动计算位置、处理边界溢出翻转,这套逻辑的复杂度极高。

CSS Anchor Positioning —— 原生的气泡定位

用 CSS 原生锚点定位

/* 声明锚点 */
.trigger-button {
  anchor-name: --my-anchor;
}

/* 气泡自动定位到锚点下方,溢出时自动翻转 */
.tooltip {
  position: fixed;
  position-anchor: --my-anchor;
  top: anchor(bottom);
  left: anchor(center);

  /* 原生的溢出翻转逻辑,浏览器自动处理 */
  position-try-fallbacks: flip-block, flip-inline;
}

不需要任何 JavaScript 库,不需要计算getBoundingClientRect,不需要处理滚动偏移。浏览器的渲染引擎直接在布局阶段帮你搞定一切,包括边界检测和自动翻转。这意味着你可以从项目的依赖里删掉一整个定位库。

结语

这些 CSS 新特性不是花里胡哨的锦上添花,而是实实在在减少 JS 代码、降低主线程开销、简化组件开发成本的工具。当然不是说要完全抛弃 JavaScript,业务复杂交互依旧需要 JS 配合。只是下次再碰到这类布局和简单交互场景,可以先想想:能不能交给 CSS 原生能力去做。少写脚本,Bug 自然也会跟着变少。

以上关于前端必看!6 个主流浏览器已支持的 CSS 原生交互特性的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。

「点点赞赏,手留余香」

32

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » 前端必看!6 个主流浏览器已支持的 CSS 原生交互特性

发表回复