當咱們遇到一種與本身認知不一樣的方案或者觀點的時候,情感上的喜歡和不喜歡確定是衝在咱們前面的,這是咱們的本能無可厚非。你不喜歡一我的,你就很難注意到他身上的優勢,你喜歡一我的你本能會忽略這我的身上的缺點。css
像最開始我不喜歡 BEM 同樣,我以爲它讓個人 CSS 名稱又長又臭。當我靜下心來去思考它要解決的問題時,我知道本身看待問題是如此的帶有偏見。前端
任何一種方案的提出一定是要解決一個痛點。建議能夠先把我的喜愛滯後,先冷靜的思考這個方案要解決什麼問題。頗有可能這個方案不是很差,只是他沒有解決你的痛點,僅此而已。react
固然本文是想要給你們分享一個觀點,因此還請你們多海涵。😄git
咱們在學習任何一門計算機語言的時候,都是要求命名必定要具備可讀性。好比在原生 js
中,咱們會看到這樣的命名:github
getElementById
getElementsByClassName
getElementsByName
基本上咱們一看就知道這個是要幹什麼的,能夠若是你發現有的人把上面的命名改爲這樣:web
getEId
getECN
getEN
我想你和我同樣第一眼看到這樣的代碼,腦殼裏面會出現一個大大的問號,可能 getEId
大概還能猜到是要幹什麼。可是 getEN
我可能會覺得這個是將中文轉化成英文的方法吧。npm
因此你們約定俗成的是,在命名的時候不要用縮寫,能寫全的都儘可能寫全,即便那樣會增長必定的代碼體積,可是對於項目管理來講是值得推薦的。bootstrap
然而在寫 CSS
的時候,我卻發現,這個條定律彷佛能夠稍微的鬆動一點點。react-native
爲了避免一開始引出結論引發你們的抵觸情緒,我先談談在什麼狀況下咱們會選擇縮寫?設計模式
總結一下,在特定環境中一些出現頻率很是高的詞組,爲了使用方便,咱們會選擇使用縮寫。
仍是拿咱們以前的 JS 環境舉例,像 getElementById
這個方法,在咱們實際開發過程當中,若是你就只用到 10 次左右,我想你並不會考慮去縮寫它的問題。
但是當你發現使用它的頻次達到了成百上千次的時候,即便你的編輯器,在你輸入get
會爲你聯想出getElementById
,你依然會考慮給這個單詞取一個更短的名字。好比像這樣:
function $(id){
return document.getElementById(id);
}
複製代碼
簡單的來講,咱們想要縮寫就是它出現的次數是在是太多了。
在 CSS 這個環境中,對於命名我相信你們聽得最多的就是 語義化 這個詞了。
對於 CSS 語義化 我比較佩服的就是 禪意花園 了。做者就寫了一個 DOM 結構和一些 CSS 類名,而後成百上千的人就能基於他這些 CSS 類名,徹底不須要修改任何的 DOM 結構,就能寫出和做者樣子徹底不同的頁面。這就和換皮膚同樣,結構和樣式的完美分離。
因此這裏仍是要聲明一下,對於語義化的命名,我就很是不推薦使用縮寫。
那麼除了 語義化 還有什麼可選的 CSS 命名方式呢?
這個問題我相信大多數的前端開發者仍是很難回答的。由於在從業多年以後,我發現一直堅信的 CSS 語義化 是致使我寫 CSS 效率低下最根本的緣由。由於命名就是一個須要花費不少時間的東西。具體能夠看看我以前寫的其它 CSS 相關文章 《如何管理 CSS 「內褲」》。
基於 CSS 類名能夠縮寫的這個點,我給到的答案是 ACSS (Atomic CSS),固然這裏說 ACSS 是一種命名方式是極爲不許確的。
若是你目前對於 ACSS 這個理念,表示不太容易接受的話,說明它不能解決你工做中的痛點。就把時間拿去打遊戲或者和妹子聊天吧,後面的內容就能夠忽略了。
ACSS 就如同它的名字來講是原子化CSS。就是把的 CSS 的樣式,拆分到原子級別。
簡單的說,就是一個命名只有一行代碼,一行代碼只表示一個樣式,是否是聽起來特別符合設計模式中的單一指責?
語義化
.main-title{
font-size:24px;
line-height:32px;
color:$color_primary;
font-weight:700;
}
複製代碼
<h2 class="main-title">這是主標題</h2>
複製代碼
ACSS
.fontSize24{ font-size:24px; }
.lineHeight32{ line-height:32px; }
.colorPrimary{ color:$color_primary; }
.fontWeight700{ font-weight:700; }
複製代碼
<h2 class="fontSize24 lineHeight32 colorPrimary fontWeight700">這是主標題</h2>
複製代碼
語義化 Class 和 ACSS Class,被複用的機率基本不在是量級的。就拿上面的例子來講,一個頁面的 .main-title
個數能達到 10 個就已是一個很複雜的頁面了。即便是在整站來看被複用的次數也是有限的。
ACSS 裏面某些類名即便只是在一個頁面被複用的機率,都是遠高於語義化 Class 。好比說 font-size:14px;
在一個項目中被複用上百次是很常見的事情。
因此 ACSS 裏面的類名能夠縮寫的核心在於,ACSS 的類名被複用的次數是在是太多了。
類名不能縮寫有一個最核心反駁點在於,如何定義縮寫的規則。不一樣的人縮寫的習慣是不同的。
首先咱們來看看,知名的一些解決方案對於縮寫是如何定義的。
{
"bg-primary":"background-color:$primary;",
"p-*":"padding: * ;",
"m-*":"margin: * ;";
"d-inline":"display: inline;",
"sm":"small",
"md":"middle",
"col":"column",
"btn":"button",
"w-":"width:*;"
/*...*/
}
複製代碼
{
"bgcolor":"backgroundColor",
"zIndex":"z-index",
"p":"padding",
"m":"margin",
"sm":"small",
"md":"middle"
/*...*/
}
複製代碼
{
"dn":"display:none;",
"b":"font-weight:bold;",
"cl":"clear:both;",
"ovh":"verflow:hidden;",
"ml10":"margin-left:10px;"
}
複製代碼
相信看到這裏,你和我同樣是凌亂的。哪些能夠縮寫啊?是用連字符仍是用下滑線仍是用大小寫啊?
不過咱們零亂的緣由在於咱們不在這些項目組裏面。咱們沒有在 material-ui 的項目裏寫 padding
寫過上百次, 也沒有在 bootstrap 項目裏寫 margin
超過成上千次,更沒有像張老師同樣有超過 10 年的頁面編寫經驗。因此很容易有一些既定的思惟邏輯。
多年的工做經驗,我也維護着這樣一份枚舉映射表。可是我也不得不認可,經過枚舉映射的方式,對於新手來講是很是高的。「汝之蜜糖,乙之砒霜」 就是這樣一個道理。
爲了解決這個問題,我花了不少的時間,進行着嘗試,如下是我目前的結論(基本上是在張老師的邏輯上二次封裝的)。
.db{ display:block; }
;.mb10{ margin-bottom:10px; }
;.mb-10{ margin-bottom:-10px; }
;.w100p{ width:100%; }
;.lh1d5{ line-height:1.5; }
;.c_primary{ color:$primay; }
;.clearfix{ }
;和其它枚舉映射表最大不一樣點在於,個人映射表是經過上面這套命名規則維繫着的。
簡單的說就是記憶上述這套命名規則會比記憶一整套映射表是更容易的。
而且命名規則會減小開發時候疑惑的機率。好比我如今須要一個背景顏色,若是沒有命名規則,我就要去看一下映射表裏面,是相似於 material 的bgcolor
仍是和bootstrap 同樣叫 bg-
。若是有明確的命名規則你就知道確定是叫 bc
由於只取首字母。
有一套命名規則,也比較便於其它的人往裏面添加經常使用的類,而不是根據我的的習慣。固然要說服不一樣的人定義同一套規則也是很難的,對於這個我只能說隨緣吧。
<div class="pt16 pl16 pr16 pb16">
<h3 class="fs16 lh24 fw700 mb4">Atomic css</h3>
<p class="fs12 lh20">Atomic css 的開發體驗真是太好了,速度也是超快。</p>
</div>
複製代碼
<style> .card{ padding: 16px; } .title{ font-size:16px; line-height:24px; font-weight:700; margin-bottom:4px; } .content{ font-size:12px; line-height: 20px; } </style>
<div class="card">
<h3 class="title">Atomic css</h3>
<p class="content">Atomic css 的開發體驗真是太好了,速度也是超快。</p>
</div>
複製代碼
當別人還在糾結這個容器是叫 card
仍是叫 box
的時候,你的代碼已經都寫完了。當你熟練整個命名規則以後,在開發過程當中你會有種,你想要某個樣式,而後你的代碼就已經寫完了的錯覺。這個對於 開發體驗 來講是很是好的。
固然我這個方案也不併完美,仍是有些邊邊角角不能徹底覆蓋,可是基本上平常基礎的樣式是徹底沒有問題的。若是你有比我這個規則更少的命名方案,請和我分享。
若是你有使用 emmet 這個插件,你會發現你甚至連編寫 css 的屬性均可以是使用縮寫的而後 tab 補全的。固然個人規則和 emmet 的有些不一樣,可是不影響實際的使用。
ACSS 這個映射表和設計同窗的原子設計素材有很大的關係,甚至說,應該保持一致。好比說你的項目 A 全部的間距都是基於 5 的倍數開發的,那麼你的這份映射表裏就應該會有:
.mb5{ margin-bottom: 5px; }
.mb10{ margin-bottom: 10px; }
.pt10{ padding-top:10px; }
.pb10{ padding-bottom: 10px; }
/* ... */
複製代碼
你的項目 B 全部的間距都是基於 4 的倍數開發的,那麼你的映射表裏就不該該有上面 5 的倍數的邏輯,而是:
.mb4{ margin-bottom: 4px; }
.mb8{ margin-bottom: 8px; }
.pt4{ padding-top:4px; }
.pb8{ padding-bottom: 8px; }
/* ... */
複製代碼
若是你以爲每次新項目都要去寫這個很麻煩,能夠推薦咱們這邊封裝的 Mixin 庫,less 和 sass 都有 ui-system。
對於瞭解 style-system 的朋友可能會發現,對於間距咱們並無採用相似於 style-system 中倍數邏輯( material-ui 和 bootstrap 是採用的這個邏輯 )。
$margins: [4px,8px,16px,24px,32px];
.mb-1{ margin-bottom:$margins[1]; }
.mb-2{ margin-bottom:$margins[2]; }
.mb-3{ margin-bottom:$margins[3]; }
.mb-4{ margin-bottom:$margins[4]; }
/*...*/
複製代碼
簡單的說,咱們以爲這個很不直觀。而且若是咱們要增長一個 20px
的間距,咱們的整個邏輯就會出現問題以前叫 mb-3
的類名要換成 mb-4
(固然 style-system 的邏輯應該是先定義好設計規範再開發,不該該在後期添加不符合設計規範的間距)。
然而實際每每是計劃趕不上變化,因此還不如直接用數字來的直接簡單粗暴,在開發的還不用思考。mb4
就是 margin-bottom:4px;
不是什麼 margin-bottom:$margins[4]
,你還不知道這個$margins
數組裏面是啥。
本文雖然一直是在圍繞着 CSS 展開的,但其實我想說的實際上是 樣式能夠嘗試考慮 ACSS, 而後 ACSS 的地方能夠嘗試考慮 縮寫 這個點。
樣式寫多了的同窗會知道,經常使用樣式的來來去去也就那幾個,無非就是調整一下他們的排列組合。每次寫這些重複的樣式代碼我就感受本身是在重複造輪子。
隨着 JS 瘋同樣的發展,CSS-in-js 也正發熱發光。但這並不影響咱們這整套邏輯。這裏拿比較有名的 emotion 舉例。
import react from 'react';
import "acss.scss";
render (<h2 className="fs24 lh32 c_primary fw700">{children}</h2>);
複製代碼
import react from 'react';
import { css, jsx } from '@emotion/core';
const primary = 'blue';
render(
<h2 className={css` font-size:24px; line-height:32px; color:${primary}; font-weight:700; `}>這是主標題</h2>
);
複製代碼
咱們甚至用原生的 CSS 就解決了 CSS-in-js 要解決的問題(對於這個點我就不展開了,你們能夠思考如下爲啥CSS-in-js 這樣的理論恰好在組件化風行的時候出現?)。
若是你想在 React-native 中也使用以上的開發體驗。能夠去看一下咱們這邊針對於 React-native 開發的 ACSS 組件 @_nu/react-native-acss。
import React from 'react';
import {Text, View, ImageBackground, Image} from './packages/withAcss';
import mImg1 from "./assets/1.jpg";
import mImg2 from "./assets/2.jpg";
export default function App() {
return (
<View bc="#f5f5f5" pt={100} ph={30} h="100%"> <View mb={16} aic> <Image br={32} w={64} h={64} source={mImg1}/> </View> <Text c="#ffffff" p={16} bc="#4c5fe2" tac mb={16}>Hello world!</Text> <ImageBackground source={mImg2} mb={40}> <View bc="rgba(255,255,255,.8)"> <Text fs={40} lh={100} tac fwb c="#4c5fe2">Hello Again!</Text> </View> </ImageBackground> </View> ); }; 複製代碼
想要實現上面的效果,只須要這幾行代碼,你能夠對比如下以前無論是用styleSheets 仍是用 style-components 的代碼量。就知道這個是多麼的酣暢淋漓。
本文一開始雖然只是想解釋,CSS 類名能夠縮寫這一個點。但到最後仍是難免我介紹了我鍾愛的 ACSS,並王婆賣瓜的推薦了三個工具。畢竟是花了本身不少心力,仍是但願能被更多人看到和使用。
本文觀點屬於經驗總結,走的是務實的邏輯,可能實現方案看起來有點醜陋。
可是不能解決問題,優雅又有何用呢?有什麼疏漏,還請你們海涵,能夠給我留言指正。
更新於 2019/10/22
名稱 | NPM | github | CDN |
---|---|---|---|
@_nu/css-acss |
![]() |
![]() |
![]() |
講了這麼多,感受都只是空談理論。這邊我多年的使用經驗,總結的一個 ACSS 的 npm 類庫 @_nu/css-acss
供你們使用。
對於 ACSS, bootstrap, material-ui, github ... 都有相關的 類庫,而後整個 ** 類庫** 最完善的屬於 tailwindcss。固然他們都是基於 style-system
理論建立的。上手成本相對較高,且每每須要設計師的介入。
和這些項目相比,我這邊的方案,優勢在於簡單和極致的 CSS 開發體驗。簡單到整個邏輯只落點在命名規則,看完文檔 5 分鐘就會用,甚至徹底理解全部的邏輯。極致的 CSS 開發體驗,體如今熟悉這套規則以後,你會開始懷疑,你的手指速度慢於你思考 CSS 的速度。
固然爲了追求簡單和開發體驗這也是缺點,就是不夠完善,沒有處理相似 hover
,focus
... 等中間態,也沒有添加任何自定義的響應點。這部分須要你們基於本身項目和 命名規則 自由擴展。