CSS智能化的未来:从样式语言到逻辑驱动的进化

本文探讨了CSS从纯粹的表现层语言向具备逻辑能力语言的演变历程,重点分析了容器查询、if()函数等新特性如何推动CSS智能化发展,并讨论了开发者社区对此变革的不同观点与未来挑战。

CSS Intelligence: Speculating On The Future Of A Smarter Language

CSS已从纯粹的表现层语言演变为具备逻辑能力的语言——这得益于容器查询、关系型伪类和if()函数等特性。它是否仍仅用于样式设计,还是正在变得更强大?Gabriel Shoyombo探讨了CSS这些年的智能化发展、未来方向、解决的问题、是否变得过于复杂,以及开发者如何应对这一转变。

历史背景:CSS的刻意简化

回顾CSS历史,这个语言的诞生是为了分离内容与表现,使网页更易管理和维护。1996年发布的CSS1引入了字体属性、颜色、盒模型(内边距、外边距和边框)、尺寸(宽度和高度)、简单显示属性(none、block、inline)和基础选择器。两年后,CSS2推出了定位、z-index、增强选择器、表格布局和针对不同设备的媒体类型等功能。但样式语言存在不一致性,这一问题在2011年CSS2.1成为现代CSS标准后得到解决。

在CSS1到CSS2.1期间,CSS基本上是静态和声明式的。开发者经历了项目中的挫折和突破。由于缺乏Flexbox和CSS Grid等直观布局,开发者依赖表格布局、定位或浮动等临时方案应对复杂设计,尽管浮动最初是为文本环绕网页上的媒体对象设计的。结果,开发者面临容器坍塌和意外换行等问题。尽管如此,基础样式是直观的。新手可以轻松学习Web开发并在第二天添加基本样式。CSS与内容和逻辑分离,因此性能高且轻量。

CSS3:迈向上下文感知的第一步

当CSS3推出时,情况发生了变化。开发者期望像以前版本那样的单一整体更新,但他们的期望与最新发布的现实不符。CSS3红毯揭示了一个模块化系统,具有强大的布局工具如Flexbox、CSS Grid和媒体查询,首次定义了开发者如何建立响应式设计。拥有超过20个模块,CSS3标志着“更智能的CSS”的开始。

Flexbox在2012年左右引入,提供了一个灵活的一维布局系统,而2017年推出的CSS Grid通过提供二维布局框架进一步推进了布局,使复杂设计以最少代码成为可能。正如Chris Coyier所讨论的,这些进步减少了对浮动等临时方案的依赖。

不仅如此。媒体查询是CSS3的一个重要发布,是推动智能CSS的主要贡献者之一。通过媒体查询,CSS可以响应不同设备的屏幕,调整样式以适应屏幕尺寸、宽高比和方向,这是早期版本无法轻易实现的壮举。在第五级中,它添加了用户偏好媒体功能,如prefers-color-scheme和prefers-reduced-motion,通过适应用户设置的样式使CSS更加以用户为中心,增强了可访问性。

CSS3标志着上下文感知CSS的开始。

上下文感知意味着能够理解并相应反应周围环境或情况的能力。它意味着系统和设备可以感知关键信息,如您的位置、一天中的时间和活动,并相应调整。

在Web开发中,“上下文感知”一词一直与组件一起使用,但什么驱动了上下文感知组件?如果您提到组件样式以外的任何东西,您就错了!对于一个组件被认为是上下文感知的,它需要感知其环境的存在并知道其中发生了什么。例如,为了让您的网站更新样式以适应暗模式界面,它需要知道用户的偏好。此外,要更改其布局,网站需要知道用户访问它的设备——多亏了用户偏好媒体查询,这是可能的。

尽管有这些功能,CSS仍然主要是反应式的。它响应外部因素,如屏幕大小(通过媒体查询)或输入状态(如:hover、:focus或:checked),但它从不基于环境变化做出决策。开发者通常转向JavaScript来实现那种级别的交互。

然而,现在不再是这样了。

例如,通过容器查询和最近的容器样式查询,CSS现在不仅响应布局约束,还响应设计意图。它可以基于组件的环境甚至其父级的主题或状态进行调整。这还不是全部。最近规范的if()函数承诺内联条件逻辑,允许样式基于条件更改,所有这些都可以在没有脚本的情况下实现。

这些发展表明CSS正在超越表现层来处理行为,挑战其传统角色。

推动智能化的新CSS特性

目前有几个特性正在推动CSS走向动态和自适应边缘,从而使它更智能,但这两个值得提及:容器样式查询和if()函数。

什么是容器样式查询,为什么它们重要?

为了更好地理解容器样式查询,快速了解其近亲:CSS Containment Module Level 3中引入的容器大小查询是有意义的。

容器大小查询允许开发者基于其父容器的尺寸来样式化元素。这对于基于组件的设计是一个巨大的胜利,因为它消除了将响应式样式硬塞到全局媒体查询中的需要。

1
2
3
4
5
6
/* 基于大小的容器查询 */
@container (min-width: 500px) {
  .card {
    flex-direction: row;
  }
}

容器样式查询通过允许您基于容器上设置的自定义属性(又名CSS变量)来样式化元素,进一步推进了这一点。

1
2
3
4
5
6
7
/* 基于样式的容器查询 */
@container style(--theme: dark) {
  .button {
    background: black;
    color: white;
  }
}

这些特性在CSS中非常重要,因为它们解锁了上下文感知组件。一个按钮可以基于父级设置的–theme属性更改外观,而无需使用JavaScript或硬编码类。

if()函数:窥见未来

CSS if()函数可能是最激进的转变。当实现时(截至版本137,只有Chrome支持它),它将允许开发者在属性声明中直接编写内联条件逻辑。想想CSS中的三元运算符。

1
padding: if(style(--theme: dark): 2rem; else: 3rem);

这行假设的代码或伪代码(不是语法)将文本颜色设置为白色,如果–theme变量等于dark,否则为黑色。目前,if()函数在任何浏览器中都不支持,但它在CSS工作组的雷达上,并且有影响力的开发者如Lea Verou已经在探索其可能性。

新CSS:CSS和JavaScript之间的界限是否模糊?

传统上,关于样式的关注点分离是这样的:CSS负责事物看起来如何,JavaScript负责事物行为如何。然而,像容器样式查询和规范的if()函数这样的特性开始模糊这条线。CSS开始行为,不是在API调用或事件监听器的意义上,而是在基于逻辑或上下文条件应用样式的能力上。

随着Web开发的发展,CSS开始 encroach on JavaScript territory。CSS3带来了动画和过渡,这是交互式Web开发的强大组合,在早期没有JavaScript是不可能的。今天,研究证明CSS已经承担了先前由JavaScript处理的几个交互任务。例如,:hover伪类和transition属性允许视觉反馈和平滑动画,如“Bringing Interactivity To Your Website With Web Standards”中所讨论的。

这还不是全部。切换手风琴和模态框以前存在于JavaScript的领域,但今天,这可以通过新的强大CSS组合实现,如用于手风琴的

HTML标签或用于模态框的:target伪类。CSS还可以使用aria-label与content: attr(aria-label)处理工具提示,以及使用单选输入和标签处理星级评分,如同一篇文章中详细说明的。

另一篇文章“5 things you can do with CSS instead of JavaScript”列出了如scroll-behavior: smooth用于平滑滚动和@media (prefers-color-scheme: dark)用于暗模式等功能,这些任务曾经需要JavaScript。在同一篇文章中,您还可以看到通过使用CSS滚动捕捉功能(我们甚至不是在谈论专门为仅在CSS中创建轮播而设计的特性,最近在Chrome中原型化)创建轮播而无需JavaScript是可能的。

CSS向JavaScript领域的这些扩展现在使后者仅处理Web应用程序中的复杂、关键交互,如用户输入、进行API调用和管理状态。虽然CSS伪类如:valid和:invalid可以作为输入元素中的错误或成功指示器,但您仍然需要JavaScript进行动态内容更新、表单验证和实时数据获取。

CSS现在解决了许多开发者从未知道存在的问题。在许多样式场景中,JavaScript被排除在外,开发者现在有了简化的代码库。依赖更少,开销更低,网站性能更好,尤其是在移动设备上。事实上,这种转变使CSS倾向于更易访问的Web,因为CSS驱动的设计通常更容易被浏览器和辅助技术处理。

虽然新特性带来了很多好处,但它们也引入了以前不存在的复杂性:

  • 当逻辑分布在CSS和JavaScript中时会发生什么?
  • 如果没有清晰视图显示什么触发了它们,我们如何调试条件样式?
  • CSS只需要处理颜色、字体、布局和间距等基本样式,这些对新开发者来说更容易上手。随着这些新特性需要理解 once exclusive to JavaScript的概念,学习曲线变得多难?

开发者分裂了。虽然一些人欢迎更智能、更组件感知的Web的自然演变想法,但其他人担心CSS变得过于复杂——一个最初设计用于格式化文档的语言现在 juggling logic trees and style computation。

分裂的观点:CSS中的逻辑是有益还是有害?

虽然上一节的证据倾向于边界模糊,但开发者之间存在 significant controversy。许多现代开发者认为CSS中的逻辑早就该有了。随着Web开发变得更加组件化,声明式样式的局限性变得更加明显,导致支持者将逻辑视为 once purely styling language的必要演变。

例如,在像React这样的前端库中,组件通常需要基于props或states的条件样式。开发者不得不使用JavaScript或CSS-in-JS解决方案来处理这种情况,但事实是这些解决方案并不正确。它们引入了复杂性并将样式和逻辑耦合。CSS和JavaScript在Web开发中 meant to have standalone concerns,但像CSS-in-JS这样的库忽略了规则并将两者结合。

我们已经看到像SASS和LESS这样的预处理器证明了条件、循环和变量在样式中的有用性。不接受CSS in JavaScript方法的开发者已经 settled for these preprocessors。尽管如此,像Adam Argyle一样,他们表达了他们对原生CSS解决方案的需求。通过原生条件,开发者可以减少JavaScript开销并避免运行时类切换以实现条件呈现。

“对我来说,在JavaScript中操作样式设置从来感觉不对,当CSS是工作的正确工具时。通过CSS自定义属性,我们可以将需要来自JavaScript的内容发送到CSS。”
— Chris Heilmann

此外,Bob Ziroll不喜欢使用JavaScript来处理CSS meant to handle的事情,并认为这是不必要的。这反映了即使涉及JavaScript,也偏好使用CSS进行样式任务。这些开发者拥抱CSS的新能力,将其视为出于性能原因减少JavaScript依赖的一种方式。

其他人反对它。将逻辑引入CSS是一个 slippery slope,CSS可能通过变得太像编程语言而失去其核心优势——简单性、可读性和可访问性。担心的是开发者 run the risk of complicating the web more than it is supposed to be。

“我是老派的。我喜欢我的CSS与HTML分离;我的HTML与JS分离;我的JS与CSS分离。”
— Sara Soueidan

这种观点强调了传统的关注点分离,认为混合角色会使维护复杂化。此外,Brad Frost在 specifically talking about CSS-in-JS时也表示怀疑, stating that it, “doesn’t scale to non-JS-framework environments, adds more noise to an already-noisy JS file, and the demos/examples I have seen haven’t embodied CSS best practices.” 这突出了对可扩展性和最佳实践的担忧,表明模糊的边界可能并不总是有益的。

社区讨论,如Stack Overflow上的讨论,也反映了这种分裂。像“Is it always better to use CSS when possible instead of JS?”这样的问题收到答案 favouring CSS for performance and simplicity,但其他人 argue JavaScript is necessary for complex scenarios,说明了持续的辩论。不要被欺骗。同意CSS在样式上比JavaScript表现更好似乎很方便,但情况并非总是如此。

更智能的CSS而不失去其灵魂

CSS一直通过声明式、可访问和目的驱动而与完整的编程语言如JavaScript区分开来。

如果CSS要变得更智能,挑战不在于为了自身利益而使其更强大,而是在发展时不 compromise its major concern。

“那么,一个逻辑丰富但仍然声明式的CSS可能是什么样子?让我们找出答案。

条件规则(if, @when…@else)与谨慎引入的逻辑

CSS演变的一个主要前沿是通过if()函数和@when…@else at-rules引入原生条件,这些是CSS Conditional Rules Module Level 5规范的一部分。虽然仍处于早期草案阶段,这将允许开发者基于评估的条件应用样式,而无需转向JavaScript或预处理器。与JavaScript的命令式性质不同,这些条件旨在保持逻辑 ingrained in CSS’s existing flow,与级联和特异性对齐。

更强大、有意的选择器

选择器一直是CSS的主要优势之一,以 targeted way扩展它们将使更容易声明式表达关系和条件,而无需类或脚本。目前,:has()让开发者基于子元素样式化父元素,而:nth-child(An+B [of S]?)(在Selectors Level 4中)允许更复杂的匹配模式。 together,它们允许更大的精度而不改变CSS的性质。

无JavaScript的作用域样式

开发者在像React或Vue这样的基于组件的框架中面临的挑战之一是样式作用域。样式作用域确保样式仅应用于特定元素或组件,并且不泄漏。过去,为了实现这一点,您需要实施BEM命名约定、CSS-in-JS或构建工具如CSS Modules。CSS中的原生作用域样式,通过新的实验性@scope规则,允许开发者在特定上下文中封装样式,而无需额外工具。此特性使CSS更加模块化,而不将其绑定到JavaScript逻辑或复杂的类系统。

一个基本的设计问题现在是,我们是否可以在不使CSS像JavaScript的情况下赋予它权力。事实是,为了赋予CSS条件逻辑、强大选择器和作用域规则,我们不需要它 mirror JavaScript’s syntax or complexity。目标是声明式表达性,给CSS更多意识和控制,同时保留其清晰、可读的性质,我们应该专注于这一点。当做得正确时,更智能的CSS可以放大语言的优势而不是稀释它们。

真正的危险不是逻辑本身,而是 unchecked complexity that obscures the simplicity with which CSS was built。

注意事项和约束:为什么智能并不总是更好

推动更智能的CSS伴随着 significant trade-offs alongside control and flexibility。多年来,历史表明,向语言或框架或库添加新特性 most likely introduces complexity,不仅对新

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计