CSS的全稱是層疊樣式表(Cascading Style Sheets),它的一個重要概念既是“層疊”,靠後聲明的樣式會覆蓋前面的樣式。這個特性使我們在開發新內容時,非常方便地在繼承舊樣式的同時做出一些微調。
隨著前端開發的工程化,特別是Vue.js等框架的廣泛使用,我們需要在專案中管理越來越多的碎片樣式檔案。當這些樣式檔案互相關聯時,為了讓它們在HTML文件中出現的順序符合我們的預期,往往需要我們付出更多的精力。
好在,我們現在有了CSS級聯層。
透過級聯層,我們可以非常方便地歸類CSS程式碼,使得層中的樣式永遠在邏輯上按我們想要的方式排序,而不用關心它們在HTML文件中出現的順序。
CSS級聯層已被確認為 Baseline 2022,您可以放心地使用這個特性。
原子設計(Atomic Design)是現代Web開發常用的設計模式,我們可以依照這個設計,將樣式層同樣分成以下五層:
在實際工程中您可能需要增減它們,例如添加一個基礎層用於在不同瀏覽器中規範初始樣式(Reboot/Normalize),所以最終工程中的樣式層可能是這樣的:
/* 规范基础样式、定义CSS自定义属性等 */ @layer base { /* ... */ } /* 我们可以借助子层来排序这些可重用组件的样式 */ @layer components.atoms { /* ... */ } @layer components.molecules { /* ... */ } @layer components.organisms { /* ... */ } /* 模板可以被归类到布局中 */ @layer layouts { /* ... */ } @layer pages { /* ... */ }
只要我們保證HTML文件的最開始按照這個順序定義層,我們就可以在之後的開發中直接將樣式代碼防止在層中而無需關係它們的被導入的先後順序。
<meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <!-- 在定义层时,可以用简写 --> <style>@layer base, components.atoms, components.molecules, components.organisms, layouts, pages;</style> <!-- 实际的样式代码从这里之后导入 --> <style>/* ... */</style> <link rel="stylesheet" href="...">
目前絕大多數與TailwindCSS結合的元件庫,都是透過JS控制工具類別的方式調整元件的樣式,本文不討論這個方式。借助級聯層可以將TailwindCSS與任意的元件庫結合使用,從而允許我們使用tailwind微調元件庫的樣式。
TailWindCSS中已經有了層的概念,在4之前的版本中,依舊使用的模擬的層,並非真正的級聯層,為了讓TailwindCSS的樣式在我們的工程中出現在合適的位置,我們需要改寫導入檔:
/* * "base"这个层名会被TailwindCSS当作它的逻辑层处理, * 此处我们使用"tailwind-base"代替 */ @layer tailwind-base { @tailwind base; } /* * "utilities"和"variants"同理, * 但我们无需定义两个层来包裹它们,因为它们始终应该定义在我们的样式之后 */ @layer tailwind-utilities { @tailwind utilities; @tailwind variants; }
然後,我們調整一下級聯層的定義:
/* * 注意!我在此处删除了前文中的base层, * tailwind的base已经包含了样式的规范化内容, * 我们的工程通常不需要再次格式化 */ @layer tailwind-base, components.atoms, components.molecules, components.organisms, layouts, pages, tailwind-utilities;
元件庫是前端工程不可或缺的部分,以上文為基礎,我們可以很容易地想到,元件的樣式應當在「base」層(或「tailwind-base」層)與「layout」層之間,也即「components」層中。至於它應該在components中的何處,這需要您結合實際情況來決定,我們可以利用子層的特性進行排序
然而,絕大多數元件庫都沒有使用級聯層,直接導入元件庫的樣式會使它們出現在所有層之外,在級聯層規則下,它們的樣式將是最高優先級,我們無法使用tailwind或其他方式覆蓋它們的樣式。
為了解決這個問題,我開發了一個postcss插件,它能夠透過配置為匯入的樣式添加級聯層。
接下來,以Vite專案為例,簡單說明如何在工程中結合使用 element-plus 元件庫。
初始化項目以及安裝TailwindCSS和Element Plus的內容在此省略,無論您是否使用自動導入的方式引入Element Plus均可以按本文的方式操作。
首先,安裝@web-baseline/postcss-wrap-up-layer,您可以選擇您喜歡的套件管理器:
yarn add -D @web-baseline/postcss-wrap-up-layer
然後,在vite.config.ts檔案中使用這個外掛程式:
/* 这里省略了其他无关的配置内容 */ import WrapUpLayer from '@web-baseline/postcss-wrap-up-layer'; export default defineConfig({ css: { postcss: { plugins: [ WrapUpLayer({ rules: [ { /* 此处使用了正则进行匹配 */ includes: /^node_modules\/element-plus\//, layerName: 'components.element-plus', }, ], }), ], }, }, })
就是這樣,這個外掛程式將會為所有符合的檔案添加設定的級聯層,如果您使用其他的元件庫,可以進行類似的設定。
在Vue的單一檔案元件中,我們可以使用定義樣式,我們可以直接在其中將樣式包裹在級聯層中,就像這樣:
<template> <h2 class="title">Title</h2> </template> <style scoped> @layer components.atoms { .title { font-size: 3rem; } } </style>
這樣不方便,也不美觀。通常情況下,我們不會注意樣式在哪個層中,也不希望看到這個始終存在的縮排。因此,我也開發了一個vite插件,讓您以屬性的形式(例如:
安裝@web-baseline/vite-plugin-vue-style-layer:
yarn add -D @web-baseline/vite-plugin-vue-style-layer
在vite.config.ts檔案中使用這個外掛程式:
/* 这里省略了其他无关的配置内容 */ import Vue from '@vitejs/plugin-vue'; import VueStyleLayer from '@web-baseline/vite-plugin-vue-style-layer'; export default defineConfig({ plugins: [ Vue(), VueStyleLayer(), ], })
這樣,就可以將上文的組件改寫成下面的樣子:
<template> <h2 class="title">Title</h2> </template> <style scoped layer="components.atoms"> .title { font-size: 3rem; } </style>
我认为,这或许可以成为Vue SFC官方支持的功能,甚至是新的Web特性,将layer作为
这个Vite插件目前已经满足了使用的需要,但我知道它还有些许不足之处,我正在考虑将其使用 unplugin 重构,以支持更多的框架,而不仅仅是Vite+Vue。
我通常使用Nuxt进行Web开发,而以上的功能在Nuxt中配置需要分散在各处,因此我将它们合并为一个模块以集中配置。由于Nuxt并不公开HTML文档的编辑,我在模块中添加了级联层排序字段。
安装@web-baseline/nuxt-css-layer:
yarn add -D @web-baseline/nuxt-css-layer
在nuxt.config.ts文件中使用这个模块:
/* 这里省略了其他无关的配置内容 */ export default defineNuxtConfig({ modules: [ '@web-baseline/nuxt-css-layer', '@nuxtjs/tailwindcss', '@element-plus/nuxt', ], cssLayer: { rules: [ { includes: /^node_modules\/element-plus\//, layerName: 'components.element-plus', }, ], cssLayerOrder: [ 'tailwind-base', 'components.element-plus', 'components.atoms', 'components.molecules', 'components.organisms', 'layouts', 'pages', 'tailwind-utilities', ], }, });
在CSS级联层的帮助下,我们可以方便的在大型项目中管理样式文件,同时也允许我们将TailwindCSS与那些传统的组件库结合使用。
感谢您的阅读,如果您觉得我的工作对您有所帮助,欢迎为我的仓库添加Star!
如果您在使用的过程中发现任何问题,欢迎提出issue以及提出pr!
以上是在Web工程中使用CSS級聯層的詳細內容。更多資訊請關注PHP中文網其他相關文章!