本文首發於圖靈教育微信本文作者:李松峰
本文首發於圖靈教育微信
農諺:「種地不上糞,等於瞎胡混。」
跟許許多多大城市裡的上班族一樣,我也是在農村長大的。因此,毋庸諱言,我小時候拾過糞。畢竟,那時候在農村長大的孩子,有幾個沒拾過糞呢。糞就是屎,主要是牛屎,因為個頭大,我們那裡也把風吹日晒幹了的牛糞叫作「牛糞坯子」。
屎,本來是廢棄物。但正如牛糞,卻是農民種地所必需的天然肥料,是莊稼茁壯成長的營養來源,更是來年好收成的重要保障。俗話說:「沒有尿屎臭,哪有稻米香?」
如今,我有幸成為一名在前端領域辛勤耕種的碼農。就在前幾天,我心血來潮,從電腦里翻出了十幾年前出版的一本CSS名著的第1版(2006年)和第2版(2009年)。翻來翻去,我不禁聯想到小時候拾糞的經歷。說到這裡,不少讀者可能還不明就裡,其實如果你是一名資深前端,我只要提幾個當年火得不得了的技術你就會明白我在說什麼了。
好吧,閑話少說,言歸正傳。馬上開始我們的CSS拾糞之旅吧!
不知道大部分讀者怎麼樣,反正我一聽到這個詞就會有一種穿越感。十幾年前,CSS遠遠不如今天這麼強大。頁面仔們想要在網頁中實現稍微前沿、酷炫一點的效果,都必須絞盡腦汁。
滑動門
「滑動門」,即Sliding Doors,是誕生於2003的一種實現「圓角盒子」技術。假設最終要通過CSS實現下圖中這樣可以伸縮適應的圓角盒子:
你會怎麼做?
……等等,那可是在遙遠的2003年,當時的CSS標準里並沒有border-radius這麼一個屬性,更沒有瀏覽器支持類似的特性。於是,一位聰明的大牛Douglas Bowman發明了「滑動門」技術。其原理如下圖所示:
圖中展示了兩個GIF圖片:top-left.gif和top-right.gif,前者頭部是一個1/4圓且比較長,後者尾部是一個1/4圓且比較短。
關鍵是使用background-image和background-position屬性,後者最終會覆蓋到前者上面。當然,要實現4個圓角,就必須要用到4張圖片:
配合HTML標記和CSS代碼更容易理解:
<div class="box"> <div class="box-outer"> <div class="box-inner"> <h2>Headline</h2> <p>Content</p > </div> </div> </div>
.....
.box { width: 20em; background: #effce7 url(images/bottom-left.gif) ? no-repeat left bottom; } .box-outer { background: url(images/bottom-right.gif) no-repeat right bottom; padding-bottom: 5%; } .box-inner { background: url(images/top-left.gif) no-repeat left top; } .box h2 { background: url(images/top-right.gif) no-repeat right top; padding-top: 5%; } .box h2, .box p { padding-left: 5%; padding-right: 5%; }
哇哦,精彩!
可以腦補出來最終效果的同學請為自己鼓掌,同時也恭喜你成功撿起了第一塊「牛糞」。暫時還沒搞明白的小夥伴也不必氣餒,有時候撿屎本身也是個技術活兒呢~
山頂角
「山頂角」,英文是Mountaintop Corners,誕生於2004年,由另一位牛人Dan Cederholm發明。相比於「滑動門」直接用圖片本身充當圓角,「山頂角」反其道而行之:用圓角蒙版遮住背景顏色實現圓角,因此更為靈活。上圖:
如果一看到這張圖你就立即明白了,那恭喜你,第二塊「牛糞」成功入筐。還不明白的同學,請看以下代碼,HTML跟前面類似,同樣需要4個元素來應用4張背景圖片:
CSS也極為相似:
成功撿到這塊「牛糞」的同學也不要過分興奮,「山頂角」雖然可以通過簡單修改背景顏色來改變圓角盒子的顏色,省去重新製作圖片的麻煩,但它也有不足。由於當時每個角的蒙版圖片是用點陣圖製作的,所以只適用於製造細微的曲線,較大弧度的圓角會顯得粗糙。
不過,瑕不掩瑜。「山頂角」無論如何都是當時製作圓角盒子當之無愧的王牌技術,更是當時每一個頁面仔的大救星。十幾年後,當屏幕前的我們與這塊「牛糞」不期而遇時,一定也會暗自讚歎。關鍵是,這塊簡潔巧妙的牛糞,它好撿啊!
多重背景圖片
在前述兩塊重量級「牛糞」的啟發下,支持多背景圖片的background-image屬性終於應運而生。於是,更簡單的實現方案出現了:
.box { background-image: url(/img/top-left.gif), url(/img/top-right.gif), url(/img/bottom-left.gif), url(/img/bottom-right.gif); background-repeat: no-repeat, no-repeat, no-repeat, no-repeat; background-position: top left, top right, bottom left, bottom right; }
當然,給一個元素應用多個背景並不局限於實現圓角盒子效果。至於還可以實現什麼,請相信:限制你的只有你的想像力。
圓角邊框
同樣是在前兩塊「牛糞」滋養的沃土之上,迄今為止最為簡單強大的border-radius屬性也誕生了:
.box { border-radius: 1em; }
成功撿起兩塊「牛糞」之後,是不是很有成就感?你還想繼續撿?沒問題,走著~
想當初,不僅僅是實現圓角盒子需要全世界的大牛為之殫精竭慮,同樣讓他們苦思冥想的還有下拉陰影。
先看看Dunstan Orchard大牛的傑作。其核心思想就是給元素背景上應用一大張陰影圖,然後通過負外邊距把陰影部分顯露出來。
如圖所示,這是一張800px?800px的陰影圖shadow.gif,其右下角放大後看可以看到5像素的陰影。以下是要應用陰影效果的HTML:
<div class="img-wrapper"> < img src="dunstan.jpg" width_="300"? height="300" alt="Dunstan Orchard" /> </div>
顯然,這是一個容器div中包含一張人物圖片(dunstan.jpg)。為了讓容器div包裹住圖片,首先要利用float讓這個塊級元素收縮,從而包裹住其中的圖片:
.img-wrapper { background: url(images/shadow.gif) no-repeat bottom right; clear: right; float: left; }
但這樣背景圖片完全隱藏在了人物圖片下方,為了讓它顯露出來,還必須配合神奇的負外邊距:
.img-wrapper img { margin: -5px 5px 5px -5px; }
於是,立體感十足的陰影效果做成了,見下圖:
不過,這硬邊陰影看著也忒不自然了,就算是在十幾年前也是無法接受的。那好,這塊「牛糞」還要做大點。為了模擬出自然的陰影,還需要一張與剛才的陰影圖片對角的模糊蒙版:
HTML標記也要再嵌套一層div:
首先,還是給最外層的容器div應用硬邊陰影背景,定位在右下角:
.img-wrapper { background: url(images/shadow.gif) no-repeat right bottom; float: left; }
然後,給內層的div應用模糊蒙版背景,定位在左上角:
.img-wrapper div { background: url(images/mask.png) no-repeat left top; padding: 0 5px 5px 0; }
最後,再給圖片添加個邊框:
.img-wrapper img { background-color: #fff; border: 1px solid #a9a9a9; padding: 4px; }
大功告成:
完美!
這塊大「牛糞」威力夠大,直接催生了box-shadow:
img { box-shadow: 3px 3px 6px #666; }
這裡用了僅僅一個屬性,而且效果同上。冗長的HTML和CSS代碼不見了,它們去哪兒了?那還用問,它們已經化作沉甸甸的「牛糞」裝進了你我的糞筐里。恭喜你再次撿屎成功!
想當年,大牛們為了使用特殊字體實現不一樣的視覺效果,必須先把文字轉換成圖片,因為用戶機器上已安裝的通用字體數量有限。但圖片對搜索引擎不友好,於是有牛人想出了點子。總體的思路是像往常一樣使用文本,讓搜索引擎可以找到,同時再通過某種方式讓它對用戶不可見,只顯示包含特殊字體效果的圖片。
比如,Todd Fahrner的Fahrner Image Replacement (FIR)。先把文本包一個span中:
<h2> <span>Hello World</span> </h2>
然後給標題h2添加背景:
h2 { background:url(hello_world.gif) no-repeat; width: 150px; height: 35px; }
最後,隱藏span:
span { display: none; }
可是,由於多數屏幕閱讀器會忽略display:none;的元素,從而導致嚴重的無障礙問題。所以,這個看似簡單的方案實踐中並不可行。
於是,另一位牛人Mike Rundle想出了一個兩全其美的點子:使用負文本縮進把文本拉到屏幕之外!
這下HTML還更簡單了:
<h2> Hello World </h2>
CSS:
h2 { text-indent: -5000px; background:url(hello_world.gif) no-repeat; width: 150px; height:35px; }
這就解決了屏幕閱讀器用戶的問題。但還沒有完,新的問題又出來了。在當時網路速度很慢的情況下,可能會有用戶禁用瀏覽器顯示圖片的功能,而CSS照樣起作用。這是一種極端情況,這時候用戶會既看不到文本,也看不到圖片。
追求完美的大牛們又開始行動了。Tom Gilder和Levin Alexander最終找到了既對屏幕閱讀器友好,又能在禁用圖片打開CSS的情況下讓文本對用戶可見的方案。
這個方案首先要在被替換的元素內額外添加一個空標籤(span):
<h2> <span></span>Hello World </h2>
然後,將容器設置為相對定位:
h2 { width: 150px; height: 35px; position: relative; }
position:relative;將容器設定為其中span的定位上下文。接下來,把背景應用給span,並採用絕對定位,而寬和高均為父元素的100%會讓它完全把文本蓋在下面:
h2 span { background: url(hello_world.gif) no-repeat; position: absolute; width: 100%; height: 100%; }
這裡只有一個問題,此時的圖片必須完全不透明,否則下面的文本就會「走光」。
如前所述,這幾塊「牛糞」最終要解決的是用戶計算機上字體匱乏的問題。這些需求最終也催生了十幾年後可以廣泛使用的Web字體。
@font-face { font-family: Vollkorn; src: url(fonts/Vollkorn-Regular.eot#?ie) format(embedded-opentype), url(fonts/Vollkorn-Regular.woff2) format(woff2), url(fonts/Vollkorn-Regular.woff) format(woff), url(fonts/Vollkorn-Regular.ttf) format(truetype), url(fonts/Vollkorn-Regular.svg) format(svg); }
Web字體是一個大話題,在此我們就不過多涉及了。總之,我們再一次見證了「牛糞」的力量,同時也給我們今天的拾糞之旅畫上了一個完美的句號。
天下碼農千千萬,大牛卻不多。大牛之所以成為大牛,通常都會給數年後的從業者留下可供撿拾的「牛糞」。今天我們的拾糞之旅,既是對CSS歷史上曾經輝煌一時的技術的巡禮,更是對如群星般璀璨的大牛們的致敬。
這些曾經紅極一時的技術在今天看來或許不值一提,甚至幼稚可笑。然而,「後之視今,亦猶今之視昔。」今天被頂禮膜拜、推崇備至的技術,十幾年後再看,或許同樣不值一提,甚至幼稚可笑。但不容否認的是,恰恰是這些今天看來簡單、幼稚的「牛糞」,孕育、滋養了一代一代技術人,推動著技術不斷進步和突破。人類社會就是這樣一路走過來的。
朝花夕拾。從拾糞的視角看,我們不禁深思:今天的碼農,有幾人能留下供十年後的人撿拾的「牛糞」呢?所以,今天起,給自己定個小目標,著手準備我們的明日份「牛糞」吧!
看到這裡,有好奇的同學可能會問:這些「牛糞」到底來自哪本CSS名著,能否透露一下?當然可以。它們就是CSS Mastery: Advanced Web Standards Solutions (中文版《精通CSS》)的第1版和第2版。而且,這本名著的最新版也就是第3版的中文版也剛剛上市。值得一提的是,《精通CSS(第3版)》里可是滿滿的「明日份牛糞」哦,如果想開啟你的CSS「撿屎」之旅,那一定會是個不錯的體驗。
CSS暢銷經典全面升級,充分展示現代CSS實踐技巧
本書是CSS經典圖書升級版,結合CSS近年來的發展,尤其是CSS3和HTML5的特性,對內容進行了全面改寫。本書介紹了涉及字體、網頁布局、響應式Web設計、表單、動畫等方面的實用技巧,並討論了如何實現穩健、靈活、無障礙訪問的Web設計,以及在技術層面如何實現跨瀏覽器方案和後備方案。本書還介紹了一些鮮為人知的高級技巧,讓你的Web設計脫穎而出。
搶先入手升級版?到京東購買
到圖靈社區試讀更多
推薦閱讀:
TAG:CSS | 前端開發 | Web開發 |