当前位置: 首页 > Web前端 > CSS

2019年,你能抛弃CSS预处理器吗?

时间:2023-03-31 00:58:31 CSS

随着前端工程化的不断完善,CSS预处理器已经成为项目中不可或缺的一部分。很多人在项目技术选择阶段都会首先选择一款CSS预处理器。大多数前端工程脚手架也内置了一系列CSS预处理模板,大家已经习惯了享受CSS预处理器带来的编写代码的灵活流畅,而将原本的CSS搁置一旁。许多前端开发人员可能仍然认为CSS预处理器是一项相对较新的技术。事实上,并非如此。最早的CSS预处理器Sass从2007年至今已经诞生了12年,相对较新的Stylus也发布了9年。.前端技术栈突飞猛进,W3C的CSS工作组不断从社区汲取营养,加速CSS的迭代。那么到现在,CSS能否取代CSS预处理器的地位呢?CSS预处理器会成为CSS过渡的产物吗?W3C介绍CSS是开放网络的核心语言之一,由W3C规范跨浏览器标准化。因此,在深入研究CSS规范的更新进展之前,我们有必要先了解一下W3C及其规范的制定过程。W3C,又称万维网联盟,又称W3C理事会,是万维网的主要国际标准组织。它是一个准自治的非政府组织。它由TimBerners-Lee于1994年10月在麻省理工学院麻省理工学院计算机科学与人工智能实验室(MIT/LCS)创立。W3C制定了一系列标准,并敦促Web应用程序开发人员和内容提供商遵循这些标准。标准的内容包括所用语言的规范、开发中使用的指南和解释引擎的行为等。W3C制定了许多影响深远的标准规范,包括HTML、DOM、SVG、XML和CSS。W3C规范制定过程由于我们需要在不同的阶段谈一些CSS规范,这里有必要简单介绍一下W3C规范制定过程。根据W3C的ProcessDocument,一个推荐的制定需要经历不同的阶段。主要阶段有:WDWorkingdraft、CRCandidaterecommendation、PRrecommendation、REC、W3Crecommendation。标准流程结束。如果想了解更多W3C标准流程和组织架构,可以查看W3C标准流程和组织架构。CSS历史HTML和CSS密不可分,您可能认为它们是结合在一起的。事实上,在TimBernersLie于1989年发明互联网之后的许多年里,世界上并没有一个叫做CSS的东西(更不用说CSS预处理器了),原始版本的Web根本就没有提供对网页。HTML规范虽然规定了网页中标题和段落应该使用的标签,但没有涉及这些内容在浏览器中应该呈现的样式(如大小、位置、间距、缩进等)。然而,仅仅10年后,CSS就被现代网络社区完全采用。这期间,发生了一系列有趣的故事。如果你有兴趣,可以看看ALookBackattheHistoryofCSS。CSS1于1994年由H?konWiumLie和BertBos合作设计CSS创建。他们于1994年在芝加哥的一次会议上首次提出了他们对CSS的提议。1996年12月发布的第一版CSS1要求主要规定了选择器、样式属性、伪类和对象等几个主要部分。CSS2CSS2于1998年5月由W3C发布。CSS2规范是在CSS1的基础上设计的,扩展和改进了许多更强大的属性。包括选择器、位置模型、布局、表格样式、媒体类型、伪类、光标样式。CascadingStyleSheetsLevel2Revision1,通常称为“CSS2.1”,修复了CSS2中的错误,删除了支持不佳或不完全互操作的功能,并向规范添加了已实现的浏览器扩展。CSS2.1多年来一直在工作草案(WD)状态和候选推荐(CP)状态之间来回切换,以符合W3C标准化技术规范的过程。CSS2.1于2004年2月25日首次成为候选推荐(CR)标准,但于2005年6月13日返回工作草案(WD)以供进一步审查。它于2007年7月19日返回候选推荐(CP)标准,并在2009年更新了两次。但是,经过修改和澄清,它又回到了2010年12月7日的LastCallWorkingDraft。CSS3CSS3是CascadingStyleSheets语言的最新版本,旨在扩展CSS2.1。CSSLevel2花了9年时间(从2002年8月到2011年6月)才达到Recommendation(推荐)状态,主要是因为一些次要特性受阻。为了加快已经确认没有问题的特性的标准化,W3C的CSS工作组做出了一个被称为北京主义的决定,将CSS分成许多小组件,称为模块。这些模块彼此独立,并按照自己的节奏进行标准化。其中一些已经是W3CRecommendation状态,一些仍然是EarlyWorkingDrafts(早期工作草案)。当新的需求被确认后,新的模块将以同样的方式添加。从形式上讲,CSS3标准本身已不存在。每个模块都是独立标准化的,现在标准的CSS包括修改后的CSS2.1及其扩展的完整模块,模块层级数不一致。可以为每个时间点的CSS标准定义一个快照,列出CSS2.1和成熟的模块。W3C会定期发布这些快照,例如2007年、2010年、2015年或2017年。到目前为止,level3以上的模块还没有标准化,未来应该会改变。然而,一些模块,如Selectors4或CSSBordersandBackgroundsLevel4已经有了编辑草案,即使它们还没有达到首次发布的工作草案状态。有一张图可以更直观的表示目前CSS3Modules的分类和状态:问:为什么没有CSS4?没有单一的、集成的CSS4规范,因为它被分成单独的“4级”模块。Level4不等于CSS4,比如CSSCustomPropertiesforCascadingVariablesModuleLevel1,就不能说是CSS1。CSS预处理器CSS自诞生以来,其基本语法和核心机制都没有发生实质性的变化。长期以来,它的发展几乎完全是在表现力层面上的提升。一开始,CSS在网页中的作用只是辅助装饰,易学性是最大的要求;然而,网站的复杂性已经无法比拟,原生的CSS已经让开发者无法为所欲为。当一种语言的能力不足并且用户的操作环境不支持替代语言时,它就成为“编译目标”语言。开发者会选择另一种高级语言进行开发,然后编译成低级语言进行实际运行。于是乎,在前端领域,天道酬勤,人人有责,CSS预处理器应运而生。HundredFlowersCSSPreprocessor是一个允许您通过预处理器自己独特的语法生成CSS的程序。市面上有很多CSS预处理器可供选择,大多数CSS预处理器都会加入一些原生CSS没有或者不完善的高级特性。这些特性使得CSS的结构更具可读性和易于维护。目前以社区为代表的CSS预处理器主要有以下几类:Sass:诞生于2007年,最早最成熟的CSS预处理器,得到Ruby社区的支持和最强大的CSS框架Compass,目前受LESS影响,已经进化到完全兼容CSS的SCSS。Less:出现于2009年,受SASS影响较大,但使用CSS语法,这使得大多数开发人员和设计人员更容易上手。Ruby社区之外的支持者远远超过SASS。它的缺点是不如SASS强大,可编程的功能还不够,但优点是简单和兼容CSS,这反过来又影响了SASS向SCSS时代的演进。著名的TwitterBootstrap使用LESS作为底层语言。Stylus:Stylus是一个CSS预处理框架,创建于2010年,来自Node.js社区,主要用于为Node项目提供CSS预处理支持,因此Stylus是一种新的语言,可以创建健壮的、动态的、富有表现力的CSS。它比较年轻,其本质类似于SASS/LESS等。优点虽然各种预处理器功能强大,但使用最多的是以下功能:变量、混合、嵌套规则)和代码模块化(Modules)。下面以Sass为例,展示预处理器中这些主要特性的实现:变量和运算符(+、-、*、/、%)$font-size:10px;$font-family:Helvetica,sans-serif;body{font:$font-size$font-family;}.mark{font-size:1.5*$font-size;}Mixins@mixinclearfix{&:after{display:block;内容:'';明确:两者;}}.sidebar{@includeclearfix;}Nesting//menu.nav{>li{>a:hover{background-color:red;}}}Modules@import'./common';@import'./github-markdown';@import'./mixin';@import'./variables';缺点或不足额外的编译配置需要在写样式之前做一些额外的编译配置工作,sass-node的安装和编译配置会卡住一群前端新手。编译成本每次修改代码都需要重新编译,耗费时间和CPU。不同学习成本的CSS预处理器具有不同的语法,这增加了学习成本。在同一个团队甚至项目中,可能会同时使用多个样式预处理器。//Sass$color:#f00;$images:"../img";@mixinclearfix{&:after{content:"";显示:块;明确:两者;}}body{颜色:$color;背景:url("#{img}/1.png");@includeclearfix;}//Less@color:#f00;@images:"../img";.clearfix(){&:after{content:"";显示:块;明确:两者;}}body{颜色:@color;背景:url("@{img}/1.png");.clearfix;}调试在使用CSS预处理器的时候,我们通常会配置SourceMap来辅助调试,但即便如此,还是会出现一些难以调试的情况:更新迭代,但大部分人使用的核心功能还是一样:Variables、Mixing、Nested、Module,顶多加上一些工具功能。我们既想要预处理器的优点,也想要它带来的成本和缺点。有没有办法两全其美?CSS这么多年一直在从社区吸取养分,加速进化迭代。我们能从CSS标准中找到答案吗?CSS自定义属性(CSSCustomProperties)中的变量,也称为CSS变量(CSSVariable),允许您在样式中声明变量,并通过var()函数使用它们。级联变量的CSS自定义属性规范于2012年10月首次作为工作草案(WD)提出,并于2015年10月进入候选推荐(CR)阶段。浏览器支持率现已接近93%。CSS变量的定义和使用如下,可以定义的类型极其丰富。/*声明*/--VAR_NAME:;/*用法*/var(--VAR_NAME)/*根元素选择器(全局范围),例如*/:root{/*CSS变量声明*/--main-color:#ff00ff;--main-bg:rgb(200,255,255);--logo-border-color:rebeccapurple;--header-height:68px;--内容填充:10px20px;--基线高度:1.428571429;--过渡持续时间:.35s;--external-link:"外部链接";--margin-top:calc(2vh+20px);}body{/*使用变量*/color:var(--main-color);}不同于SASS预处理器变量的编译时处理,处理CSS变量由浏览器在运行时,所以CSS变量将更加强大和灵活。算子可以使用calc()进行计算:root{--block-font-size:1rem;}.block__highlight{/*WORKS*/font-size:calc(var(--block-font-size)*1.5);}GenerateColors可以通过RGB等函数生成和计算颜色:在GenerateColorsCSStoJSCSS变量出现之前,从CSS向JS传值非常困难,甚至需要一些Hack技术。现在使用CSS变量,可以直接通过JS获取变量值并修改:.breakpoints-data{--phone:480px;--tablet:800px;}constbreakpointsData=document.querySelector('.breakpoints-data');//GETconstphone=getComputedStyle(breakpointsData).getPropertyValue('--phone');//SETbreakpointsData.style.setProperty('--phone','custom');CustomTheme使用CSS变量来自定义和动态切换网站主题非常简单方便:先定义不同主题下的变量,然后正常编写样式即可。html{--hue:210;/*蓝色*/--text-color-normal:hsl(var(--hue),77%,17%);...}html[data-theme='dark']{--text-color-normal:hsl(var(--hue),10%,62%);...}通过JS更改元素属性,动态切换主题:document.documentElement.setAttribute('data-theme','dark')document.documentElement.setAttribute('data-theme','light')查看更多高级用法请参考:CSS自定义属性(原生变量)深入浅出变量定义为什么要以--开头?原因在这里:Let'sTalkAboutCSSVariablesMixinsinCSSCSS有一个提案:CSS@applyRule,根据草稿描述,用户可以直接使用CSS变量来存储声明块,然后通过@apply规则使用。:root{--pink-schema:{颜色:#6A8759;背景色:#F64778;}}body{@apply--pink-schema;}不幸的是,这个提议已经被放弃了。有兴趣了解具体放弃原因的可以参考这篇文章:WhyIAbandoned@apply。虽然目前Mixins还没有很好的CSS实现标准,但我们坚信,迟早会出现更好的规范来填补CSS的这一空白。NestinginCSSCSS有一个Nesting规范,虽然只是在Editor'sDraft阶段:CSSNestingModuleLevel3。根据CSSNestingModule,Nesting规范与预处理器基本相同。/*悬停时的下拉菜单*/ul{/*直接嵌套(&必须是选择器的第一部分)*/&>li{color:#000;&>ul{显示:无;}&:hover{颜色:#f00;&>ul{显示:块;}}}}CSS中的模块其实CSS很早就有模块化的解决方案,就是@import,使用CSS的@import规则,可以参考其他文件样式。这个特性从IE5.5开始所有浏览器都支持了,为什么用户这么少呢?原因有很多:在一些老的浏览器中,存在加载顺序的bug,无法并行加载,导致请求过多......但是现在大家的前端项目基本都会使用构建工具(Gulp,Webpack,etc)打包上线,就不会存在上面的缺点,而且在webpack的css-loader中可以配置是否开启@import。SelectorHelpers除了上面介绍的一些主要特性外,CSS还提供了一些新特性来帮助你写得更优雅。:matches伪类已重命名为:is():matches()CSS伪类函数将选择器列表作为参数,并选择列表中任何一个选择器可以选择的元素,即对于编写大型选择器很有用,浏览器支持率接近93%。/*语法*/:matches(selector[,selector]*).nav:matches(.side,.top).links:matches(:hover,:focus){color:#BADA55;}/*等同于以下内容code*/.nav.side.links:hover,.nav.top.links:hover,.nav.side.links:focus,.nav.top.links:focus{color:#BADA55;}更多细节你可以查看规范:SelectorsLevel4@custom-selector同时,你也可以使用自定义选择器来定义可以匹配复杂选择器的别名。/*语法*/@custom-selector:;定义方法与CSS变量类似,用法略有不同。@custom-selector:--text-inputsinput[type="text"],input[type="password"];:--text-inputs.disabled,:--text-inputs[disabled]{opacity:0.5}/*相当于下面的代码*/input[type="text"].disabled,input[type="password"].disabled,input[type="text"][disabled],input[type="password""][disabled]{opacity:0.5}要使用虽然以上CSS特性还处于不同的阶段,浏览器支持也不尽相同,但是使用postcss-preset-env,可以先尝试CSS的最新特性。当然postcss-preset-env的配置也很简单。以Webpack为例:rules:[{test:/\.css$/,use:['style-loader',{loader:'css-loader',options:{importLoaders:1}},{loader:'postcss-loader',options:{ident:'postcss',plugins:()=>[postcssPresetEnv(/*pluginOptions*/)]}}]经过一番梳理,我们发现虽然CSS下加快了更新迭代速度社区的刺激,到目前为止,还达不到CSS预处理器VSCSS的地步。只能说,在使用CSS预处理器的同时,你还可以在你的项目中尝试一些很棒的CSS新特性,即:CSSPreprocessor+CSS。但我们仍然坚信,在W3C的推动下,随着CSS本身的不断完善,CSS预处理器最终会像当年的CoffeScript和Jade一样,成为时代的过渡产物。到时候你就不用再为各种CSS预处理器的环境配置和技术选择等烦恼了,直接打开编辑器就可以愉快的编写样式了。请参阅您可能不需要CSS预处理器CSS3模块和标准化过程如何阅读W3C规范维基百科-层叠样式表层叠变量模块级别1的CSS自定义属性