前言
隨著項(xiàng)目越來(lái)越大,你是不是覺(jué)得項(xiàng)目的 CSS 越來(lái)越難維護(hù),常用的屬性就是那么幾個(gè),來(lái)來(lái)回回的寫(xiě),搞得你也很煩,如果是那么趕緊嘗試用 ACSS 方案來(lái)解決你的問(wèn)題吧,如果否,那說(shuō)明你經(jīng)歷的項(xiàng)目還不夠多不夠大,這時(shí)候你要繼續(xù)努力搬磚。
如果你不了解什么是 ACSS 的話,可以參考下我之前的教程: CSS 架構(gòu)之 ACSS 。如果你想了解項(xiàng)目組織樣式的演進(jìn)歷史,強(qiáng)烈建議你研讀 TailwindCSS 作者 2017 年寫(xiě)的把 CSS 分為五個(gè)階段的一篇文章:
讀完你會(huì)徹底理解「為什么傳統(tǒng)的 “語(yǔ)義化類名” 是 CSS 難以維護(hù)的原因」,詳述了 CSS 的五個(gè)階段,寫(xiě)的很棒,多看幾遍。
回到 ACSS,ACSS 中目前最流行的框架就是我們文章的主角 TailwindCSS。

但是,如果在項(xiàng)目中使用建議你使用 Windi CSS。

它們是一種繼承關(guān)系,如何 TailwindCSS 是父類,那么 Windi CSS 就是子類。
當(dāng)然你也可以認(rèn)為 TailwindCSS 是 ES5,Windi CSS 是 JavaScript ,Windi CSS 在 TailwindCSS 的基礎(chǔ)上進(jìn)行了擴(kuò)展,還包括 ES6+ 的部分,這個(gè)我們留在 TailwindCSS 章節(jié)講。
不過(guò),你可以放心學(xué)習(xí) TailwindCSS,它的語(yǔ)法在 Windi CSS,完全是可用的。
搭建一個(gè)環(huán)境
Windi CSS 如何安裝結(jié)合其他框架使用,在 安裝 章節(jié)非常清楚。
而且我們也沒(méi)必要糾結(jié) WIndiCSS 的大家過(guò)程,這些框架都會(huì)幫我們處理的,這里我們簡(jiǎn)單的搭建一個(gè)項(xiàng)目,方便接下里的演示:
? mkdir WindiCSS-study && cd WindiCSS-study
? WindiCSS-study npm init -y
? WindiCSS-study npm install windicss -D
在 package.json 文件中的 script 字段,我們新增如下字段:
"scripts": {
"windicss:help": "windicss --help",
"windicss:init": "windicss --init . --compile",
"windicss:build": "windicss ./index.html -to windi-acss.css"
},
接下來(lái)可以運(yùn)行命令:
npm run windicss:init
項(xiàng)目根目錄將會(huì)新增三個(gè)文件:
├── index.html
├── index.windi.html
├── package.json
└── windi.css
查看 index.html 的文件內(nèi)容大致如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WindiCSS-study</title>
<link rel="stylesheet" href="windi.css">
</head>
<body class="bg-gray-100">
<div class="container mx-auto flex flex-col justify-center items-center h-screen">
<div class="lg:flex shadow rounded-lg">
<div class="bg-blue-500 rounded-t-lg lg:rounded-tr-none lg:rounded-l-lg lg:w-4/12 py-4 h-full flex flex-col justify-center">
<div class="text-center tracking-wide">
<div class="text-white font-bold text-8xl lg:text-4xl">24</div>
<div class="text-white font-normal text-4xl pt-4 lg:pt-0 lg:text-2xl">Sept</div>
</div>
</div>
<div class="w-full px-1 bg-white py-5 lg:px-2 lg:py-2 tracking-wide">
<div class="flex flex-row lg:justify-start justify-center">
<div class="text-gray-700 font-light text-sm text-center lg:text-left px-2">
1:30 PM
</div>
<div class="text-gray-700 font-light text-sm text-center lg:text-left px-2">
Organiser : IHC
</div>
</div>
<div class="text-gray-700 text-xl pb-1 text-center lg:text-left px-2">
Hello WindiCSS
</div>
<div class="text-gray-800 font-light text-sm pt-1 text-center lg:text-left px-2">
A-142/1, A-142, Ganesh Nagar, Tilak Nagar, New Delhi, 110018
</div>
</div>
<div class="flex flex-row items-center w-full lg:w-1/3 bg-white lg:justify-end justify-center px-2 py-4 lg:px-0 rounded-lg">
<span class="tracking-wider text-gray-600 cursor-pointer bg-gray-100 hover:bg-gray-200 px-4 py-2 text-sm rounded-lg leading-loose mx-2">
Going
</span>
</div>
</div>
</div>
</body>
</html>
HTML 層面全部都是 ACSS 的寫(xiě)法,同時(shí)注意文件開(kāi)頭應(yīng)用的樣式:
<link rel="stylesheet" href="windi.css">
我們對(duì)其重新命名:windi.css => windi-acss.css。
現(xiàn)在我們運(yùn)行命令:
# "windicss ./index.html -to windi-acss.css"
# 使用 -o 參數(shù)指定生成 css 文件的名稱, -t 參數(shù)指定是否添加預(yù)檢樣式 (基本樣式)。
npm run windicss:build
這個(gè)命令會(huì)根據(jù) HTML 的類名生成對(duì)應(yīng)的 CSS,這是項(xiàng)目的目錄結(jié)構(gòu)為:
.
├── index.html
├── index.windi.html
├── package.json
├── windi-acss.css
└── windi.css
多了個(gè)文件 windi-acss.css 其內(nèi)容為:
*, ::before, ::after {
-webkit-box-sizing: border-box;
box-sizing: border-box;
border-width: 0;
border-style: solid;
border-color: #e5e7eb;
}
* {
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgba(59, 130, 246, 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
}
:root {
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
}
:-moz-focusring {
outline: 1px dotted ButtonText;
}
:-moz-ui-invalid {
box-shadow: none;
}
::moz-focus-inner {
border-style: none;
padding: 0;
}
::-webkit-inner-spin-button, ::-webkit-outer-spin-button {
height: auto;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-file-upload-button {
-webkit-appearance: button;
font: inherit;
}
[type='search'] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
}
body {
margin: 0;
font-family: inherit;
line-height: inherit;
}
html {
-webkit-text-size-adjust: 100%;
font-family: ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
line-height: 1.5;
}
.container {
width: 100%;
}
@media (min-width: 640px) {
.container {
max-width: 640px;
}
}
@media (min-width: 768px) {
.container {
max-width: 768px;
}
}
@media (min-width: 1024px) {
.container {
max-width: 1024px;
}
}
@media (min-width: 1280px) {
.container {
max-width: 1280px;
}
}
@media (min-width: 1536px) {
.container {
max-width: 1536px;
}
}
.bg-gray-100 {
--tw-bg-opacity: 1;
background-color: rgba(243, 244, 246, var(--tw-bg-opacity));
}
.bg-blue-500 {
--tw-bg-opacity: 1;
background-color: rgba(59, 130, 246, var(--tw-bg-opacity));
}
.bg-white {
--tw-bg-opacity: 1;
background-color: rgba(255, 255, 255, var(--tw-bg-opacity));
}
.hover\:bg-gray-200:hover {
--tw-bg-opacity: 1;
background-color: rgba(229, 231, 235, var(--tw-bg-opacity));
}
.rounded-lg {
border-radius: 0.5rem;
}
.rounded-t-lg {
border-top-left-radius: 0.5rem;
border-top-right-radius: 0.5rem;
}
.cursor-pointer {
cursor: pointer;
}
.flex {
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
.flex-row {
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
-webkit-flex-direction: row;
flex-direction: row;
}
.flex-col {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
-webkit-flex-direction: column;
flex-direction: column;
}
.items-center {
-webkit-box-align: center;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
}
.justify-center {
-webkit-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
.font-light {
font-weight: 300;
}
.h-screen {
height: 100vh;
}
.h-full {
height: 100%;
}
.text-8xl {
font-size: 6rem;
line-height: 1;
}
.text-4xl {
font-size: 2.25rem;
line-height: 2.5rem;
}
.text-sm {
font-size: 0.875rem;
line-height: 1.25rem;
}
.text-xl {
font-size: 1.25rem;
line-height: 1.75rem;
}
.leading-loose {
line-height: 2;
}
.mx-auto {
margin-left: auto;
margin-right: auto;
}
.mx-2 {
margin-left: 0.5rem;
margin-right: 0.5rem;
}
.py-4 {
padding-top: 1rem;
padding-bottom: 1rem;
}
.px-1 {
padding-left: 0.25rem;
padding-right: 0.25rem;
}
.py-5 {
padding-top: 1.25rem;
padding-bottom: 1.25rem;
}
.px-2 {
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.px-4 {
padding-left: 1rem;
padding-right: 1rem;
}
.py-2 {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
.pt-4 {
padding-top: 1rem;
}
.pb-1 {
padding-bottom: 0.25rem;
}
.pt-1 {
padding-top: 0.25rem;
}
.shadow {
--tw-shadow-color: 0, 0, 0;
--tw-shadow: 0 1px 3px 0 rgba(var(--tw-shadow-color), 0.1), 0 1px 2px 0 rgba(var(--tw-shadow-color), 0.06);
-webkit-box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.text-center {
text-align: center;
}
.text-white {
--tw-text-opacity: 1;
color: rgba(255, 255, 255, var(--tw-text-opacity));
}
.text-gray-700 {
--tw-text-opacity: 1;
color: rgba(55, 65, 81, var(--tw-text-opacity));
}
.text-gray-800 {
--tw-text-opacity: 1;
color: rgba(31, 41, 55, var(--tw-text-opacity));
}
.text-gray-600 {
--tw-text-opacity: 1;
color: rgba(75, 85, 99, var(--tw-text-opacity));
}
.tracking-wide {
letter-spacing: 0.025em;
}
.tracking-wider {
letter-spacing: 0.05em;
}
.w-full {
width: 100%;
}
@media (min-width: 1024px) {
.lg\:rounded-l-lg {
border-top-left-radius: 0.5rem;
border-bottom-left-radius: 0.5rem;
}
.lg\:rounded-tr-none {
border-top-right-radius: 0px;
}
.lg\:flex {
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
.lg\:justify-start {
-webkit-box-pack: start;
-ms-flex-pack: start;
-webkit-justify-content: flex-start;
justify-content: flex-start;
}
.lg\:justify-end {
-webkit-box-pack: end;
-ms-flex-pack: end;
-webkit-justify-content: flex-end;
justify-content: flex-end;
}
.lg\:text-4xl {
font-size: 2.25rem;
line-height: 2.5rem;
}
.lg\:text-2xl {
font-size: 1.5rem;
line-height: 2rem;
}
.lg\:px-2 {
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.lg\:py-2 {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
.lg\:px-0 {
padding-left: 0px;
padding-right: 0px;
}
.lg\:pt-0 {
padding-top: 0px;
}
.lg\:text-left {
text-align: left;
}
.lg\:w-4\/12 {
width: 33.333333%;
}
.lg\:w-1\/3 {
width: 33.333333%;
}
}
現(xiàn)在可以在瀏覽器打開(kāi) index.html 文件了,看到效果是下面這樣:

優(yōu)化項(xiàng)目
為了更好的演示和提升開(kāi)發(fā)體驗(yàn),我們需要對(duì)項(xiàng)目進(jìn)行一些調(diào)整。
首先,就是增加熱更新:
"scripts": {
"windicss:help": "windicss --help",
"windicss:init": "windicss --init . --compile",
"windicss:build": "windicss ./src/index.html -mto ./src/windi-minify.css",
"windicss:watch": "windicss ./src/index.html -dto ./src/windi-acss.css"
},
windicss:watch 命令添加了 -d 參數(shù),開(kāi)啟開(kāi)發(fā)環(huán)境下的熱更新功能。
目錄調(diào)整為如下結(jié)構(gòu):
.
├── package.json
└── src
├── index.html
└── windi-acss.css
index.html 的內(nèi)容替換為:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WindiCSS-study</title>
<link rel="stylesheet" href="windi-acss.css">
</head>
<body class="bg-gray-100">
<section class="flex justify-center items-center min-h-screen text-pink-600 text-5xl">Hello WindiCSS!</section>
</body>
</html>
npm run windicss:watch 之后,打開(kāi)瀏覽器看到:
