DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> CSS入門知識 >> CSS詳解 >> 那些差一點成為了 CSS 的語言
那些差一點成為了 CSS 的語言
編輯:CSS詳解     

原文:http://www.zcfy.cc/article/709

事實上,對我來說在過去的一年裡,一直有一個快樂源泉是,不斷告訴人們,如果你們想同 TeX、Microsoft Word 以及其他常見的文本處理環境那樣地控制你們的網頁文檔:“對不起,你搞砸了”。

—— Marc Andreessen(Netscape 公司創始人、硅谷風投家,譯者注)1994

當 1991 年 Tim Berners-Lee 宣布 HTML 問世時,沒有給網頁寫樣式的辦法。如何對 Html 標簽進行渲染是由浏覽器根據用戶的喜好設置來決定的。然而,似乎創建一個標准方法讓網頁被“建議”如何渲染比按照設置的風格進行渲染要更好。

然而 CSS 直到五年之後才出現,十年之後才完全實現。這段時期是充滿著創新和緊鑼密鼓地工作的時期,這導致不只一兩種相互競爭的樣式方法出現,其中一些簡單到差一點成為標准。

由於這些語言顯然今天不常用,我發現想象這個世界可能出現的另一種樣子很令人著迷。甚至更令人驚訝的是,碰巧許多其他的選擇包含著一些開發者會希望在現在的 CSS 中看到的特性。

第一個提案

早在 1993 年,Mosaic 浏覽器還沒有發布 1.0 版本,那些已存在的浏覽器單獨處理 HTML。沒有一種方法能夠為 Html 指定樣式,意味著一旦浏覽器決定了一個 <h1> 看起來應該是什麼樣的,你看到的就是那個樣子。

在那一年的六月份,Robert Raisch 向 www-talk 郵件組提出了一個提案,希望創建“一個易於解析的格式來為 Web 文檔提供一個樣式信息”,這後來被叫做 RRP。

@BODY fo(fa=he,si=18) 

你不知道上面的代碼在做什麼情有可原。在 gzipping 之前的時代,網絡連接的速度在 14.4kb 左右,讓這個新格式的內容盡可能簡潔是有意義的。這個特別的規則將 font famliy (fa)設置為 helvetica (he),並將 font size (si) 設為 18 points。

這個提案裡面缺失一些有趣的內容,沒有提到數值單位,所有的數值基於它們的上下文來解釋(例如 font size 的單位總是 points)。這可以歸因於 RRP 被設計為更多地作為一組“對浏覽器渲染的提示或者建議”,而不是一個規范。這被認為是必要的,因為同樣的樣式表需要支持命令行模式的浏覽器(比如 Lynx),以及正變得越來越受歡迎的圖形化浏覽器。

Lynx browser screenshot

逐漸地,RRP 包含了一個方法來指定一個分縱欄的布局,而這個特性直到 2011 年 CSS 才支持了。例如,分三列,每一列寬度為“80 單位”看起來如下:

@P co(nu=3,wi=80) 

這個解析起來有點難,但可能比起 white-space:nowarp 來也糟不到哪裡去。

值得注意的是,RRP 不支持任何我們現在樣式表中所擁有的“層級”。給定的文檔在一個時間點只能有一個有效的樣式,這對於指定文檔的樣式來說是一個符合邏輯的思考方式,盡管今天我們有了 CSS,已經不習慣那樣思考了。

Macro Andressen (Mosaic 的創建者,Mosaic 本來有望成為最流行的浏覽器)注意到了 RRP 提案,然而 Mosaic 從未實現它。相反地,Mosaic 快速轉向(某種意義上來說,悲劇地)使用 Html 標簽來定義樣式的路線上,引入了一些標簽例如<FONT>以及<CENTER>

Viola 以及早期浏覽器之爭

那麼為什麼你不僅僅實現眾多樣式表提案其中的一個。如果選擇對了,問題基本就解決了。

因此我要告訴人們,“好吧,你得學習這個語言來寫你的文檔,然後你得學習那個語言來實際決定你的文檔如何展現。”噢,他們會喜歡的。

— Marc Andreessen 1994

與流行的看法相反,Mosaic 不是第一個圖形浏覽器,ViolaWWW 才是。ViolaWWW 是一個圖形浏覽器,由魏培源在四天之內寫出來的。

Viola browser screenshot

魏培源創建了一個樣式表語言,它支持一種格式的嵌套結構,而嵌套結構在今天的 CSS 裡我們已經習慣了:

(BODY fontSize=normal BGColor=white FGColor=black (H1 fontSize=largest BGColor=red FGColor=white) ) 

在這個例子裡,我們應用一個 color 樣式到 body 然後特別地為出現在 body 中的 H1 指定新的樣式。PWP 使用一個括號系統如同今天一些開發者喜歡使用的 Stylus 和 SASS 語言使用一個縮進系統那樣來處理嵌套,而不是用重復的選擇器來處理嵌套。這令 PWP 的語法潛力至少在一方面比最後成為了網頁通用語的 CSS 更好。

PWP 也因為引入了外部樣式表機制而得到關注,這個機制我們今天依然在使用:

<LINK REL="STYLE" HREF="URL_to_a_stylesheet"> 

不幸地是,ViolaWWW 主要工作在 X Windowing 系統 上,這個系統只在 Unix 系統上流行。當 Mosaic 被移植到 Windows 上,它很快將 Viola 遠遠甩在身後。

在 Web 出現之前的樣式表

HTML 是一種只在計算機科學家中受歡迎的東西。是的,它表達了一個文檔的底層結構,但是文檔不僅僅只是結構化的文本數據,它們有視覺上的影響。Html 完全消除了一切視覺創造力,而文檔設計本應該包含視覺創造力。

— Roy Smith 1993

一個語言對表達文檔樣式的需求遠早於互聯網存在。

正如你可能知道的,Html 源自於在互聯網之前出現的語言,這個語言叫 SGML。在 1987 年,美國國防部決定研究 SGML 是否能夠用來方便地存儲和傳輸他們需要處理的大量文檔。如同其他“好”的政府工程,他們沒有把時間浪費在起名字上。那個團隊最初被叫做計算機輔助後勤支援隊,後來改名計算機輔助采集與後勤支援隊,然後最終叫做連續采集與生命周期支持計劃。不管叫哪一個,簡寫都是 CALS。

CALS 團隊創建了一個語言來給 SGML 文檔添加樣式,這個語言叫做 FOSI,這是一個縮寫,無疑是四個單詞的組合(只是年代久遠不知道是哪四個單詞了——譯者注)。他們為這個語言發布了一個規范,這一規范匯集了一切不可理解的內容。它包含一個在網絡上永遠存在的我最喜歡的無意義的信息圖表。

互聯網的一個不可侵犯的原則是:如果你能證明過程中有人錯了,就能進一步完善。在 1993 年,魏培源的提案僅僅提出四天之後,Steven Heaney 提出(http://1997.webhistory.org/www.lists/www-talk.1993q4/0295.Html) 何必“重復發明輪子”,我們最好使用 FOSI 的一個變種來為 web 添加樣式。

一個 FOSI 文檔自身用 SGML 編寫,這實際上是一個有點邏輯的設計,因為 web 開發者已經熟悉 SGML 的變體 Html。一個 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 用法的人們的首選。

從編程語言誕生的那一天起,語言沖突就產生了。函數式 LISP 風格的語言和更多其他聲明式語言之間爆發了戰爭。魏培源將自己的語法描述成 LISP 風格,但不久以後,一個真正的 LISP 語言變體進入了歷史舞台。

圖靈完備的樣式表

由於它的復雜性,FOSI 實際上被認為只是格式化文檔的一個臨時方案。長遠的計劃是創建一個基於函數式編程語言 Scheme 的語言,這可以實現你所能想象到的最強大的文檔轉換。這個語言被叫做 DSSSL。它的作者 Jon Bosak 說:

把 DSSSL 與腳本語言放在一起是一個錯誤。是的,DSSSL 是圖靈完備的。是的,它是一個編程語言。但是一個腳本語言(至少我使用這個詞的方式)是過程式的,DSSSL 很顯然不是。DSSSL 是完全的函數式而且完全沒有副作用。在 DSSSL 中,副作用不可能發生。DSSSL 樣式表是一個巨大的函數,它的值是一個抽象的、獨立於設備的、非過程的描述,描述了格式化的文檔,它為下游的渲染過程提供顯示區域的規范(一種聲明,如果你願意那樣說的話)。

最簡單的形式,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)))) 

但不幸的是,如同所有 Scheme 類的語言一樣,DSSSL 有致命的缺陷:太多的括號。此外,當它最後發布的時候,它可以說是太完備了,以至於嚇到了浏覽器開發者。DSSSL 規范包含超過 210 個獨立的可以定制樣式的屬性。

DSSSL 團隊接下來創建了 XSL,一個用來轉換文檔的語言,它也很令人困惑,但確實要受歡迎一些。

為什麼一些樣式表脫穎而出?

CSS 沒有包含父級選擇器(基於子元素包含的樣式給父元素設置樣式的一種方法)。這個事實長期讓很多人在 Stack Overflow 發表文章表示不滿,然而,事實證明,它缺少這一特性是有一個很好的理由的。特別是在互聯網的早期,讓網頁在完全加載完成之前就能夠被渲染,是非常重要的。換句話說,我們想要在浏覽器在下載完頁面底部的 HTML 之前就能夠渲染前面已經下載好的 Html。

實現父類選擇器將意味著樣式得在 Html 文檔一邊加載的同時一邊更新。類似 DSSSL 這樣的語言更慘,因為他們可以在文檔本身上執行操作,這樣,如果在文檔加載完之前就開始渲染,它們的很多操作將不可用。

Bert Bos 在 1995 年 3 月第一個提出父類選擇器問題,並提交了一個可行的語言提案。他的提案還包括一個早期版本的微笑表情符 :-)。

這個語言自身在語法上有點“面向對象”:

*LI.prebreak: 0.5 *LI.postbreak: 0.5 *OL.LI.label: 1 *OL*OL.LI.label: A 

使用 . 來指定直系後代,使用 * 來指定祖先。

他的語言也包含一個很酷的屬性來通過樣式表定義鏈接元素的特性如何作用:

`*A.anchor: !HREF` 

在上面的例子裡,我們指定鏈接元素的目標是它自己的 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 

他的語言也引入一個 content 關鍵字作為從樣式表中控制 Html 元素內容的一個方法,這一概念後來被引入到 CSS 2.1 中。

可能是什麼

在我討論最終實際成為 CSS 的語言之前,另一個語言提案值得一提,即使僅僅是因為它從某種意義上代表了早期 web 開發者的夢想。

這個語言是 PSL96,因為是 1996 年的版本,按照時間規范命名為 PSL96, 它的全稱是“表述規范語言(Presentation Specification Language)”。在它的核心,PSL 看起來像 CSS:

H1 { fontSize: 20;
} 

盡管如此,它很快變得更有趣。例如,你可以不僅僅基於 Width 指定的大小表達元素的位置,,還可以通過浏覽器渲染的實際(Actual Width)大小來表達:

LI { VertPos: Top = LeftSib . Actual Bottom;
} 

注意到你也可以使用元素的左鄰來作為約束。

你還可以加邏輯表達式到你的樣式中。例如只為擁有 href 屬性的 a 元素指定樣式:

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),它被 Håkon W LIE 提出於 1994 年。

如大多數好主意,原方案是相當瘋狂的:

h1.font.size = 24pt 100% h2.font.size = 20pt 40% 

注意到在規則末尾的百分比,這個百分比指明當前樣式設置的值有多少“權重”。例如:如果前一個樣式定義了 h2 的 font size 為 30pt,權重60%,然後這個樣式定義了 h2 為 20px 40%,這兩個值將被基於他們的權重結合在一起,得到大約 26pt

現在相當清楚這個提案是如何在基於文檔的 Html 網頁時代被提出的,可是我們應用導向的世界容不下基於妥協的設計。然而,它確實包含了樣式表應當級聯的基本理念。換句話說,它能夠允許多個樣式表被應用到同一個網頁。

它那個計算公式被認為是重要的,因為它讓最終用戶能控制他們所能看到的結果。原始網頁將有用一個樣式表,而 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` 

你知道接下來發生了什麼

微軟絕對致力於開放標准,尤其是在互聯網上。

— John Ludeman 1994

Håkon LIE 繼續簡化他的提案,然後,在 1996 年 12 月與 Bert Bos 一起發布了 CSS 的第一版規范。最終他將創立 CSS 寫進他的博士論文,這篇論文對我寫成這篇文章超有幫助。

與其他許多提案相比較,一個值得注意的事實是 CSS 的簡單性。它容易解析,容易編寫也容易閱讀。和互聯網的歷史上的許多其他的例子一樣,讓新手最容易上手的技術,往往會最終戰勝那些更強大的給專業人員使用的技術。

它本身給我們一個提醒,提醒我們創新多少是一種偶然。例如,支持上下文選擇器(body ol li)僅僅是因為 Netscape 浏覽器已經有一個方法來移除超鏈接圖片的 border,而其他流行的浏覽器必須要能做到。這個功能本身的實現經過了比較長的時間,是因為在那個時候大多數浏覽器都沒有在解析 Html 的時候維持一個標簽棧,這意味著要實現這個功能,解析器得重新設計。

像這樣的挑戰(以及廣泛傳播的用非標准 Html 標簽來定義樣式)意味著 CSS 不可用直到 1997 年,而在 2000 年 3 月之前,都沒有任何一個浏覽器完全支持 CSS 所有特性。正如任何開發人員可以告訴你,浏覽器支持沒有任何地方接近標准兼容直到幾年之前,在 CSS 發布了 15 年之後。

最終 Boss

如果 Netscape 4 忽略應用到 <body> 元素的 CSS 規則並添加隨機數量的空白到你網頁的每一個結構元素,而如果 IE 4 處理 <body> 正確但是搞砸了 padding 屬性,什麼樣的 CSS 可以安全編寫?一些開發者選擇完全不寫 CSS。另一些開發者寫一份樣式表來補 IE 4 的缺,另一份不同的樣式表來填 Netscape 4 的坑。

— Jeffrey Zeldman

IE 3 高調地宣稱支持 CSS(某種程度上有點可怕)。為了競爭,Netscape 4 也考慮了 CSS。但它決定通過將 CSS 轉換為 Javascript 來執行它,而不是也支持這個第三(考慮到 Html 和 Javascript)語言。甚至更進一步,它決定讓這個“JavaScript Style Sheet”中介語言能夠被 web 開發者訪問(https://web.archive.org/web/19970709133056/http://home.Netscape.com/comprod/products/communicator/guide.Html )。

這個語法是直接的 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 已經添加 JavaScript 支持到 IE3(作為“JScript”)。更大的問題是社區已經團結起來支持 CSS,而 Netscape,在那個時間,被許多標准社區視為惡霸。當 Netscape 提交 JSSS 到標准委員會,沒有人理會它。三年後,Netscape 6 放棄支持 JSSS,這項技術(基本上)悄無聲息地消亡了。

可能是什麼

多虧了 W3C 組織的一些公開羞辱,在 2000 年 IE 5.5 幾乎完全支持了 CSS 1。當然,如我們所知道的,至少在接下來的十年裡浏覽器的 CSS 實現非常粗糙且難以使用。幸運地是,今天這一狀況大幅度改善了,讓開發者寫一份代碼在不同的浏覽器下得到(幾乎)同樣的結果的夢想成為現實。

我個人從這些中得出的結論是領悟到影響我們現有工具的許多決定是既有偶然性也有必然性的。如果 CSS 被設計出來時只是為了滿足 1996 年的約束,那麼可能那時它已經給了我們一個承諾 20 年後會做一些有點不同的事情。

英文原文:https://eager.io/blog/the-languages-which-almost-were-CSS/

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved