盡量減少代碼重復(fù)
在軟件開發(fā)中,保持代碼的DRY 和可維護性是最大的挑戰(zhàn)之一,而這句話對CSS 也是適用的。在實踐中,代碼可維護性的最大要素是盡量減少改動時要編輯的地方。舉例來說,如果在放大一個按鈕時需要在一堆規(guī)則中進行10 處修改,那就很可能會漏改其中某處,當你在給別人善后時更是如此。即使這些要修改的地方很明顯,或者最終可以找齊它們,但你還是浪費了時間,原本可以利用這些時間來做點更有意義的事情。
而且,這還不僅僅是后期修改的問題。靈活的CSS 通常更容易擴展:在寫出基礎(chǔ)樣式之后,只用極少的代碼就可以擴展出不同的變體,因為只需覆蓋一些變量就可以了。讓我們來看一個例子。
先來看看下面這段CSS,它給按鈕添加了一些效果(參見圖1-4):
padding: 6px 16px;
border: 1px solid #446d88;
background: #58a linear-gradient(#77a0bb, #58a);
border-radius: 4px;
box-shadow: 0 1px 5px gray;
color: white;
text-shadow: 0 -1px 1px #335166;
font-size: 20px;
line-height: 30px;

這段代碼在可維護性方面存在一些問題,我們來一一修復(fù)。最軟的杮子應(yīng)該是跟字體尺寸相關(guān)的部分了。如果我們決定改變字號1①(可能是為了生成一個更大、更重要的按鈕),就得同時調(diào)整行高,因為這兩個屬性都寫成了絕對值。更麻煩的是,行高并沒有反映出它跟字號的關(guān)系,因此我們還得做些算術(shù),算出字號改變之后的行高該是多少。當某些值相互依賴時,應(yīng)該把它們的相互關(guān)系用代碼表達出來。在這個例子中,行高是字號的1.5 倍。因此,把代碼改成下面這樣會更易維護:
font-size: 20px;
line-height: 1.5;
① 在本書中,“字號”是對字體尺寸(font-size)的俗稱?!g者注
既然跨出了這一步,我們?yōu)槭裁催€把字號定為絕對長度值呢?沒錯,絕對值很容易掌控,但每當你想要修改它們的時候,它們都會回頭反咬你一口。比如說,如果我們決定把父級的字號加大,就不得不修改每一處使用絕對值作為字體尺寸的樣式。如果改用百分比或em 單位就好多了:
font-size: 125%; /* 假設(shè)父級的字號是 16px */
line-height: 1.5;

現(xiàn)在,如果我們改變父級的字號,按鈕的尺寸就會隨之變化。但是,它看起來很不協(xié)調(diào)(參見圖1-5),因為所有其他效果都是為一個小按鈕設(shè)計的,并沒有跟著縮放。如果我們把這些長度值都改成em 單位,那這些效果的值就都變成可縮放的了,而且是依賴字號進行縮放1①。按照這種方法,我們就可以在一處控制按鈕的所有尺寸樣式了:
padding: .3em .8em;
border: 1px solid #446d88;
background: #58a linear-gradient(#77a0bb, #58a);
border-radius: .2em;
box-shadow: 0 .05em .25em gray;
color: white;
text-shadow: 0 -.05em .05em #335166;
font-size: 125%;
line-height: 1.5;
① 這里我們希望字號和其他尺寸能夠跟父級的字號建立關(guān)聯(lián),因此采用了em 單位。但在某些情況下,你可能希望這些尺寸是和根級字號(即 元素的字號)相關(guān)聯(lián)的,此時使用em 可能會導(dǎo)致復(fù)雜的計算。在這種情況下,你可以使用rem 單位。在CSS 中,相關(guān)性是一個很重要的特性,但你得想清楚到底哪些東西是真正相關(guān)的。
現(xiàn)在我們的大號按鈕看起來更像是一個原按鈕的等比例放大版本了(參見圖1-6)。請注意還有一些長度值是絕對值。此時就需要重新審視到底哪些效果應(yīng)該跟著按鈕一起放大,而哪些效果是保持不變的。比如在這個例子中,我們希望按鈕的邊框粗細保持在1px,不受按鈕尺寸的影響。

不過,讓按鈕變大或變小并不是我們唯一想要改動的地方。顏色是另一個重要的變數(shù)。比如,假設(shè)我們要創(chuàng)建一個紅色的取消按鈕,或者一個綠色的確定按鈕,該怎么做呢?眼下,我們可能需要覆蓋四條聲明(bordercolor、background、box-shadow 和text-shadow),而且還有另一大難題:要根據(jù)按鈕的亮面和暗面相對于主色調(diào)#58a 變亮和變暗的程度來分別推導(dǎo)出其他顏色各自的亮色和暗色版本。此外,若我們想把按鈕放在一個非白色的背景之上呢?顯然使用灰色( gray)作投影只適用于純白背景的情況。
其實只要把半透明的黑色或白色疊加在主色調(diào)上,即可產(chǎn)生主色調(diào)的亮色和暗色變體,這樣就能簡單地化解這個難題了:
padding: .3em .8em;
border: 1px solid rgba(0,0,0,.1);
background: #58a linear-gradient(hsla(0,0%,100%,.2),
transparent);
border-radius: .2em;
box-shadow: 0 .05em .25em rgba(0,0,0,.5);
color: white;
text-shadow: 0 -.05em .05em rgba(0,0,0,.5);
font-size: 125%;
line-height: 1.5;
小提示:推薦使用HSLA 而不是RGBA 來產(chǎn)生半透明的白色,因為它的字符長度更短,敲起來也更快。這歸功于它的重復(fù)度更低。
現(xiàn)在我們只要覆蓋background-color 屬性,就可以得到不同顏色版本的按鈕了(參見圖1-7):
button.cancel {
background-color: #c00;
}
button.ok {
background-color: #6b0;
}

我們的按鈕現(xiàn)在已經(jīng)非常靈活了。不過,這個例子并沒有涵蓋所有能讓代碼變得更DRY 的方法。你會在下面幾節(jié)中發(fā)現(xiàn)更多的技巧。
1. 代碼易維護vs. 代碼量少
有時候,代碼易維護和代碼量少不可兼得。比如在上面的例子中,我們最終采用的代碼甚至比一開始的版本略長。來看看下面的代碼片斷,我們要為一個元素添加一道10px 寬的邊框,但左側(cè)不加邊框。
border-width: 10px 10px 10px 0;
只要這一條聲明就可以搞定了,但如果日后要改動邊框的寬度,你需要同時改三個地方。如果把它拆成兩條聲明的話,改起來就容易多了,而且可讀性或許更好一些:
border-width: 10px;
border-left-width: 0;
2. currentColor
在CSS 顏色(第三版)(http://w3.org/TR/css3-color)規(guī)范中,增加了很多新的顏色關(guān)鍵字,比如lightgoldenrodyellow 等,其實并不是很常用。但是,我們還得到了一個特殊的顏色關(guān)鍵字currentColor,它是從SVG 那里借鑒來的。這個關(guān)鍵字并沒有綁定到一個固定的顏色值,而是一直被解析為color。實際上,這個特性讓它成為了CSS 中有史以來的第一個變量1①。雖然功能很有限,但它真的是個變量。
① 可能有人會爭論說em 單位才是CSS 中的第一個變量,因為它引用了font-size 的值。其實大多數(shù)百分比數(shù)值也扮演了類似的角色,只不過它們的工作方式不是很起眼。
舉個例子,假設(shè)我們想讓所有的水平分割線(所有元素)自動與文本的顏色保持一致。有了currentColor 之后,我們只需要這樣寫:
hr {
height: .5em;
background: currentColor;
}
你可能已經(jīng)注意到了,很多已有的屬性也具有類似的行為。舉例來說,如果你沒有給邊框指定顏色,它就會自動地從文本顏色那里得到顏色。這是因為currentColor 本身就是很多CSS 顏色屬性的初始值,比如border-color 和outline-color,以及text-shadow 和box-shadow 的顏色值,等等。
未來,我們在原生CSS 中擁有處理顏色的函數(shù)后,currentColor 就會變得更加有用,因為我們可以用這些函數(shù)來產(chǎn)生其各種深淺明暗的變體。
3. 繼承
盡管絕大多數(shù)開發(fā)者都知道有inherit 這個關(guān)鍵字,但還是很容易遺忘它。inherit 可以用在任何CSS 屬性中,而且它總是綁定到父元素的計算值(對偽元素來說,則會取生成該偽元素的宿主元素)。舉例來說,要把表單元素的字體設(shè)定為與頁面的其他部分相同,你并不需要重復(fù)指定字體屬性,只需利用inherit 的特性即可:
input, select, button { font: inherit; }
與此類似,要把超鏈接的顏色設(shè)定為與頁面中其他文本相同,還是要用
inherit:
a { color: inherit; }
這個inherit 關(guān)鍵字對于背景色同樣非常有用。舉個例子,在創(chuàng)建提示框的時候,你可能希望它的小箭頭能夠自動繼承背景和邊框的樣式(參見圖1-8):
.callout { position: relative; }
.callout::before {
content: "";
position: absolute;
top: -.4em; left: 1em;
padding: .35em;
background: inherit;
border: inherit;
border-right: 0;
border-bottom: 0;
transform: rotate(45deg);
}

相信你的眼睛,而不是數(shù)字
人的眼睛并不是一臺完美的輸入設(shè)備。有時候精準的尺度看起來并不精準,而我們的設(shè)計需要順應(yīng)這種偏差。舉一個在視覺設(shè)計領(lǐng)域廣為人知的例子吧,我們的眼睛在看到一個完美垂直居中的物體時,會感覺它并不居中。實際上,我們應(yīng)該把這個物體從幾何學(xué)的中心點再稍微向上挪一點,才能取得理想的視覺效果。來親身體驗一下這件怪事吧(參見圖1-9)。

與此類似,在字體設(shè)計領(lǐng)域廣為人知的是,圓形的字形(比如0)與矩形字形相比,需要稍微放大一些,因為我們傾向于把圓形感知得比其實際尺寸更小一些。你也可以在圖1-10 中體驗一下。

這些視覺上的錯覺在任何形式的視覺設(shè)計中都普遍存在,需要我們有針對性地進行調(diào)整。一個非常常見的例子是給一個文本容器設(shè)置內(nèi)邊距。不論內(nèi)容文本有多長,是一個單詞還是幾個段落,這個問題都會出現(xiàn)。假如我們給容器的四邊指定相同的內(nèi)邊距,則實際效果看起來并不相等,就像圖1-11顯示的那樣。原因在于,字母的形狀在兩端都比較整齊,而頂部和底部則往往參差不齊,從而導(dǎo)致你的眼睛把這些參差不齊的空缺部分感知為多出來的內(nèi)邊距。因此,如果我們希望四邊的內(nèi)邊距看起來是基本一致的,就需要減少頂部和底部的內(nèi)邊距。你可以在圖1-12 中看出這種差異。


關(guān)于響應(yīng)式網(wǎng)頁設(shè)計
響應(yīng)式網(wǎng)頁設(shè)計(Responsive Web Design,RWD)在最近幾年風(fēng)靡一時。但是,人們大多只是在不停念叨網(wǎng)頁的“響應(yīng)式”是多么重要,而極少有人去深入探討怎樣才能做好響應(yīng)式設(shè)計。
比較常見的實踐是用多種分辨率來測試一個網(wǎng)站,然后添加越來越多的媒體查詢(Media Query)規(guī)則來修補網(wǎng)站在這些分辨率下出現(xiàn)的問題。然而對于今后的CSS 改動來說,每個媒體查詢都會增加成本,而這種成本是不應(yīng)輕易上升的。未來每次對CSS 代碼的修改都要求我們逐一核對這些媒體查詢是否需要配合修改,甚至可能要求我們反過來修改這些媒體查詢的設(shè)置。這一點常常被我們忽略,后患無窮。你添加的媒體查詢越多,你的CSS代碼就會變得越來越經(jīng)不起折騰。
這并不是說媒體查詢是一種不良實踐。只要用對了,它就是利器。但是,你只應(yīng)該把它作為最后的手段。比如你想把網(wǎng)站做得彈性靈活,但其他嘗試全都失敗了;或者我們希望在較大或較小的視口下完全改變網(wǎng)站的設(shè)計形態(tài)(譬如,把側(cè)欄改成水平布局)。我這么說的原因在于,媒體查詢不能以一種連續(xù)的方式來修復(fù)問題。它們的工作原理基于某幾個特定的階梯(亦稱“斷點”),如果大部分樣式代碼并不是以彈性的方式來編寫的,那么媒體查詢能做的只是修補某個特定分辨率下的特定問題——這本質(zhì)上只是把灰塵掃到地毯下面而已。
當然,有一點上面并沒有提到,媒體查詢的斷點不應(yīng)該由具體的設(shè)備來決定,而應(yīng)該根據(jù)設(shè)計自身來決定。這不僅是因為我們的網(wǎng)站需要面向的設(shè)備太多了(尤其是考慮到未來的設(shè)備時),還因為一個網(wǎng)站在桌面端可能會以任意尺寸的窗口來顯示。如果你有信心自己的設(shè)計在任何可能出現(xiàn)的視口尺寸下都能良好工作,誰關(guān)心這些設(shè)備的分辨率具體是多少呢?
遵從“盡量減少代碼重復(fù)”所描述的原則對此也是有幫助的,因為你不需要去覆蓋媒體查詢里同樣數(shù)量的聲明。這在本質(zhì)上減輕了它們所產(chǎn)生的維護成本。
下面還有一些建議,可能會幫你避免不必要的媒體查詢。
?■ 使用百分比長度來取代固定長度。如果實在做不到這一點,也應(yīng)該嘗試使用與視口相關(guān)的單位(vw、vh、vmin 和vmax),它們的值解析為視口寬度或高度的百分比。
?■ 當你需要在較大分辨率下得到固定寬度時,使用max-width 而不是width,因為它可以適應(yīng)較小的分辨率,而無需使用媒體查詢。
■? 不要忘記為替換元素(比如img、object、video、iframe 等)設(shè)置一個max-width,值為100%。
■? 假如背景圖片需要完整地鋪滿一個容器,不管容器的尺寸如何變化,background-size: cover 這個屬性都可以做到。但是,我們也要時刻牢記——帶寬并不是無限的,因此在移動網(wǎng)頁中通過CSS 把一張大圖縮小顯示往往是不太明智的。
■? 當圖片(或其他元素)以行列式進行布局時,讓視口的寬度來決定列的數(shù)量。彈性盒布局(即Flexbox)或者display: inline-block加上常規(guī)的文本折行行為,都可以實現(xiàn)這一點。
?■ 在使用多列文本時,指定column-width(列寬)而不是指定column-count(列數(shù)),這樣它就可以在較小的屏幕上自動顯示為單列布局。
總的來說,我們的思路是盡最大努力實現(xiàn)彈性可伸縮的布局,并在媒體查詢的各個斷點區(qū)間內(nèi)指定相應(yīng)的尺寸。當網(wǎng)頁本身的設(shè)計足夠靈活時,讓它變成響應(yīng)式應(yīng)該只需要用到一些簡短的媒體查詢代碼。Basecamp 的設(shè)計師在2010 年寫到過這種非常規(guī)情況。
“結(jié)果我們發(fā)現(xiàn),想讓網(wǎng)頁在一堆不同的設(shè)備上合理展示,只需要在最終產(chǎn)品上添加一點CSS 媒體查詢就可以了。這件事情之所以這么簡單,關(guān)鍵在于我們的布局原本就是彈性可伸縮的。因此,優(yōu)化網(wǎng)頁在小屏幕上的表現(xiàn),其實只意味著把一些外邊距收攏到最小程度,然后把因為屏幕太窄而無法顯示成雙列的側(cè)欄調(diào)整為單列布局而已?!?/p>
——在Iterations 中實踐響應(yīng)式設(shè)計(http://signalvnoise.com/posts/2661-experimenting-with-responsive-design-in-iterations)
如果你發(fā)現(xiàn)自己需要一大堆媒體查詢才能讓設(shè)計適應(yīng)大大小小的屏幕,那么不妨后退一步,重新審視你的代碼結(jié)構(gòu)。因為在所有的情況下,響應(yīng)式都不是唯一需要考慮的問題。
小提示:不妨考慮在你的媒體查詢中使用em 單位取代像素單位。這能讓文本縮放在必要時觸發(fā)布局的變化。
合理使用簡寫
你可能知道,以下兩行CSS 代碼并不是等價的:
background: rebeccapurple;
background-color: rebeccapurple;
前者是簡寫,它可以確保你得到rebeccapurple 純色背景;但如果你用的是展開式的單個屬性(background-color),那這個元素的背景最終有可能會顯示為一個粉色的漸變圖案、一張貓的圖片或其他任何東西,因為同時可能會有一條background-image 聲明在起作用。在使用展開式屬性的寫法時,通常會遇到這樣的問題:展開式寫法并不會幫助你清空所有相關(guān)的其他屬性,從而可能會干擾你想要達到的效果。
當然,你可以把所有的展開式屬性全都設(shè)置一遍,然后收工,但你可能會漏掉幾個;又或者,CSS 工作組可能會在未來引入更多的展開式屬性,那時你的代碼就無法完全覆蓋它們了。不要害怕使用簡寫屬性。合理使用簡寫是一種良好的防衛(wèi)性編碼方式,可以抵御未來的風(fēng)險。當然,如果我們要明確地去覆蓋某個具體的展開式屬性并保留其他相關(guān)樣式,那就需要用展開式屬性,就像我們在“盡量減少代碼重復(fù)”一節(jié)中為了得到按鈕的其他顏色版本所做的那樣。
展開式屬性與簡寫屬性的配合使用也是非常有用的,可以讓代碼更加DRY。對于那些接受一個用逗號分隔的列表的屬性(比如background),尤其如此。下面的例子可以很好地解釋這一點:
background: url(tr.png) no-repeat top right / 2em 2em,
url(br.png) no-repeat bottom right / 2em 2em,
url(bl.png) no-repeat bottom left / 2em 2em;
請注意background-size 和background-repeat 的值被重復(fù)了三遍,盡管每層背景的這兩個值確實是相同的。其實我們可以從CSS 的“列表擴散規(guī)則”那里得到好處。它的意思是說,如果只為某個屬性提供一個值,那它就會擴散并應(yīng)用到列表中的每一項。因此,我們可以把這些重復(fù)的值從簡寫屬性中抽出來寫成一個展開式屬性:
background: url(tr.png) top right,
url(br.png) bottom right,
url(bl.png) bottom left;
background-size: 2em 2em;
background-repeat: no-repeat;
現(xiàn)在,我們只需要在一處修改,就可以改變所有的background-size和background-repeat了。你會發(fā)現(xiàn)這個技巧在本書中的使用非常普遍。
我應(yīng)該使用預(yù)處理器嗎
你很可能聽說過像Stylus(http://stylus-lang.com/)、Sass(http://sass-lang.com/)或LESS(http://lesscss.org/)這樣的CSS預(yù)處理器。它們?yōu)镃SS的編寫提供提供了一些便利,比如變量、mixin、函數(shù)、規(guī)則嵌套、顏色處理等。
如果使用得當,它們在大型項目中可以讓代碼更加靈活,而CSS自身在這方面確實有很大局限。只要我們在代碼健壯性、靈活性和DRY方面有追求,就會感受到CSS在這方面的局限。不過,預(yù)處理器也不是完美無缺的。
?■ ?CSS的文件體積和復(fù)雜度可能會失控。即使是簡潔明了的源代碼,在經(jīng)過編譯之后也可能會變成一頭從天而降的巨獸。
?■? 調(diào)試難度會增加,因為你在開發(fā)工具中看到的CSS代碼并不是你寫的源代碼。不過這個問題已經(jīng)大大好轉(zhuǎn)了,因為已經(jīng)有越來越多的調(diào)試工具開始支持SourceMap。SourceMap是一種非??岬男录夹g(shù),正是為了解決這個痛點而生的,它會告訴瀏覽器哪些編譯生成的CSS代碼對應(yīng)哪些預(yù)處理器CSS代碼,精確到行號。
■?? 預(yù)處理器在開發(fā)過程中引入了一定程度的延時。盡管它們通常很快,但仍然需要差不多一秒鐘的時間來把你的源代碼編譯成CSS,而你不得不等待這段時間才能預(yù)覽到代碼的效果。
?■?? 每次抽象都必然會帶來更高的學(xué)習(xí)成本,每當有新人加入到我們的代碼庫中,這個問題都會重演。他要么已經(jīng)對我們選擇的這門預(yù)處理器“方言”很熟悉,要么得從頭學(xué)。這意味著我們要么強制協(xié)作者接受我們的選擇,要么花費額外的時間來培訓(xùn),而這兩者都不是我們想要的。
?■ ??另外,別忘了還有抽象泄漏法則:“所有重大的抽象機制在某種程度上都存在泄漏的情況?!鳖A(yù)處理器是由人類寫出來的,就像所有由人類寫出來的大型程序一樣,它們有它們自己的bug。這些bug 可能會潛伏很久,因為我們很少會懷疑預(yù)處理器的某個bug 才是我們CSS 出錯的幕后元兇。
小 花 絮 怪異的簡寫語法
你可能已經(jīng)注意到前面那個背景屬性簡寫的例子了:在background簡寫屬性中指定background-size時,需要同時提供一個background-position值(哪怕它的值就是其初始值也需要寫出來),而且還要使用一個斜杠(/)作為分隔。為什么有些簡寫的語法如此怪異?
這通常都是為了消除歧義。在這個例子中,top right顯然是background-position,而2em 2em是background-size,不管它們的順序如何。但是,請設(shè)想一下50% 50%這樣的值,它到底是background-size還是background-position呢?當你在使用展開式屬性時,CSS解析器明白你的意圖;而當你使用簡寫屬性時,解析器需要在沒有屬性名提示的情況下弄清楚50% 50%到底指什么。這就是需要引入斜杠的原因。
對絕大多數(shù)的簡寫屬性來說,并沒有這樣的歧義問題,因而簡寫屬性的多個值往往可以隨意排列。不過,我還是建議你養(yǎng)成隨手查閱語法的好習(xí)慣,以免犯錯。如果你對正則表達式以及規(guī)范的語法描述方式(grammar)很熟悉的話,不妨直接在相關(guān)規(guī)范中查詢語法描述。如果要確定某個屬性的值是否有明確的順序要求,這可能是最快的方式。
除了上面列出的這些問題,預(yù)處理器還可能導(dǎo)致這種風(fēng)險:網(wǎng)站開發(fā)者可能會不自覺地“依賴”和“濫用”。因為在某些時候,預(yù)處理器并不必要。比如在小型項目中;或者在未來,說不定預(yù)處理器最受歡迎的那些特性都被加入了原生CSS 中。很驚訝嗎?沒錯,很多受預(yù)處理器啟發(fā)的特性都已經(jīng)以各種方式融入到原生CSS 中了。
?■?? 有一份關(guān)于(跟變量類似的)自定義屬性的草案,叫作CSS 自定義屬性暨層疊式變量(http://w3.org/TR/css-variables-1)。
■?? CSS 值與單位(第三版)中的calc() 函數(shù),不僅在處理運算時非常強大,而且已經(jīng)得到了廣泛的支持,當下可用。
?■?? CSS顏色(第四版)(http://dev.w3.org/csswg/css-color)引入的color()函數(shù)會提供顏色運算方法。
?■?? 關(guān)于嵌套,CSS 工作組內(nèi)部正在進行一些正式的討論,甚至以前還有過一份相關(guān)的草案(ED)。
請注意,這些原生特性通常比預(yù)處理器提供的版本要強大得多,因為它們是動態(tài)的1①。舉個例子,預(yù)處理器完全不知道如何完成100% - 50px 這樣的計算,因為在頁面真正被渲染之前,百分比值是無法解析的。但是,原生CSS 的calc() 在計算這樣的表達式時沒有任何壓力。與此類似,下面這樣的變量玩法在預(yù)處理器中是不可能做到的:
ul { --accent-color: purple; }
ol { --accent-color: rebeccapurple; }
li { background: var(--accent-color); }
① 不要忘了這樣的原生CSS 特性也可以通過腳本來操縱。比如說,你可以用JS 來改變一個變量的值。
你看清楚這段代碼的意圖了嗎?在有序列表中,列表項的背景色將是rebeccapurple;但在無序列表中,列表項的背景色將是purple。試試用預(yù)處理器能否做到!當然,在這個例子中,我們可以直接使用后代選擇符,只不過這個例子的重點在于向你展示CSS 的原生變量所具備的動態(tài)性。

上面提到的原生CSS特性絕大多數(shù)在目前還沒有得到很好的支持,因此在很多情況下,如果可維護性很重要(它確實很重要),使用預(yù)處理器是不可避免的。我的建議是,在每個項目開始時使用純CSS,只有當代碼開始變得無法保持DRY時,才切換到預(yù)處理器的方案。為了避免可能發(fā)生的“依賴”或“濫用”,在引入預(yù)處理器的問題上需要冷靜決策,不應(yīng)該在每個項目一開始時就不動腦筋順著慣性來。
可能你還不知道(或許直接跳過了前言,嘖嘖),這里再說一次,這本書的樣式是用SCSS寫的。這些樣式代碼以純CSS起步,而且只在代碼增長得太過復(fù)雜以致無法維護時才切到SCSS。誰說CSS和預(yù)處理器只能用在網(wǎng)頁上?
本文選自《CSS揭秘》。

這是一本注重實踐的教程。CSS專家Lea Verou單刀直入,教你用代碼解決實際問題。她在書中揭示了47個鮮為人知的CSS技巧,指導(dǎo)中高級CSS開發(fā)者循序漸進,探尋更優(yōu)雅的解決方案,攻克每天都會遇到的各種網(wǎng)頁樣式難題。
讀者將在本書中領(lǐng)略作者的縝密思路,并學(xué)會用這種思路來應(yīng)對各種不期而遇的CSS難題,最終達成DRY、可維護、可擴展、輕量級并且符合標準的結(jié)果。
目錄
第 2 章 背景與邊框
第 3 章 形狀
第 4 章 視覺效果
第 5 章 字體排印
第 6 章 用戶體驗
第 7 章 結(jié)構(gòu)與布局
第 8 章 過渡與動畫
按規(guī)范分類
魔法哥在 CSS Conf 上的演講:
作者叫 Lea Verou,她是一位資深 Web 開發(fā)者,有著豐富的實踐經(jīng)驗。更重要的是,她是 W3C CSS 工作組的特邀專家——CSS 工作組匯集了這個領(lǐng)域內(nèi)的專家,他們是制定 CSS 規(guī)范、設(shè)計 CSS 這門語言的一群人——全球只有極少數(shù)頂尖的開發(fā)者才有機會獲邀加入 CSS 工作組。
國內(nèi)開發(fā)者親切地稱呼她為 “CSS 一姐”。
那這本書到底好在哪里呢?
對于中級的 CSS 開發(fā)者來說,這本書可以發(fā)揮最大的功效——它可以幫助你進階。相信很多開發(fā)者在學(xué)習(xí) CSS 到了一定階段的時候,感覺自己好像什么都會了,但遇到復(fù)雜問題時往往又感覺捉襟見肘、力不從心。這就是遇到瓶頸了。如何突破瓶頸、進入下一個階段?要做的無非是兩件事——實踐和思考。書并不能代替你思考,但一本好書可以向你示范,什么樣的思考方式是正確的。
如果你已經(jīng)是一位 CSS 專家了,已經(jīng)有些飄飄然了,那這本書可以告訴你和這個星球上最頂尖的 CSS 專家的差距在哪里,從而幫助你找到人生下一階段的目標和動力。