by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=12450
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。
一、一步到位
今天介绍一个特殊的@supports检测函数,那就是named-feature(),目前就下面两个经典用法:
/* 检测:锚点定位是否感知 transform(transform后锚点位置跟着变) */ @supports named-feature(anchor-position-follows-transforms) { /* 支持该行为时,启用高级锚点布局 */ .tooltip { position: anchor(--btn); } } /* 检测单轴滚动容器能力 */ @supports named-feature(single-axis-scroll-container) { .scroll-x { overflow-x: auto; overflow-y: clip; } } 有别于之前的(property: value)属性检测、selector(:has())选择器检测、at-rule(@container) AT规则检测。
这里的named-feature()检测的函数参数是CSS规范里显式登记的特殊名字。
二、为何需要?
先说anchor-position-follows-transforms。
锚点定位 anchor() 有一个大坑,那就是部分旧版实现,元素做 transform 之后,锚点是坐标不会跟着更新的。
锚点定位是非常强悍的CSS特性,很好用,好用的不得了,有兴趣可以访问我之前的文章:全新的CSS Anchor Positioning锚点定位API
如果使用传统语法检测,比方说@supports (position: anchor()),结果只能检测浏览器认识 anchor 语法与否,并不能检测transform定位bug浏览器是否修复。
所以,就必须用 named-feature(anchor-position-follows-transforms) 判断行为是否符合预期,以此区分两套实现逻辑,避免 UI 错位。
那single-axis-scroll-container呢?
说起单轴滚动,就不得不提我上个月写的这篇文章:一个视频彻底看懂CSS scroll-axis-lock none的作用
虽然都是轴滚动相关的特性,但这里的检测背景和作用与之还有所不同,这个值得展开说说。
三、单轴溢出的问题
比方说设置一个表格可以水平和垂直滚动,结构如下:
<div class="table-wrapper" style="overflow-x: auto;"> <table> … </table> </div>
然后希望表头和第一列粘性定位:
.table-wrapper thead { position: sticky; top: 0; } /* 第一列也粘性定位*/ .table-wrapper td:first-child { position: sticky; left: 0; } 结果怎么着,水平滚动是有粘性定位效果的,但是垂直滚动就没有。
为何?
这是一个“次轴无法被彻底裁剪”历史遗留问题。
长期以来,CSS overflow 的组合存在限制。
如果你设置了 overflow-x: auto,哪怕将 overflow-y 显式设为 clip 或 hidden,浏览器在底层计算滚动上下文时,仍然会将该容器视为两个轴向都能滚动的容器(或者说,计算逻辑仍会将其视为 overflow-y 产生了滚动边界)。
插播一下,如果不知道overflow:clip的作用,可以看我很多年前写的这篇文章:CSS overflow-clip-margin属性简介
于是乎,大表格的粘性定位就成了受害者。
浏览器会误认为该外层容器在 Y 轴也是滚动容器,从而导致表头被困在外层容器中,无法跟随页面垂直滚动条实现粘性固定(这句话不理解也没关系,AI时代了,细节原理不重要了)。
效果见下面录屏示意(不动点击播放),左侧是有问题的,右侧是目标效果,左侧可以看到本该粘性定位的表格头直接被滚走了。
停顿了片刻……
算了,还是有不少好学的小伙伴的,上面这句话再通俗解释下吧。
就是我特么的只设置了水平滚动,垂直方向我压根没有任何滚动,你不能傻乎乎的看到我是个滚动容器,就不让我垂直方向的表头无法粘性定位吧!
PS:粘性定位的启动点计算是根据第一个滚动容器来的,详见此文:深入理解position sticky粘性定位的计算规则
为了解决该问题,CSS 规范进行了修订,允许 overflow-x: auto 与 overflow-y: clip(或通过简写 overflow: auto clip)配对时,容器仅充当单轴(X轴)滚动容器。
此时,Y 轴的 position: sticky 就可以绕过该容器,正确地去跟踪文档(页面)的垂直滚动条。
根据我从chrome开发者官方页面看到的数据,貌似是Chrome 154开始支持的。
而为了检测浏览器是否开始了单轴滚动的支持,就需要用到这里的named-feature(single-axis-scroll-container)检测。
为什么不能直接用 @supports (overflow: auto clip)?
- 如果仅用
@supports (overflow: auto clip),浏览器只会检查自己能不能解析这个语法。 - 很多旧版本浏览器虽然能解析这个语法,但其底层的滚动上下文计算机制仍然是旧的,并不会正确处理修订后的单轴滚动逻辑。
所以这里才需要@supports named-feature(single-axis-scroll-container)检测浏览器是否已经支持了overflow:clip与浏览器单轴滚动。
如果不支持,我们可以使用JS打个补丁,或使用其他策略修复。
演示页面
对了,演示页面差点忘记了,如果你的浏览器Chrome版本154及其以上,可以狠狠地点击这里:CSS单轴滚动容器的怪异行为以及修复demo
四、结语碎碎念
named-feature()特征检测其实没什么好讲的,因为太小众了,我估计全中国,99.9%的前端都没有机会在实际项目中使用此特性。
那为什么还专门写一篇文章呢?
主要是这两个特征检测背后的故事很有意思,值得念叨。
一般named-feature()特征检测都是检测浏览器之前有某某渲染问题,在之后的版本中修改了策略,或者修复了bug,然后针对这个现象,专门弄个白名单机制一个的特殊名称。
方便开发者更好地对新老特性做兼容。
很好的设计想法。
但是太小众,AI时代的前端开发者普遍没什么学习热情,怎么可能学这种东西,狗都不学。
接下来看下此特性的兼容性,看图:

哇,好新的特性啊。

得,更是没什么学习价值了。
😮💨😮💨😮💨
好,就说这多,我们下周再见!

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=12450
(本篇完)

