Skip to content

浏览器支持 ​

这套组件不靠 JS 补丁解决样式和浮层问题,而是直接用了浏览器自带的现代能力。好处是代码小、无障碍好、没有额外依赖;代价是有一条底线:太老的浏览器上会掉东西。

先把底线说清楚:

浏览器最低版本
Chrome、Edge123
Safari(含 iOS)17.5
Firefox120

这个底线是 light-dark() 定的,因为几乎每个颜色变量都写成 light-dark(浅色, 深色)。比它老的浏览器看不懂这个函数,会把整条声明丢掉,页面就只剩黑白和无色状态。

我们实际用到的特性 ​

下面每一条都在 packages/core/styles 里真实出现过,不是照抄原版清单。

特性用在哪ChromeSafariFirefox
light-dark()所有主题颜色变量12317.5120
@layer 分层每份样式表的第一行,声明 astryx.* 五层顺序9915.497
:has()表单状态、列表、聊天、Tab 的父子联动样式10515.4121
color-mix()计算悬停底色、滑杆、代码块等的过渡色11116.2113
@property注册按压动画用的自定义属性,让它能做数字动画8516.4128
Popover API下拉菜单、提示、命令面板、Toast 视口:用原生 popover 和 popovertarget11417125
<dialog> + showModal()对话框、底部抽屉、大图查看3715.498
@starting-style浮层、抽屉、Toast 的入场动画起点11717.5129
容器查询 @container分页、步骤条、聊天的窄宽自适应10516110
text-wrap: balance / pretty标题平衡换行、正文避免孤字11417.5121
:dir()滑杆等少数地方的方向判断12016.449
逻辑属性内外边距、圆角、定位大量用 padding-inline-start 这类写法8714.166

@property 和 @starting-style 属于「没有也不崩」:缺了它们,按压动画和入场动画直接不播,界面照常能用。真正决定底线的是 light-dark()。

版本号按 MDN 和 caniuse 的记录写成,写这份文档时的数据;拿不准就去 caniuse 搜一下特性名。

低于底线会怎样 ​

  • 颜色全丢。 light-dark() 认不出来,--astryx-color-* 拿不到值,文字可能变成默认的黑色。
  • 浮层还在,但可能不贴着触发器。 原生 popover 不支持时,菜单和提示还能打开,位置靠 CSS 兜底,不会那么准。
  • 对话框可能打不开。 <dialog> 的 showModal() 没有时,对话框组件没有降级路径。
  • 动画不播。 入场、按压这类动效消失,内容照样显示。

没有一条会让页面白屏。但视觉按预期走不了,所以老浏览器不算支持。

想支持更老的浏览器怎么办 ​

我们没有提供老浏览器专用的回退包,也没有内置 polyfill。可行的做法有三种。

1. 用户群很老,就守住底线。 内部工具通常能推浏览器升级,这是最省事的路径。

2. 用 @supports 探测,自己补一份颜色。 可以在应用入口检查 light-dark() 在不在,不在就给变量写死浅色值:

css
@supports not (color: light-dark(#fff, #000)) {
  :root {
    --astryx-color-text-primary: #000000;
    --astryx-color-background-surface: #ffffff;
  }
}

这只补回颜色,浮层定位和动画不会因此变好。

3. 需要老浏览器上也完整可用,就得自己改。 包括引入 popover 和 @starting-style 的降级写法,或者在项目里重写相关组件的浮层实现。这类改造不在组件库的范围内。

我们已经替你处理的兼容细节 ​

  • iOS 输入框自动放大。 iOS 上输入框字号小于 16px 时,聚焦会自动放大页面。所有输入类组件在触摸设备上都把字号顶到至少 1rem,靠 @supports (-webkit-touch-callout: none) 只在 iOS 上生效。
  • 减少动效。 全局有一条 prefers-reduced-motion: reduce 规则,把入场和退场的位移、缩放、透明度变化压成「没有」,各组件也有自己的关闭规则。系统开了「减弱动态效果」,动画就不播。
  • 滚动条。 滚动条样式集中在 scrollbars.css,靠 overlayscrollbars 这个运行时依赖实现,配色用 color-mix() 从文字色混出来,所以深色模式也能跟着走。

自己验一遍 ​

在浏览器控制台里粘这段,能查到你手上这台浏览器缺哪几项:

js
const checks = {
  'light-dark()': CSS.supports('color', 'light-dark(#fff, #000)'),
  '@layer': CSS.supports('at-rule', '@layer a, b;'),
  ':has()': CSS.supports('selector(:has(*))'),
  'color-mix()': CSS.supports('color', 'color-mix(in oklab, red, blue)'),
  'Popover API': typeof HTMLElement.prototype.showPopover === 'function',
  '@container': CSS.supports('container-type', 'inline-size'),
}
console.table(checks)

有一项是 false,就对照上面的表格看这一项影响什么。light-dark() 是 false 时,页面颜色基本不可用。