- 首發:krissarea.gitee.io
- 作者:陳大魚頭
- github: KRISACHAN
HTML的誕生
HTML是怎麼來的?
在1982年的時候,全球資訊網的發明者Tim Berners-Lee爵士為了讓全世界的物理學家能夠方便的進行合作與資訊共享,造了HTML(HyperText Markup Language) 超文字標記語言。
在1991年3月,Tim Berners-Lee
把HTML
介紹給了給他在CERN(歐洲核子研究中心) 工作的朋友,當時網頁瀏覽器被其世界各地的成員用來瀏覽CERN
龐大的電話薄。
然後在8年之後的1990年,博士發明了世界上第一個瀏覽器WorldWideWeb,也因此推動著網際網路高速發展。
在WorldWideWeb
問世之後的1993年NCSA推出了Mosaic瀏覽器並且迅速火了起來,成為第一個世界級應用的瀏覽器,推動著網際網路發展。隨後跟著的有當時的兩大霸主Netscape
de Netscape瀏覽器與MicroSoft
的Internet Explorer瀏覽器,這兩個瀏覽器在當時掀起了一場網際網路瀏覽器大戰。這場戰爭的結果是以Internet Explorer
全勝告終。但也因此大大的推動了網際網路的發展。
CSS的誕生
CSS是怎麼來的?
就在承載HTML
的瀏覽器迅猛發展的90年代,CSS (Cascading Style Sheet)也應運而生。不同的瀏覽器結合各自HTML
語法結構實現了很多不同的外部樣式語法。但隨著HTML
的發展,為了滿足設計師的要求而增加了很多顯示功能,隨著這些功能的增加,外部樣式語法作用越來越沒有意義。
在1994年10月10日,CSS之父Håkon Wium Lie提出了 CSS 的最初建議,並且為 HTML 樣式在芝加哥的一次會議上正式提出了 CSS 。
在1996 年 12 月,W3C
在經過多方的討論之後,推出了CSS1.0
。這一規範一出現就引起了各方的注意,隨即 MicroSoft 公司和 Netscape 公司紛紛表示自己的瀏覽器能夠支援 CSS1.0
。
CSS的各個版本
CSS各版本的更新
CSS1.0
在1997 年 由W3C
釋出,第一版主要規定了選擇器、樣式屬性、偽類 / 物件幾個大的部分;CSS2.0/2.1
在1998 年 由W3C
釋出,CSS2 規範是基於 CSS1 設計的,擴充和改進了很多更加強大的屬性。包括選擇器、位置模型、佈局、表格樣式、媒體型別、偽類、游標樣式;- 由於
CSS2
經歷了 9 年的時間(從 2002 年 8 月到 2011 年 6 月)才達到 Recommendation(推薦) 狀態,此後W3C為了加快那些已經確認沒有問題的特性的標準化速度,便作出了一項被稱為 Beijing doctrine 的決定,將CSS模組化,並且按照每個模組的進度來標準化。所以從形式上來講,CSS3
已經不存在了。現在CSS 包括了修訂後的 CSS2.1 以及完整模組對它的擴充,模組的 level(級別)數並不一致。可以在每個時間點上為 CSS 標準定義一個 snapshots(快照)。
下圖為CSS模組化的發展程式圖,來自MDN
差點要成為CSS的語言
現在的CSS也是經過一番爭鬥才脫穎而出的
以下內容翻譯於The Languages Which Almost Became CSS
第一個提案
早在1993年Mosaic
瀏覽器1.0釋出之前,當時現有的瀏覽器已經開始獨立處理HTML
了,但是它們並沒有能給標籤定製樣式的方式,這就意味著你看到的標籤長什麼樣就長什麼樣,不能改。
所以在1993年的6月,Robert Raisch
給www-talk
郵件發了一個提案,希望建立一個“一種易於解析可以與Web文件一起提供樣式資訊的格式”,並給它起名叫RRP
。
格式如下:
@BODY fo(fa=he,si=18)
複製程式碼
看不懂上面的程式碼是情有可原的。在gzipping
之前的時代,網路傳輸速度只有14.4K,所以格式儘量壓縮都是合理的。這個特殊規則是將font family (fa)
設定為helvetica (he)
,將font size(si)
設定為18 points
。
Viola 以及原始瀏覽器之戰
和流行的看法不一樣,Mosaic
並不是第一個圖形瀏覽器,ViolaWWW才是。由Pei-Yuan Wei花了4天寫的。
以下是Pei-Yuan Wei
建立的樣式表語言:
(BODY fontSize=normal
BGColor=white
FGColor=black
(H1 fontSize=largest
BGColor=red
FGColor=white)
)
複製程式碼
在這個例子中我們給body
新增了顏色選擇器,並且給body
中的h1
新增了樣式。
值得一提的是PWP還是引用外部樣式表的方法提出者,他提出的方法一直沿用至今。
<LINK REL="STYLE" HREF="URL_to_a_stylesheet">
複製程式碼
不幸的是,ViolaWWW
只能執行在X Window System系統中,這個系統只在Unix中受歡迎。當Mosaic
移植到Windows
上不久後就把ViolaWWW
拋到身後了。
Web之前的樣式表
早在網際網路之前就有對文件樣式進行修改的語言要求。
正於你所知道的,HTML
源於一個在網際網路之前就出現的語言,SGML
。早在1987年,美國國防部就決定研究SGML
是否可以使文件儲存和傳輸更加便捷,他們有大量的文件需要處理。跟其他好的政府專案一樣,他們沒有時間可以浪費在起名上。這個團隊最初叫計算機輔助後勤支援隊,後來叫計算機輔助採集和後勤支援隊,最後叫持續獲取和生命週期支援計劃。反正簡寫都是CALS
。
CALS
為SGML
建立了一個叫FOSI
(這是一個四字單詞簡寫,但是因為年代久遠,已經不知道是哪四個單詞了)的語言來為文件新增樣式。
例子如下:
<outspec>
<docdesc>
<charlist>
<font size="12pt" bckcol="white" fontcol="black">
</charlist>
</docdesc>
<e-i-c gi="h1"><font size="24pt" bckcol="red", fontcol="white"></e-i-c>
<e-i-c gi="h2"><font size="20pt" bckcol="red", fgcol="white"></e-i-c>
<e-i-c gi="a"><font fgcol="red"></e-i-c>
<e-i-c gi="cmd kbd screen listing example"><font style="monoser"></e-i-c>
</outspec>
複製程式碼
如果你困惑docdesc
或charlist
,那麼你要知道,www-talk
的成員跟你有同樣的困惑。唯一給出上下文資訊的是e-i-c
,即element in context
。FOSI
值得注意的是引入了em
作為字型單位,現在已經成為了很多熟悉CSS的人中更受歡迎的方法。
圖靈完備的樣式表
由於它的複雜性,FOSI
被認為是格式化文件問題的臨時解決方案。長遠的解決方案是建立一個基於函數語言程式設計語言Scheme的新語言,它可以做任何你能想象到的文件轉換。這門語言叫DSSSL
。
下面是語法:
(element H1
(make paragraph
font-size: 14pt
font-weight: 'bold'))
複製程式碼
因為它是一門程式語言,所以你可以函式化:
(define (create-heading heading-font-size)
(make paragraph
font-size: heading-font-size
font-weight: 'bold))
(element h1 (create-heading 24pt))
(element h2 (create-heading 18pt))
複製程式碼
並在樣式中使用數學結構,例如“條帶化”表的行:
(element TR
(if (= (modulo (child-number) 2)
0)
… ;even-row
…)) ;odd-row
複製程式碼
最後,讓你妒忌一下,DSSSL可以把繼承的值當成變數進行數學運算:
(element H1
(make paragraph
font-size: (+ 4pt (inherited-font-size))))
複製程式碼
不幸的是,DSSSL
擁有和跟所有Scheme
類語言一樣的致命弱點:括號太多了。此外,當它最終釋出時,它可能過於完整,使瀏覽器開發人員感到害怕。 DSSSL規範包含210多個獨立的可以定製樣式的屬性。
為什麼樣式表脫穎而出?
CSS 沒有父級選擇器(一種基於子元素的樣式給父元素設定樣式的方法)。 這個問題在Stack Overflow上被頻繁的提問(這是其中一個)。但是事實證明,這個特性缺失是有理由的。特別在網際網路早期,讓網頁在完全載入完成之前被渲染,是很重要的。意思就是,大家希望HTML載入完之前,就可以渲染已經載入完的部分。
父選擇器意味著樣式得在HTML文件一邊載入時,一邊更新。像DSSSL這樣的語言如果實現了這個功能,因為它們可以對文件進行操作,所以也沒很可能就不能用了。
在1995年3月,Bert Bos
作為第一個提出這個問題的人,還提供可行方案。他的提案中還包括了一個早期的笑臉表情包:-)
。
這個語言有點像物件導向:
*LI.prebreak: 0.5
*LI.postbreak: 0.5
*OL.LI.label: 1
*OL*OL.LI.label: A
複製程式碼
使用.
來指定直接子節點,使用*
來指定祖先節點。
他的語言還有一個很酷的屬性,就像這樣在樣式表中定義超連結:
*A.anchor: !HREF
複製程式碼
在上面的例子中,指定link
的目標為其HREF
的值。像這種可控制連結等元素的行為在很多提案中都很流行。在Javascript
還沒出來之前,沒有什麼可控制元素的方法,所以它們看起來是很合理的。
一個函式式的提案,1994年被一位叫C.M. Sperberg-McQueen
的紳士提出,裡面包含了類似的行為。
(style a
(block #f) ; format as inline phrase
(color blue) ; in blue if you’ve got it
(click (follow (attval 'href))) ; and on click, follow url
複製程式碼
他的語言還引入了conten
t關鍵字作為從樣式表控制HTML
元素內容的一種方式,這個概念後來被引入到CSS 2.1
中。
可能還有什麼
在我談到實際成為CSS的語言之前,還有另一種語言值得一提,因為它在某種程度上是早期Web開發者的夢想。
它就是PSL96
,按照當年的命名規範,1996年版的Presentation Specification Language
。PSL的核心很像CSS:
H1 {
fontSize: 20;
}
複製程式碼
然而,它很快就變得很有趣了。例如,你不僅可以根據元素寬度來渲染它的位置,也可以基於瀏覽器的實際寬度來渲染。
LI {
VertPos: Top = LeftSib . Actual Bottom;
}
複製程式碼
甚至你可以使用元素左邊的兄弟姐妹來定製。
你還可以為樣式新增邏輯表示式。例如,僅設定具有href的錨元素的樣式:
A {
if (getAttribute(self, "href") != "") then
fgColor = "blue";
underlineNumber = 1;
endif
}
複製程式碼
這種樣式可以擴充套件到我們今天用樣式來完成的各種事情:
LI {
if (ChildNum(Self) == round(NumChildren(Parent) / 2 + 1)) then
VertPos: Top = Parent.Top;
HorizPos: Left = LeftSib.Left + Self.Width;
else
VertPos: Top = LeftSib.Actual Bottom;
HorizPos: Left = LeftSib.Left;
endif
}
複製程式碼
支援這功能的話或許真的可以實現內容與樣式分離的夢想。遺憾的是這門語言擴充性太強,這就以為著不用瀏覽器的實現可能會不一樣。而且,它是以一系列的文章出現出現在學術界,並沒有經過www-talk
郵件列表進行討論,所以,它永遠不會出現在主流瀏覽器。
CSS之魂
一門語言,至少從名字上,直接引出了CSS
,它叫CHSS (Cascading HTML Style Sheets)
,提案在1994年被Håkon W Lie
提出。
跟很多好主意一樣,這個原始提案非常瘋狂。
h1.font.size = 24pt 100%
h2.font.size = 20pt 40%
複製程式碼
注意行尾的百分比,這個百分比是指當前樣式表佔用該值的“權重”。例如,如果之前的樣式表已將h2字型大小定義為30pt,擁有60%,並且此樣式表將h2s設定為20px 40%,則這兩個值將根據其權重百分比進行組合在一起,大概就是26pt。
很明顯,這個提案是在基於文件的HTML
頁面的時代,基於拖鞋的設計是無法在我們面向應用的世界裡發揮作用的。不過,它已經具備了樣式表應該可以疊加的基本思想。換句話說,應該可以將多個樣式表應用於同一頁面。
它最初的形式被認為是重要的,因為它讓使用者可以控制他們所看到的內容。頁面有一個樣式表,並且Web使用者將擁有自己的樣式表,這兩個樣式表一起渲染在頁面上。支援多個樣式表被視為一種維護Web個人自由的方法,而不是支援開發人員(他們仍然手動編寫單獨的HTML頁面)的方式。
使用者可以控制該頁面作者的建議的權重,就如提案中的ASCII 圖那樣。
User Author
Font o-----x--------------o 64%
Color o-x------------------o 90%
Margin o-------------x------o 37%
Volume o---------x----------o 50%
複製程式碼
像許多這些提案一樣,它包含了幾十年來不可能出現在CSS中的特性。例如,可以根據使用者的環境編寫邏輯表示式。
AGE > 3d ? background.color = pale_yellow : background.color = white
DISPLAY_HEIGHT > 30cm ? http://NYT.com/style : http://LeMonde.fr/style
複製程式碼
在一個有點樂觀的未來場景中,瀏覽器會根據給定的內容對你的相關性,允許它以更大的尺寸展示給你看。
RELEVANCE > 80 ? h1.font.size *= 1.5
複製程式碼
你知道接下來發生了什麼
Håkon Lie
繼續簡化他的提案,且和Bert Bos
合作,並在1996年11月釋出的CSS
規範的第一版。最終他將創造CSS
寫進了他的博士論文裡,也就是這個文件幫助我寫了這篇文章。
與許多其他提案相比,CSS的一個值得注意的事實是它的簡單性。它易於分析,易於編寫和輕鬆閱讀。與網際網路歷史上的許多其他例子一樣,對於初學者來說,需要的是最容易上手的技術,而不是那些給更強大的專業人員用的技術。
它本身就給我們一個提醒,這是一個偶然發生的創新。例如,僅新增了對上下文選擇器(body ol li
)的支援,因為Netscape
已經有一種方法可以從超連結的影像中刪除邊框,並且似乎有必要實現流行瀏覽器可以執行的所有操作。這個功能本身就大大拖延了 CSS
的實現,因為大多數瀏覽器在解析HTML時沒有保留標籤的“堆疊”。這意味著必須重新設計解析器才能完全支援CSS。
像這樣的挑戰(以及廣泛使用非標準HTML標籤來定義樣式)導致著CSS直到1997年才可使用,直到2000年3月才有瀏覽器完全支援它。這跟每個開發者跟你說的一樣,瀏覽器近幾年才真正標準化,這裡距首次釋出CSS已經過去了21年(原文15年)了。
最終BOSS
IE 3
以(有點可怕的)CSS
支援著稱。為了競爭,Netscape 4
也考慮了CSS
。但它還是決定通過將CSS轉換為JavaScript並執行它來實現它,而不是將第三種(考慮HTML和JavaScript)。更有甚者,Web開發人員應該可以訪問這個“JavaScript樣式表”中間語言。
語法是直接使用JavaScript
,然後新增了一些特定樣式的API:
tags.H1.color = "blue";
tags.p.fontSize = "14pt";
with (tags.H3) {
color = "green";
}
classes.punk.all.color = "#00FF00"
ids.z098y.letterSpacing = "0.3em"
複製程式碼
你甚至可以定義一個每遇到一個標籤就執行一次的函式:
evaluate_style() {
if (color == "red"){
fontStyle = "italic";
} else {
fontWeight = "bold";
}
}
tag.UL.apply = evaluate_style();
複製程式碼
我們應該簡化樣式和指令碼之間分界線的想法是合理的,現在在React社群還出現了各種類似的思路。
在當時,JavaScript
本身就是一種非常新的語言,但是通過一些逆向工程,IE
已經在IE3
中新增了對它的支援(如“JScript
”)。更大的問題是社群已經在CSS
周圍團結起來,而Netscape
在這個時候被大多數標準社群視為胖虎(原文bullies)。當Netscape確實向標準委員會提交JSSS時,它被置若罔聞。三年後,Netscape 6放棄了對JSSS的支援,而且自己也準備安樂死了。
還有什麼可能
由於W3C的一些公開羞辱,IE 5.5
在2000年推出了幾乎完整的CSS1支援。當然,正如我們現在所知,瀏覽器的CSS在未來10年裡都非常粗糙且難以使用。還好今天情況大大改善了,讓開發者寫一份程式碼並在不同瀏覽器中都可以執行的夢想(幾乎)實現了。
我個人的結論是,無論這些決策是拍大腿決定的還是深思熟慮的,都決定了當前工具的形式。如果CSS的設計方式只是為了滿足1996年的限制,那麼20年後的我們做事的方式應該會有些不同。
參考文章:
【Hello CSS】系列
【Hello CSS】
是以CSS
基礎概念為主題的系列文章,旨在幫助大家更深刻地瞭解並且提高CSS
在各位開發者心目中的地位。由於魚頭我水平有限,文筆有限,如果各位在文章中發現有任何不合理,不正確的地方,還煩不吝指出,我會非常感謝的;如果通過文章有任何想法或疑問,也希望各位能積極留言,我們互相探討;如果通過本系列文章有所收穫,這就讓魚頭我喜不自勝了!
如果你也喜歡`CSS`,喜歡探討技術,或者對本文,本系列有任何的意見或建議,魚頭非常希望你能加入一個有趣的微信群 — “進擊的CSS”。你可以掃描下方二維碼,新增魚頭微信,新增時註明 “加群”,如果你覺得我的文章有趣,歡迎關注微信公眾號“魚頭的Web海洋”。衷心希望可以遇見你。