2023 年对 CSS 来说是重要的一年,在这一年中迎来了众多功能更新,从基础到展现,再到交互,让开发人员实现了曾经认为在 Web 开发中不可能实现的众多功能。container queries、subgrid、:has() 选择器、颜色函数等等已经被所有现代浏览器所支持。此外 Chrome 浏览器还可以使用 CSS 的滚动驱动动画,并能通过视图转换在网页视图之间流畅地显示动画。最重要的是,如 CSS 嵌套和 Scope 块级作用域等,也为开发人员带来了更好的开发体验。
主要特性如下:
这个是小懒最喜欢的一个功能更新,在 《现代CSS系列》 的很多文章示例使用的都是 CSS 原生嵌套语法。
原生 CSS 嵌套可以像 SASS、LESS 预处理器一样,将相关的选择器组合在一起,从而减少需要编写的规则数量,它可以节省打字时间,并使语法更易于阅读和维护。您可以将选择器嵌套到任意深度,但要小心不要超过两层或三层。嵌套深度没有技术限制,但它会使代码更难以阅读,并且生成的 CSS 可能会变得不必要的冗长。
代码示例:
.button { background-color: red; &.warning { background-color: blue; } & .icon { width: 1rem; height: 1rem; }}
兼容性:
需要注意的是,虽然原生 CSS 嵌套语法在过去几年中不断发展,使大多数 Web 开发人员感到满意,但不要指望所有 SCSS 代码都能像您期望的那样直接工作。
详细阅读:
现代CSS:原生 CSS 嵌套综合指南
Chrome 118 版本已经实现对 CSS @scope 的支持,以允许在样式表中对样式进行区块级作用域,进一步提高 BEM 的优势。这使样式更易于维护,同时提供对影响任何前端应用程序的 CSS 层叠的更严格的控制。
代码示例:
在此 HTML 中,我们可以使用以下方法对 .section-two 样式区域中的元素进行样式设置:
.container { max-width: 600px; margin: 0 auto; .section { display: flex; flex-direction: column; border: 1px solid #ccc; border-radius: 5px; margin-bottom: 10px; & h2 { font-size: 16px; line-height: 36px; text-align: center; background-color: #ccc; margin: 0; } & p { font-size: 24px; text-align: center; } }}@scope (.section-two) { p { color: #f00; }}
兼容性:
详细阅读:
现代CSS:使用 CSS @scope 替代 BEM
Chrome 111 版本新增了对三角函数 sin()、cos()、tan()、asin()、acos()、atan()和atan2()的支持,使所有主要引擎都能使用这些函数。这些函数在制作动画和布局时非常方便。
语法规则:
/* Single <angle> values */width: calc(100px * cos(45deg));width: calc(100px * cos(0.125turn));width: calc(100px * cos(0.785398163rad));/* Single <number> values */width: calc(100px * cos(63.673));width: calc(100px * cos(2 * 0.125));/* Other values */width: calc(100px * cos(pi));width: calc(100px * cos(e / 2));
兼容性:
:empty 伪类可以匹配任何没有子元素的元素。当前已经得到所有主流浏览器的支持。如果该元素是一个空元素,我们可以结合 display 属性使用来隐藏元素。
近 20 年来,开发人员一直要求在 CSS 中选择 "父选择器",直到 :has() 的出现,这一切都可以实现了。当 :has() 和 :not() 结合时,我们可以在很多复杂场景中应用,比如查找子元素有空元素的元素、隐藏一个不包含某个子元素的父元素等。
代码示例:
.box { display: flex; width: 80%; height: 80px; background-color: #ccc; border-radius: 5px; margin: 0 auto 10px; justify-content: center; align-items: center;}.box:not(span:has(:empty)) { display: none;}
兼容性:
详细阅读:
现代CSS:使用 :empty 和 :has() 隐藏空元素
通过容器查询,可以根据元素容器的大小对元素应用样式。例如,如果容器周围的可用空间较小,就可以隐藏某些元素或使用较小的字体。容器查询是媒体查询的一种替代方法,后者可根据视口大小或其他设备特性对元素应用样式。
代码示例:
article { padding: 1rem; font-size: 1rem;}@container (min-width: 60ch) { article { padding: 2rem; font-size: 1.25rem; }}
兼容性:
详细阅读:
现代CSS:网页暗黑模式实现完整指南
Chrome 118 版本新支持的功能。不透明的界面会让各种视力缺陷的人感到头痛或视觉疲劳。这就是为什么 Windows、macOS 和 iOS 的系统偏好设置可以降低或移除用户界面透明度的原因。此 prefers-reduced-transparency 媒体查询与其他首选项媒体查询非常契合,既能让你发挥创意,又能为用户提供调整。
代码示例:
body { --opacity: .5; background: hsl(200 100% 50% / var(--opacity)); @media (prefers-reduced-transparency: reduce) { --opacity: .95; }}
兼容性:
详细阅读:
现代CSS:新媒体查询 prefers-reduced-transparency 初探
Style queries 已在 Chrome 浏览器 111 中部分实现。目前,通过样式查询,您可以在使用 @container style() 时查询父元素上的自定义属性值。例如,查询自定义属性值是否存在,或是否设置为特定值,如@container style(--rain:true)。
代码示例:
我们可以使用 @container style() 检查容器是否具有 display: flex 样式,来定制子元素的展现样式。
.page-header { display: flex;}@container style(display: flex) { .page-header__start { flex: 1; display: flex; align-items: center; border-right: 1px solid lightgrey; }}/* 也可应用于 CSS 变量 */.card-container { --boxed: true;}@container style(--boxed: true) { .card { /* boxed styles */ }}
兼容性:
详细阅读:
CSS Container Style QueriesOpenReplay
scripting media query 可用于检查 JavaScript 是否可用。这对渐进增强非常有用。在使用媒体查询之前,检测 JavaScript 是否可用的策略是在 HTML 中放置一个 nojs 类,然后用 JavaScript 将其移除。现在,直接使用 CSS 可以检测 JavaScript 并进行相应调整,因此这些脚本也可以移除。
该功能在最新的 Chrome 120 版本已经被支持,大家可以更新浏览器体验。
代码示例:
通过脚本媒体查询可以直接判断,当 JavaScript 脚本可用时,设置页面透明度为 1,否则设置为 0。
@media (scripting: none) { .page { opacity: 0; }}@media (scripting: enabled) { .page { opacity: 1; }}
兼容性:
详细阅读:
scripting - CSS: Cascading Style Sheets | MDNMDN Web DocsMDN logoMozilla logo
2023 年有许多交互设计相关的功能出现,使用这些功能实现部分场景的交互效果会更加容易。主要包括:滚动驱动动画、视图转换、渐进函数等功能。
Scroll-driven Animations 是网络上一种常见的用户体验模式。这些动画与滚动容器的滚动位置相关联。这意味着当你向上或向下滚动时,链接的动画会直接向前或向后刷新。想想有趣的效果,比如视差背景图片或随着滚动而移动的阅读指示器。一种类似的滚动驱动动画是与元素在其滚动容器中的位置相关联的动画。例如,有了它,元素可以在进入视图时淡入。
Scroll-driven Animation 规范中定义了两种新的 timeline,可以指定动画在元素滚动条滚动时运行,@keyframes 的进度也就跟着滚动进度进行。
代码示例:
main { & section { .pop-out-image { view-timeline-name: --popper; } & figure { & img { animation-timeline: --popper; animation-range: entry 100% cover 50%; } } }}
兼容性:
详细阅读:
现代CSS:纯 CSS 实现苹果风格(Apple-style)的图片滚动器
现代CSS:纯 CSS 实现滚动图像弹出(pop-out)效果
View transitions 对页面的用户体验影响巨大。利用视图转换 API,您可以在单页应用程序的两个页面状态之间创建可视化转换。这些转换可以是整个页面的转换,也可以是页面上较小的内容,如在列表中添加或删除一个新项目。
视图转换 API 的核心是 document.startViewTranstion 函数。只要传递一个将 DOM 更新为新状态的函数,API 就会为你处理好一切。它的做法是获取之前和之后的快照,然后在两者之间进行转换。您可以使用 CSS 控制捕获的内容,还可以选择自定义这些快照的动画效果。
代码示例:
<style>::view-transition-old(root),::view-transition-new(root) { animation-duration: 2s;}</style><details> <summary>Toggle</summary> Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsam incidunt itaque accusantium, quis molestiae quia provident quas, rem consequuntur, fugiat placeat aperiam quo non! Aspernatur error et asperiores velit harum?</details><script>if (document.startViewTransition) { document.addEventListener('click', function (event) { if (event.target.matches('summary')) { event.preventDefault() // toggle the element const details = event.target.closest('details') document.startViewTransition(() => details.toggleAttribute('open')) } })}</script>
兼容性:
详细阅读:
Animating View Transitions
不要被这个函数的名字所迷惑。linear() 函数(不要与 linear 关键字混淆)允许您以简单的方式创建复杂的缓和函数,但会损失一些精度。
在使用 Chrome 113 中的 linear() 之前,在 CSS 中创建反弹或弹簧效果是不可能的。有了 linear(),我们就可以将这些缓和效果简化为一系列点,然后在这些点之间进行线性插值。
代码示例:
:root { --custom-easing: linear( 0, 0.06, 0.25 18%, 1 36%, 0.81, 0.75, 0.81, 1, 0.94, 1, 1 );}.bounce[data-method="css"] { animation: move var(--custom-easing) 2s infinite both;}@keyframes move { to { translate: 0% 200%; }}
兼容性:
@starting-style CSS 规则建立在新的 Web 能力的基础上,用于在 display: none 和其他属性之间进行动画。这个规则提供了一种在元素打开之前,浏览器可以查找的 “before-open” 样式的方法。这对于进入动画以及动画显示弹出框或对话框等元素非常有用。它还可以在创建元素并希望给它动画效果时使用。
代码示例:
/* IS-OPEN STATE */dialog[open] { translate: 0 0;}/* EXIT STATE */dialog { transition: translate 0.7s ease-out, overlay 0.7s ease-out, display 0.7s ease-out allow-discrete; translate: 0 100vh;}/* BEFORE-OPEN STATE */@starting-style { dialog[open] { translate: 0 100vh; }}
兼容性:
详细阅读:
@starting-style - CSS: Cascading Style Sheets | MDNMDN Web DocsMDN logoMozilla logo
Chrome 119 新增对 :user-invalid 和 :user-valid CSS伪类的支持,Chrome 119 稳定版本将于2023年10月25日正式发布。Firefox 88 和 Safari 16.5 已增加对改伪类的支持。
代码示例:
使用 :user-valid 和 :user-invalid 伪类,在 input 失去焦点时会自动提示
<style> :root { --color-default: grey; --color-invalid: red; --color-valid: green; } input:user-invalid { border-color: var(--color-invalid); } input:user-invalid ~ .error-message { display: block; } input:user-valid { border-color: var(--color-valid); }</style><form> <label for="email">E-MAIL:</label> <input type="email" id="email" placeholder="" required autocomplete="off"/> <p class="error-message">Please enter a valid e-mail address</p></form>
详细阅读:
前端快讯|Chrome 119 新增对 :user-invalid 和 :user-valid CSS 伪类的支持
Chrome 在 119 版本对 <select> 元素进行了小而强大的升级,Safari 17 中也实现了这项功能。现在,您可以在 select 选项列表中添加 <hr>(横向规则)元素,它们将显示为分隔符,有助于在视觉上分割选项,从而获得更好的用户体验。
详细阅读:
Chrome 119:select 元素支持添加 hr 元素,用户体验更好!
有了 color-mix() 您不仅可以将白色或黑色混合成一种颜色,还可以将透明度混合成一种颜色,并且可以在您选择的任何色彩空间中实现这一切。这既是基本的色彩功能,也是高级的色彩功能。
a { &::before { position: absolute; left: -20px; bottom: 10px; width: 20px; height: 100%; content: ""; background-color: color-mix(in srgb, var(--color), black 20%); transform: skewY(45deg); transition: background-color 200ms; } &::after { position: absolute; left: -10px; top: -20px; width: 100%; height: 20px; content: ""; background-color: color-mix(in srgb, var(--color), black 20%); transform: skewX(45deg); }}.circle-02 { --t: 2; --k: calc(var(--t)/20); fill: none; transform: rotate(-90deg); stroke-linecap: round; stroke: color-mix(in hsl shorter hue, #8a9b0f calc(var(--k)*100%), #940a3d); stroke-dasharray: var(--k) 1;}
详细阅读:
现代CSS:纯 CSS 实现 3D 导航栏
现代CSS:纯 CSS 实现倒计时效果
2023 年 CSS 经历了一次复兴,实现很多现代 CSS 功能,对 Web 开发者来说是一大利好,过去很多需要使用 JavaScript 实现的功能,现在可以直接使用 CSS 来实现了。让我们对未来充满期待,相信 CSS 还会带来更多的新功能。