前言
2022
年是 CSS
最伟大的年份之一,本文提供此次更新的介绍和简要概述,针对的是更新的广度而非深度,如果你对其中某个功能感兴趣,请查看对应功能末尾的资源链接。
下面是本次更新的一些重要主题:
浏览器兼容性
Compat 2021
2021
年,开发人员进行了兼容性调查,此次更新旨在稳定当前功能、改进测试套件,并改善浏览器的下面五个功能:
sticky
定位aspect-ratio
尺寸flex
布局grid
布局transform
定位和动画
Interop 2022
2022
年,浏览器厂商决定为开发人员提供了以下 Web
功能:
- 级联层
@layer
- 颜色空间和方法
- 容器查询
<dialog>
- 表单兼容性
- 滚动
- 子网格
subgrid
- 排版
- 视口单位
Web
兼容
2022年的新功能
级联层(layer
)
由于后加载样式可能会覆盖先加载样式,因此我们需要精心设计样式表的加载顺序。
使用 @layer
后,在入口文件处可以预定义图层及其加载顺序,然后当样式加载、加载完成或者定义时,它们可以放置在一个层中,允许保留样式覆盖的重要性,但无需精心管理加载顺序。
上图展示了级联层如何允许更自由、更开放地编写和加载过程,但仍然根据需要维护层叠顺序。
Chrome DevTools
可以可视化哪些样式分别来自哪些层:
更多参考
- CSS Cascade 5 specification
- Cascade layers explainer
- Cascade layers on MDN
- Post by Una Kravets, Cascade Layers
- Post by Ahmad Shadeed: Hello, CSS Cascade Layers
子网络(subgrid
)
在 subgrid
之前,其他网络的网格无法与其父单元格或网格线对齐。每个网格布局都是独一无二的,因此在 CSS
中是无法实现子网格的对齐的,但是此功能是许多设计师必须的。
现在我们可以使用 subgrid
,网格的子级可以采用其父级的列或行作为自己的列,并将自己或子级与它们对齐。
下面的演示中,body 元素创建了一个三列网络: 中间列为 main ,左右列称为 fullbleed。body
中的 <nav>
和 <main>
元素通过设置 grid-template-columns: subgrid
来采用 body
中的命名行。
body {
display: grid;
grid-template-columns:
[fullbleed-start]
auto [main-start] min(90%, 60ch) [main-end] auto
[fullbleed-end]
;
}
body > * {
display: grid;
grid-template-columns: subgrid;
}
<nav>
或 <main>
的子级可以使用 fullbleed
和main
列和行对齐或调整自己的大小。
.main-content {
grid-column: main;
}
.fullbleed {
grid-column: fullbleed;
}
Firefox Devtools
提供了查看线条和子网络的功能。在下图中,父网格和子网格已重叠。
Devtools
元素面板中,你可以看到 grid
和 subgrid
分别是哪些元素,这非常有利于调试和验证布局。
更多参考
- Spec: www.w3.org/TR/css-grid…
- MDN: developer.mozilla.org/docs/Web/CS…
- Post by Bramus: Practical CSS Subgrid Video Tutorials
容器查询(Container queries
)
没有 @container
之前,网页的元素只能响应视口的大小,这非常有利用宏观布局,但相对于外部容器的微布局,无法进行相应调整。
使用 @container
,元素可以响应父容器的大小或者样式。但需要注意,需要将容器声明为可能的查询目标。
/* 新建容器 */
.day {
container-type: inline-size;
container-name: calendar-day;
}
上面的样式可以使下图中的 Mon、Tues、Wed、Thurs
和 Fri
列能够被事件元素查询。
下面的 CSS
用于查询 calendar-day
容器大小,然后调整布局和字体大小:
@container calendar-day (max-width: 200px) {
.date {
display: block;
}
.date-num {
font-size: 2.5rem;
display: block;
}
}
下面是另一个案例: book 组件会根据其拖动到的列中的可用空间进行调整:
更多参考
- Spec: https:/www.w3.org/TR/css-contain-3/#container-queries
- Explainer: css.oddbird.net/rwd/query/e…
- MDN: developer.mozilla.org/docs/Web/CS…
- The new responsive: /new-responsive/#responsive-to-the-container
- Calendar demo by Una: codepen.io/una/pen/Rwo…
- Awesome container queries: github.com/sturobson/A…
- Designcember: - How we built Designcember
- Post by Ahmad Shadeed: Say Hello To CSS Container Queries
accent-color
以前版本中,如果你想实现一个与主题颜色匹配的表单,可能需要使用复杂的库或者 CSS 解决方案,随着时间推移,这些解决方案会越来越难以管理。即使他们提供了很多选项和可定制性,但选择使用内置组件或者采用自己的组件会变得越来越乏味,无法继续扩展。
使用 accent-color
之后,一行 CSS 可以实现内置组件的主题颜色,除了色调之外,浏览器还会智能地为组件的辅助部分选择适当的对比色,并适应系统配色方案(亮暗)。
/* 为所有颜色着色 */
:root {
accent-color: hotpink;
}
/* 为一个元素着色 */
progress {
accent-color: indigo;
}
更多参考
- Spec: www.w3.org/TR/css-ui-4…
- MDN: developer.mozilla.org/docs/Web/CS…
- web.dev: /accent-color/
- Post by Bramus: Tint User-Interface Controls with CSS accent-color
Color level 4 and 5
过去的几十年里,sRGB
主导网络中的颜色世界,但随着高清显示器和预先配备 OLED
或 QLED
屏幕的移动设备的不断发展,sRBG
已经远远不够了。此外,为了更好的使用用户偏好的动态效果,颜色管理越来越成为设计师、设计系统和代码维护人员日益关注的问题。
2022
年,CSS
添加了许多新的颜色函数和空间
- 达到显示器高清色彩功能的色彩。
- 与意图相匹配的色彩空间,例如感知一致性。
- 渐变的颜色空间会显著改变插值结果。
- 颜色功能可帮助你混合和对比,并选择在哪个空间进行工作。
没有这些颜色特性之前,需要 JavaScript
或者预处理器需要完成很多繁重的工作来实现各种对比色。
使用 CSS 2022
提供的新颜色特性,CSS
可以进行编排和计算,动态且及时的完成颜色相关工作,且 CSS
还支持向前检查和优雅回退。
@media (dynamic-range: high) {
.neon-pink {
--neon-glow: color(display-p3 1 0 1);
}
}
@supports (color: lab(0% 0 0)) {
.neon-pink {
--neon-glow: lab(150% 160 0);
}
}
hwb()
hwb
代表色相、白度和黑度。通过一种色调和一定量的白色和黑色来变亮和变暗,因此这种颜色对人类比较友好。
:root {
--hwb-swatch-1: hwb(200 75% 0%);
--hwb-swatch-2: hwb(200 50% 25%);
--hwb-swatch-3: hwb(200 25% 50%);
--hwb-swatch-4: hwb(200 0% 75%);
--hwb-swatch-5: hwb(200 0% 90%);
}
.swatch:nth-of-type(1) {
background: var(--hwb-swatch-1);
}
.swatch:nth-of-type(2) {
background: var(--hwb-swatch-2);
}
.swatch:nth-of-type(3) {
background: var(--hwb-swatch-3);
}
.swatch:nth-of-type(4) {
background: var(--hwb-swatch-4);
}
.swatch:nth-of-type(5) {
background: var(--hwb-swatch-5);
}
* {
box-sizing: border-box;
margin: 0;
}
html {
block-size: 100%;
}
body {
min-block-size: 100%;
font-family: system-ui, sans-serif;
display: grid;
}
效果图:
使用此颜色函数可以产生 sRGB
颜色空间的颜色,但并没有带来新的色彩。
更多参考
- Spec: www.w3.org/TR/css-colo…
- MDN: developer.mozilla.org/docs/Web/CS…
- Post by Stefan Judis: hwb() – a color notation for humans?
颜色空间
颜色的表示是基于颜色空间实现的。每个颜色空间都为颜色使用提供了丰富的功能。
CSS 2022
将提供 10
个全新的颜色空间,每个颜色空间都为开发者、设计师提供了独一无二的功能来进行颜色的混合、显示、挑选等。
color-mix()
以前版本中,开发人员和设计人员需要使用 Sass
等预处理器来混合颜色,而且大多数颜色混合功能并没有制定在那个颜色空间进行混合,这可能会造成结果混乱。
使用 color-mix()
后,开发人员和设计人员可以在浏览器中进行颜色混合,并且无需运行构建过程或者 JavaScript 脚本。此外,还可以指定混合的颜色空间。
通常,主题颜色被用作基础颜色,并从中创建变体,例如悬停样式的浅色或深色。下面是color-mix()
例子:
.color-mix-example {
--brand: #0af;
--darker: color-mix(var(--brand) 25%, black);
--lighter: color-mix(var(--brand) 25%, white);
}
如果你想在不同的颜色空间中进行混合,例如 sRGB,请更改他:
更多参考
- Spec: www.w3.org/TR/css-colo…
- MDN: developer.mozilla.org/docs/Web/CS…
- Theming demo: codepen.io/argyleink/p…
- Another theming demo: codepen.io/argyleink/p…
- Post by Fabio Giolito: Create a color theme with these upcoming CSS features
color-contrast()
以前版本中,样式表编写者需要在调色板颜色样本上显示黑色或白色文本,以向颜色系统的用户指示需要哪种文本颜色才能与该样本进行适当对比。
使用 color-contrast()
,可以使用浏览器自动选择黑色或者白的,还可以为设计系统提供适用的颜色列表,并让其选择第一个通过所需对比度的颜色。下面是 HWB 调色板演示的屏幕截图,其中文本颜色有浏览器根据颜色自动选择
语法使用如下: 函数的参数为灰色,浏览器确定黑色或者白色是否具有最大对比度。``
color: color-contrast(gray);
还可以使用颜色列表进行自定义,函数会从中选择对比度最高的颜色:
color: color-contrast(gray vs indigo, rebeccapurple, hotpink);
如果不需要从列表中选择对比度最高的颜色,可以提供目标对比度,选择第一种达到该对比度的颜色:
color: color-contrast(
var(--bg-blue-1)
vs
var(--text-lightest), var(--text-light), var(--text-subdued)
to AA /* 4.5 could also be passed */
);
更多参考
相对颜色语法
以前版本中,计算颜色或者调整颜色需要将颜色通道单独胡设置到自定义属性中,通常使用 HSL
来作为颜色的主要处理函数,因为色调、饱和度和亮度都可以通过 calc
函数进行调整。
使用相对颜色语法后,任何空间内的任何颜色都可以解构、修改并作为颜色返回。
例如下面的语法示例中,提供了一个基本的十六进制颜色,并相对于该颜色创建了来个那种新颜色。第一种颜色 --absolute-change
在 LCH
中从基色创建新颜色,然后将基色的亮度替换为 75%
,保持色度 (c) 和色相 (h)。 第二种颜色 --relative-change
在 LCH
中从基色创建新颜色,但这一次将色度 (c) 降低了 20%
.relative-color-syntax {
--color: #0af;
--absolute-change: lch(from var(--color) 75% c h);
--relative-change: lch(from var(--color) l calc(c-20%) h);
}
基于相对颜色语法,你可以基于一种颜色创建另一种颜色,可以访问某种颜色的三个通道值,并且可以修改这些值。
在下面的例子中,使用了相对颜色语法来创建基色更亮和更暗的变体,并使用 color-contrast()
来确保标签具有适当的对比度。
此函数也可以用于调色板的生成。
:root {
--_color-base: #339af0;
--color-0: lch(from var(--_color-base) 98% 10 h);
--color-1: lch(from var(--_color-base) 93% 20 h);
--color-2: lch(from var(--_color-base) 85% 40 h);
--color-3: lch(from var(--_color-base) 75% 46 h);
--color-4: lch(from var(--_color-base) 66% 51 h);
--color-5: lch(from var(--_color-base) 61% 52 h);
--color-6: lch(from var(--_color-base) 55% 57 h);
--color-7: lch(from var(--_color-base) 49% 58 h);
--color-8: lch(from var(--_color-base) 43% 55 h);
--color-9: lch(from var(--_color-base) 39% 52 h);
--color-10: lch(from var(--_color-base) 32% 48 h);
--color-11: lch(from var(--_color-base) 25% 45 h);
--color-12: lch(from var(--_color-base) 17% 40 h);
--color-13: lch(from var(--_color-base) 10% 30 h);
--color-14: lch(from var(--_color-base) 5% 20 h);
--color-15: lch(from var(--_color-base) 1% 5 h);
}
更多参考
- Spec: www.w3.org/TR/css-colo…
- Palettes: codepen.io/web-dot-dev…
- Variants: codepen.io/web-dot-dev…
渐变颜色空间
sRGB
颜色空间非常可靠,但是其处理灰色死区非常难。
使用渐变颜色空间后,可以告知浏览器使用何种颜色空间进行插值,开发人员和设计人员可以选择他们喜欢的渐变颜色。
语法添加在渐变方向之后,使用新的in
语法,并且是可选的:
background-image: linear-gradient(
to right in hsl,
black, white
);
background-image: linear-gradient(
to right in lch,
black, white
);
下面是各个颜色空间中黑色到白色的渐变规则,可以看到有些更早达到深黑色,有些更晚达到白色。
下面是黑色转换为蓝色的案例,这是个已知的渐变问题,大多数颜色空间在插值过程中逐渐会变为紫色。
okLCH
并且okLAB
是专门的色彩空间,可以解释各种变化,比如紫色,这使得它们对于渐变特别准确。
更多参考
- Spec: drafts.csswg.org/css-images-…
- Codepen comparing gradients: codepen.io/argyleink/p…
- Observable notebook: observablehq.com/@argyleink/…
inert
前端开发中,我们经常使用焦点捕获,将用户的注意力引导到交互空间中,如果焦点离开交互空间,则强制进行返回。例如使用键盘或者屏幕阅读器的用户,当焦点离开交互空间时,需要将其引导回交互空间,来继续完成后续操作。
使用 inert
,你可以冻结或者保护应用程序的整个页面或者部分页面。当文档的这些部分处于惰性状态时,单击和焦点更改尝试根本不可用。
可以把 inert 理解成守卫,守卫指定的部分。
JavaScript alert()
函数就是一个特别好的案例。调用 alert
之前,页面可以通过鼠标和和键盘进行访问,但当 alert
警示框弹出后,页面的其他部分将被冻结,用户的注意力会集中在警示框中。用户完成交互后,页面可以再次进行操作。
下面案例展示了上述的工作机理:
<body>
<div class="modal">
<h2>Modal Title</h2>
<p>...<p>
<button>Save</button>
<button>Discard</button>
</div>
<main inert>
<!-- cannot be keyboard focused or clicked -->
</main>
</body>
inert
有助于提高诸如滑出式侧边菜单的用户体验,当用户滑出侧边栏菜单时,鼠标和键盘不应该与后面的页面进行交互,因此可将页面处理 inert
状态,只有用户关闭侧边栏菜单后,才可继续交互。
更多参考
- Spec: html.spec.whatwg.org/multipage/i…
- MDN: developer.mozilla.org/docs/Web/AP…
- Chrome Developers: Introducing inert
COLRv1 字体
Web
提供了 OT-SVG
字体,这是一种开放字体格式,可以用于渐变字体、内置颜色和效果。但是这种字体非常大,并且定制的自由度很小。
CSS 2022
提供了 COLRv1
字体,这种字体具有更小的占用空间,支持矢量可缩放、可重新定位、渐变功能和混合模式驱动,同时可以接受参数来自定义每个用例的字体或匹配主题。
下面是 Chrome Developer
博客文章中有关表情符号的示例,如果你放大表情符号的大小,你会发现,符号不在清晰,但如果使用 COLRv1
字体,表情符号既是矢量的又可以保持清晰。
COLRv1
字体加载与其他字体一样:
@import url(https://fonts.googleapis.com/css2?family=Bungee+Spice);
使用 @font-palette-values
来自定义 COLRv1
字体,这是一个特殊的 CSS
规则,用于将一组自定义选项分组和命名为一个包以供以后参考。 指定自定义名称就像自定义属性一样,以 --
开头:
@import url(https://fonts.googleapis.com/css2?family=Bungee+Spice);
@font-palette-values --colorized {
font-family: "Bungee Spice";
base-palette: 0;
override-colors: 0 hotpink, 1 cyan, 2 white;
}
使用 --colorized
作为自定义的别名,然后将调色板应用于使用颜色字体系列的元素。
@import url(https://fonts.googleapis.com/css2?family=Bungee+Spice);
@font-palette-values --colorized {
font-family: "Bungee Spice";
base-palette: 0;
override-colors: 0 hotpink, 1 cyan, 2 white;
}
.spicy {
font-family: "Bungee Spice";
font-palette: --colorized;
}
更多参考
- Github: github.com/googlefonts…
- Chrome Developers: developer.chrome.com/blog/colrv1…
- BlinkOn developer explainer video: www.youtube.com/watch?v=Bmq…
视口单位
为帮助适应视口,Web
中提供了一些物理单位,例如高度、宽度、最小尺寸(vmin)和最大尺寸(vmax)。
但这些给移动端带来了麻烦,移动设备加载页面时,会显示 url
状态栏,状态栏会占据部分视口空间。为了用户更好的视口体验,状态栏几秒后会隐藏。随着状态栏的显示和隐藏,视口的高度会发生变化,这特别影响 vh
单位值的确定。(目前已经将 vh 定义为最大的视口高度)
.original-viewport-units {
height: 100vh;
width: 100vw;
--size: 100vmin;
--size: 100vmax;
}
CSS 2022
提供了小型、大型和动态视口单位,该设计理念是让开发人员和设计人员能够选择他们想要在给定场景中使用的单位。
下面时 CSS 2022
提供的所有视口单位列表:
高度视口单位
.new-height-viewport-units {
height: 100vh;
height: 100dvh;
height: 100svh;
height: 100lvh;
block-size: 100vb;
block-size: 100dvb;
block-size: 100svb;
block-size: 100lvb;
}
宽度视口单位
.new-width-viewport-units {
width: 100vw;
width: 100dvw;
width: 100svw;
width: 100lvw;
inline-size: 100vi;
inline-size: 100dvi;
inline-size: 100svi;
inline-size: 100lvi;
}
最小视口单位
.new-min-viewport-units {
--size: 100vmin;
--size: 100dvmin;
--size: 100svmin;
--size: 100lvmin;
}
最大视口单位
.new-max-viewport-units {
--size: 100vmax;
--size: 100dvmax;
--size: 100svmax;
--size: 100lvmax;
}
更多参考
:has()
使用 :has()
后,你可以保留样式树中较高的元素,同时还支持子项查询,例如 ul:has(> li)
,就是获取拥有 li
子元素的 ul
元素。
下面是基本用法,其中 .parent
类是主体,当子元素具有 .child
类时主体被选中
.parent:has(.child) {...}
利用 :has()
可以实现很多有用的功能,例如包装图像的 <a>
标签不好修改其样式,可以借助 :has()
实现
a:has(> img) {...}
更多参考
- Spec: www.w3.org/TR/selector…
- MDN: developer.mozilla.org/docs/Web/CS…
- The CSS
:has()
selector is way more than a "parent selector": www.bram.us/2021/12/21/…
2022年及以后的功能
CSS 2022
增加了很多功能,但是仍有很多事情目前暂未实现,下面来介绍一些待解决的问题或者正在积极开发的解决方案。
松散类型的自定义属性
CSS
自定义属性非常强大,可以把各种值存储在变量中,然后对变量进行扩展、计算、共享等。但这样并不好,应该要有一些限制。
例如下面的场景,长方体阴影使用自定义属性作为它的值:
box-shadow: var(--x) var(--y) var(--blur) var(--spread) var(--color);
上述 css
样式是可以正常运行的,但是如果其中的属性接受了不符合 CSS box-shadow
语法的属性值,例如 --x: red
,那么阴影将无法渲染出来。
这时候我们就需要为 --x
添加类型化配置,@property
就是为此而生的。
@property --x {
syntax: '<length>';
initial-value: 0px;
inherits: false;
}
设置完 @property
后,--x
接收非 <length>
值,将会被忽略。
除了类型安全外,@property
还为动画提供了很多可能。例如使用径向渐变来制作覆盖的一部分,从而创建聚光灯聚焦效果。按下 alt/opt
键时,JavaScript 设置鼠标 x
和 y
,然后将焦点大小更改为较小的值,例如 25%
,在鼠标位置创建聚光灯焦点圆。
.focus-effect {
--focal-size: 100%;
--mouse-x: center;
--mouse-y: center;
mask-image: radial-gradient(
circle at var(--mouse-x) var(--mouse-y),
transparent 0%,
transparent var(--focal-size),
black 0%
);
}
渐变无法设置动画,因为浏览器无法理解当前渐变的意图,但如果使用@property
,可以单独设置一个属性并为其设置动画,浏览器可以轻松理解其意图。
附带聚焦效果的电子游戏始终会为圆设置动画,从一个大圆到一个针孔圆。下面是将演示@property
如何配合渐变使用:
@property --focal-size {
syntax: '<length-percentage>';
initial-value: 100%;
inherits: false;
}
.focus-effect {
--focal-size: 100%;
--mouse-x: center;
--mouse-y: center;
mask-image: radial-gradient(
circle at var(--mouse-x) var(--mouse-y),
transparent 0%,
transparent var(--focal-size),
black 0%
);
transition: --focal-size .3s ease;
}
更多参考
- Spec: www.w3.org/TR/css-prop…
- MDN: developer.mozilla.org/docs/Web/CS…
- web.dev: web.dev/at-property…
- Zoom demo: codepen.io/argyleink/p…
- CSS Tricks: css-tricks.com/exploring-p…
媒体查询
目前,我们通常使用 min-width
和 max-width
来进行媒介查询:
@media (min-width: 320px) {
…
}
或者使用 min-width
和 max-width
共同查询
@media (min-width: 320px) and (max-width: 1280px) {
…
}
但如果支持媒介查询范围,上述代码可能会修改为:
@media (320px >= width) {
…
}
@media (320px <= width <= 1280px) {
…
}
更多参考
- Spec: www.w3.org/TR/mediaque…
- MDN: developer.mozilla.org/docs/Web/CS…
- PostCSS plugin: github.com/postcss/pos…
自定义媒体查询
使用 @custom-media
之后,CSS
允许对媒体查询进行定义别名和引用,就像自定义属性一样。
@custom-media --OSdark (prefers-color-scheme: dark);
@custom-media --OSlight (prefers-color-scheme: light);
@custom-media --pointer (hover) and (pointer: coarse);
@custom-media --mouse (hover) and (pointer: fine);
@custom-media --xxs-and-above (width >= 240px);
@custom-media --xxs-and-below (width <= 240px);
然后在对应位置进行使用即可:
@media (--OSdark) {
:root {
…
}
}
更多参考
- Spec: www.w3.org/TR/mediaque…
- PostCSS plugin: github.com/postcss/pos…
嵌套选择器
目前如果想实现嵌套选择器,我们需要借助类似 Sass
的预处理语言,提供 @nest
后,将支持嵌套选择器功能。
article {
color: darkgray;
}
article > a {
color: var(--link-color);
}
/* with @nest becomes */
article {
color: darkgray;
& > a {
color: var(--link-color);
}
}
@nest
能帮助 CSS
代码组织更明确,提高可读性和方便性,这将是一个非常厉害的更新。
更多参考
- Spec: www.w3.org/TR/css-nest…
- PostCSS plugin: github.com/csstools/po…
- Post by Bramus: The future of CSS: Nesting Selectors
样式范围
CSS
中的样式默认是级联、继承和全局的,这种特性在很多情况下很便捷,但对于复杂的站点或者应用程序,可能会存在许多样式不同的组件,级联和全局继承可能会使样式造成泄露。
使用 @scope
,可以将样式限定在一个上下文中,这里面的样式不会级联或者继承。
以下案例中,BEM 选择器试图将 header
元素的颜色范围限定为具有命名约定的 .card
容器。 使用 @scope
,无需命名约定即可在不标记 header
元素的情况下完成上述功能:
.card__header {
color: var(--text);
}
/* with @scope becomes */
@scope (.card) {
header {
color: var(--text);
}
}
@scope
还允许设置样式范围的结束位置。但这并不能通过任何命名约定或预处理器来完成,只有浏览器内置的 CSS 才能做到。 在以下示例中,当 .media-block
的子项是 .content
的兄弟或父项时,将专门应用 img
和 .content
样式:
@scope (.media-block) to (.content) {
img {
border-radius: 50%;
}
.content {
padding: 1em;
}
}
更多参考
- Spec: www.w3.org/TR/css-scop…
- Explainer: css.oddbird.net/scope/expla…
瀑布流布局
目前我们通常使用 JavaScript
来实现瀑布流布局,但如果使用 Grid
构建 CSS
后,将不需要 JavaScript
。
上面案例的代码如下:
.container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: masonry;
}
更多参考
- Spec: drafts.csswg.org/css-grid-3/…
- MDN: developer.mozilla.org/docs/Web/CS…
- Smashing Magazine: www.smashingmagazine.com/native-css-…
CSS 可保存数据
使用 prefers-reduced-data
媒体查询,CSS 可以加入用户体验增强,并在保存数据方面发挥作用。
@media (prefers-reduced-data: reduce) {
picture, video {
display: none;
}
}
上面的媒体滚动组件使用了前面的 CSS ,可以节省很多资源。当用户与媒体滚动条交互时,继续保存。这些图像上都附有 load="lazy"
属性,再加上 CSS 完全隐藏元素,这意味着永远不会对图像发出网络请求。
经过测试,在一个中等大小的视口上,最初加载了 40 个请求和 700kb 的资源,当用户滚动媒体选择组件时,会不断进行加载。使用 CSS prefers-reduced-data
媒体查询,加载了 10 个请求和 172kb 的资源。
使用 prefers-reduced-data
媒体查询不仅仅是节省数据,并且不会有分散注意力的封面图片来吸引注意力。许多用户使用付费的流量,这可以大大降低他们的流量费用。
滚动快照
在没有滚动快照提案以前,我们需要编写自己的 JavaScript 来实现轮播、滑块或者图库,实现起来相对复杂,如果实现的效果不好,用户交互起来会感觉很笨拙。
snapChanging()
当浏览器浏览器释放了一个 snap child
,该事件便会触发。这允许用户界面反映缺少快照子项和滚动条的不确定快照状态,因为它现在正在使用,并将在新的地方落地。
document.querySelector('.snap-carousel').addEventListener('snapchanging', event => {
console.log('Snap is changing', event.snappedTargetsList);
});
snapChanged()
当浏览器捕获到新的子对象,并且滚动条停止,该事件触发。
document.querySelector('.snap-carousel').addEventListener('snapchanged', event => {
console.log('Snap changed', event.snappedTargetsList);
});
scroll-start
思考一下可滑动组件,其中向左或向右滑动会触发不同的事件,或者页面加载时的搜索栏最初是隐藏的,直到滚动到顶部。这个 CSS 属性允许开发者指定一个滚动条应该从一个特定的点开始。
:root { --nav-height: 100px }
.snap-scroll-y {
scroll-start-y: var(--nav-height);
}
:snap-target
当前 CSS
选择器将匹配滚动捕捉容器中当前被浏览器捕捉的元素。
.card {
--shadow-distance: 5px;
box-shadow: 0 var(--shadow-distance) 5px hsl(0 0% 0% / 25%);
transition: box-shadow 350ms ease;
}
.card:snapped {
--shadow-distance: 30px;
}
基于这些滚动快照的提案,制作滑块、轮播图要容易多。但这些 CSS 和 JavaScript 功能还处于早期阶段。
更多参考
- Draft spec: drafts.csswg.org/css-scroll-…
- Explainers: github.com/argyleink/S…
- Snap demos: snap-gallery.netlify.app/
CSS 状态管理
以前版本中,只有浏览器内置的状态才能用于样式交互。 例如,复选框输入具有 :checked
,这是一种内置的浏览器状态,用于 CSS 能够用于视觉更改元素的输入
使用 toggle()
之后,可以在任何元素上创建自定义状态,以便 CSS 更改和用于样式。 它允许循环、定向切换等。
下面案例取自 <selectmenu>
解释器页面,创建了一个带有一些基本选项的新选择菜单
<selectmenu>
<option>Option 1</option>
<option>Option 2</option>
<option>Option 3</option>
</selectmenu>
CSS 样式
.my-select-menu::part(button) {
color: white;
background-color: red;
padding: 5px;
border-radius: 5px;
}
.my-select-menu::part(listbox) {
padding: 10px;
margin-top: 5px;
border: 1px solid red;
border-radius: 5px;
}
更多参考
anchor 定位
以前版本可以通过绝对定位和相对定位,可以定位子元素在父元素中的位置。
使用 anchor
后,可以将元素定位到其他元素上,无论是否为子元素。它还允许开发人员指定定位的边缘,以及创建元素之间位置关系的其他细节。