写过前端的人都踩过这个坑——判断一个元素显不显示,每次都要写一长串 getComputedStyle 递归查父元素,今天一个浏览器原生 API 把这件事彻底原生化了

写过前端的人都踩过这个坑——判断一个元素显不显示,每次都要写一长串 getComputedStyle 递归查父元素,opacity、visibility、display、content-visibility 四个属性漏掉任何一个都会出 bug。今天一个浏览器原生 API 把这件事彻底原生化了。

这个 API 叫 checkVisibility(),是 Element 接口的方法,Baseline Widely Available,Chrome 105+、Edge 105+、Firefox 106+、Safari 17.4+ 全部支持,全球约 95% 覆盖率。它的工作方式很简单:

const isVisible = element.checkVisibility();

一个调用,返回 true 或 false。

你不需要再写这种祖传代码了:

// 旧方式:递归查父元素,每次都触发同步布局
function isElementVisible(el) {
  let cur = el;
  while (cur) {
    const style = window.getComputedStyle(cur);
    if (style.display === "none") return false;
    if (style.visibility === "hidden") return false;
    if (parseFloat(style.opacity) === 0) return false;
    if (style.contentVisibility === "hidden") return false;
    cur = cur.parentElement;
  }
  return true;
}

现在一行搞定:

const isVisible = element.checkVisibility();

它内部会检查所有四种隐藏情况:display:none、visibility:hidden、opacity:0、content-visibility:hidden。

如果你只想检查某一个维度,可以传 options 精细控制:

// 只检查 opacity
element.checkVisibility({ opacityProperty: true });

// 只检查 visibility
element.checkVisibility({ visibilityProperty: true });

// 检查 content-visibility:auto 是否正在跳过渲染
element.checkVisibility({ contentVisibilityAuto: true });

它的核心价值在于性能。getComputedStyle 是同步的,每次调用都会触发浏览器的样式计算重排,在循环里调用上百次会直接影响页面响应。而 checkVisibility() 是浏览器内部实现的一次性检查,不需要反复跨 JS/CSS 边界,代价低得多。

它和 content-visibility: auto 配合效果最好。当页面上有一大段列表被标记为 content-visibility: auto 时,浏览器会跳过那段内容的渲染以提升性能。但如果某段内容从隐藏状态变为可见(比如用户展开了一个折叠区),你需要知道这件事——用 checkVisibility({ contentVisibilityAuto: true }) 可以准确检测到,而不依赖 getComputedStyle 的笨拙遍历。

需要注意一点:checkVisibility() 返回 true 只代表元素”可能可见”,不代表用户真的能看到。它不会判断元素是否在视口内、是否被其他内容遮挡。所以如果你要判断”用户是否看到了这个元素”,IntersectionObserver 仍然是正确工具;但如果你要判断”这个元素的 CSS 状态是不是隐藏了”,checkVisibility() 就是那个零代价的答案。

这个 API 2024 年 3 月就 Baseline Widely Available 了,已经稳定两年多,但很多团队还在用老办法递归查样式。下次遇到要判断元素显隐的场景,先试试这一行。

评论区

0 条评论

登录后可评论。