CSS中的滑動門技術

來源:互聯網
上載者:User

ISSN: 1534-0295. 20 October 2003 – Issue No. 160

原文作者:Douglas Bowman

原文出自:A List Apart

中文翻譯:54player.com nobita

著作權說明:本文中文翻譯著作權歸譯者54player.com nobita所有。需要轉載發表的,請先與作者聯絡

在CSS中,一個經常被人們討論的先進之處即背景映像的可層疊性,並允許他們在彼此之上進行滑動,以創造一些特殊的效果。根據CSS2.0當前的規定,每一個背景映像都需要各自的HTML元素。在許多情況下,典型的標記已經為一般的介面組件提供了多種元素以供我們使用。

標籤導覽列就是其中的一個例子。過去,我們頻繁的使用這些標籤,並已成為了一種非常流行的網站導覽方式。現今,在CSS已被廣泛支援的前景下,我們可以為我們網站製作出更高品質和更好外觀的標籤導覽列來。你也許知道CSS可以用來“馴服”無序的列表,或許你還曾經看到過這種樣式的標籤列表:

如果我們想用和以上類似的標記,將導航標籤變成這種樣式,該怎麼辦呢?

經過簡單的設計,我們是可以做到的。

創新於何處?

我見過的許多基於CSS的導航標籤大都具有一類的特徵:矩形的色塊,也許僅僅是一個輪廓,對於當前選中的標籤則沒有邊框,標籤在滑鼠指標遊至其上時改變顏色。這難道就是CSS所能給我們的全部嗎?一連串的小盒子和單調的色彩嗎?

在CSS被廣泛採用之前,我們已經看到許多標籤導航設計中的創新之處。獨創的外形,熟練的色彩混合,以及對真實世界中許多物理介面的模仿。但是這些設計往往過分依賴於經過複雜製作、帶有文本的映像,或被封裝成若干嵌套的表格。修改文本或改變標籤的順序則需要一個複雜的過程。文本的伸縮更是不可能的,或給頁面的布局極大的影響。

純文字的導覽列比起文本即映像的導覽列更具有持續使用性和更快的載入速度。同樣,我們甚至可以為每一個映像加上alt屬性,對於弱視者,純文字更可以自由的改變大小。不足為奇的是,基於純文字的導覽列,並加以CSS樣式,又重新回到Web設計中來。但是,大多數基於CSS的導覽列設計,至今為止仍然是毫無意義的。一種最近被採用的技術(例如CSS)可以讓我們做的更好,同樣不失先前提到的那些表格和圖片標籤的效果。

滑動門技術

美觀的工藝,真正靈活的介面組件,並根據文本自適應大小,我們可用兩個獨立的背景映像來創造它。一個在左邊,一個在右邊。把這兩幅映像想象成兩扇可滑動的門,它們滑到一起並交迭,佔據一個較窄的空間;或者相互滑開,佔據一個較寬的空間,就像所顯示的那樣:

在這個模型中,一個映像掩蓋住另一個圖片的一部分。假設我們放置一些獨特的內容在每個映像的周圍,例如標籤的圓角,我們並不希望上面一副映像完全的遮蔽住下面一副。為了防止這種情況的發生,我們可以將上面一副映像(此例中的左邊那幅)控制的儘可能的窄。但仍然要保證一定的寬度來顯現標籤一側的獨特性。如果外部是圓角,我們就應該控制上面一副映像和它的弧線部分具有一樣的寬度。

如果目標在大小上增長,並超過了以上所顯示的寬度,歸咎於文字大小及字型的改變,映像會被拉開,產生不美觀的間隙。我們需要判斷的是,預測這種可擴充的量將有多大。如果在瀏覽器中改變字型的大小,目標又會如果增長呢?實際來說,我們至少應該估算到字型大小增長至300%的情況。背景映像也得適應這種增長。對於以上的例子,我們將下面(即右邊)的映像設為400*150像素,上面的設為9*150像素。

在頭腦中,始終要有這樣的認識:背景映像只是顯示一個可供內容填充的有效空間(即內容地區和padding,稱為doorway)。這兩幅映像始終和各自外部的邊角相錨定。背景映像的可見部分和在一起即形成了一個具有這種標籤形狀的空間(doorway):

如果標籤被撐大,映像即滑開,doorway變寬,映像的也將被顯露的更多:

此例中,我在photoshop中製作兩個平滑,細的3D標籤映像,如文章開頭所顯示的那樣。對於其一,內部明亮,邊框暗淡些,用來表現當前選中的標籤。將這種技巧模型應用於左右兩幅映像中,我們需要擴大標籤映像覆蓋的地區,將它裁剪成兩部分:

同樣的方式將應用到被稱為“當前”的標籤中。一旦我們完成了這四幅映像(1, 2, 3, 4),我們就可以開始用標記和CSS來製作我們的標籤了。

標籤的創造

當你在研究用CSS來創造水平列表時,會發現至少有兩種方法將清單項目安排在同一行裡。兩種方法各有千秋,但都需要CSS來解決布局所帶來的混亂。一種方法使用inline box,另一種則用floats。

方法一,可能是比較普遍的一種,是將清單項目都inline顯示。inline方法的魅力在於它的簡易性。但是,對於我們即將談到的滑動門技術來說,inline方法在特定的瀏覽器上存在一些解釋上問題。方法二,是我們將要關注的,即用floats將清單項目安排在同一行裡。令人沮喪的是,floats表面上矛盾的行為正巧迴避了自然的邏輯。儘管如此,對於解決多重浮動元素的基本認識,以及可靠浮動的意義,仍是值得討論的。

我們將用另一種浮動元素來解決浮動元素的排列問題。這樣,父類元素將子類元素完全包括起來。於是,我們就可以為標籤加上背景色彩和背景映像。非常重要的一點必須記住,緊跟在標籤後的文本元素用CSS中的clear功能來清除浮動物件。這樣避免了浮動標籤影響頁面上其它元素的位置。

我們從以下的標記開始:

<div id="header">  <ul>   <li><a href="#">Home</a></li>   <li id="current"><a href="#">News</a></li>   <li><a href="#">Products</a></li>   <li><a href="#">About</a></li>   <li><a href="#">Contact</a></li>  </ul></div>

現實中,#header div可能同樣包含logo和搜尋方塊。對於我們的例子,我們要縮短每一個錨鏈中超連結的值。顯然,這些值應該正確的包含檔案或者目錄的位置。

我們從定位#header容器開始設計列表。這樣確保了這個容器確確實實的充當了容器的作用,以包容它內部浮動的清單項目。既然元素是浮動的,我們同樣需要聲明它的寬度為100%。加入臨時的黃色背景以確保父類容器完全填滿標籤後面的整個地區。同樣,設定預設的文字屬性,確保樣式的統一:

#header {  float:left;  width:100%;  background:yellow;  font-size:93%;  line-height:normal;  }

現在,我們同樣需要為無序列表設定預設的margin/padding值為0,並去掉清單項目前面的標記。每個清單項目左浮動:

#header ul {  margin:0;  padding:0;  list-style:none;  }#header li {  float:left;  margin:0;  padding:0;  }

設定錨鏈強製作為塊對象呈遞,我們便可無憂的控制所有的樣式:

#header a {  display:block;  }

下一步,我們將右側的背景映像加入到清單項目中去(改變如粗體所示):

#header li {  float:left;  background:url("norm_right.gif")   no-repeat right top;  margin:0;  padding:0;  }

在加入左側映像之前,我們可以在效果1種看看目前為止的效果。(在效果中,忽略body中的規則。僅設定基本margin,padding,colors,text的屬性。)

---

現在我們可以將左側映像放置在錨鏈的左邊(容器內的元素)。我們同時加入padding,擴大標籤並將文本從標籤的邊緣推開:

#header a {  display:block;  background:url("norm_left.gif")   no-repeat left top;  padding:5px 15px;  }

這樣我們就得到了效果2。注意我們的標籤是如何成型的。在這裡,IE5/Mac的使用者會立刻驚奇道,“天啊,我的標籤垂直堆在一起並且延伸至整個螢幕!”不要著急,我們馬上幫你解決。眼下,盡量按照下面去做,或者方便的話,臨時改換其他的瀏覽器,並且IE5/Mac版本的問題會馬上得到解決。

---

現在,一般標籤的背景映像已經完成了,我們要為“當前”標籤更換映像。我們通過對目標清單項目加入id="current"和錨鏈來實現。既然不需要改變背景的其他外觀,映像除外,我們就使用background-image的特性:

#header #current {  background-image:url("norm_right_on.gif");  }#header #current a {  background-image:url("norm_left_on.gif");  }

我們要在標籤下添加一條邊框。但是,將邊框屬性應用於父類的#header容器上,將不能解決“當前”標籤無需邊框的問題。於是我們製作新的帶有邊框的映像以代替它。同樣,我們可以為它加入漸層效果:

我們將映像放置到#header容器的背景中去(代替原有的黃色背景),將背景映像移至到最下方,並為映像上方留出的空白添加相應的背景顏色。同時,去掉由body繼承下來的padding,為ul的上、左、右邊加進10像素的padding:

#header {  float:left;  width:100%;  background:#DAE0D2 url("bg.gif")   repeat-x bottom;  font-size:93%;  line-height:normal;  }#header ul {  margin:0;  padding:10px 10px 0;  list-style:none;  }

我們必須讓“當前”標籤覆蓋邊框,如下面提示的那樣。你也許會認為我們將要把底部邊框加入到與其顏色相對應的、#header背景映像中去,然後將“當前”標籤的底部邊框顏色改為白色。但是,對於挑剔的觀察者,還是會發現一些細小的差別。於是,我們改變錨鏈的padding,為“當前”標籤創造出直角來,如下面放大的例子:

我們通過減少1像素普通錨鏈的底部padding值(5px-1px=4px)來實現,然後為“當前”錨鏈補上減去的padding。

#header a {  display:block;  background:url("norm_left.gif")   no-repeat left top;  padding:5px 15px 4px;  }#header #current a {  background-image:url("norm_left_on.gif");  padding-bottom:5px;  }

經過改變,底部邊框將在普通標籤中出現,而在“當前”標籤中則隱藏了起來。於是,我們得到了效果3。

收尾工作

敏銳的觀察者也許會在上一例注意到白色的標籤角落。這些不透明的角用來防止下面的映像透過上面的一副。理論上,我們可以嘗試使用部分背景映像來適應標籤的背景。但是我們的標籤會在高度上增長,嘗試通過移動背景顏色,背景映像就會相對變矮。代替的辦法是,改變映像,將標籤的角落設為透明。如果弧線是反鋸齒的,我們在其邊緣使用較平均的背景色彩。

現在,角落已經變成透明色,左邊的映像將透過右邊映像的角落。為了補償,我們為表單項加入和左邊映像寬度相吻合的padding(9px)。既然已經為表單項加入了padding,我們還需去掉同樣的寬度以達到文本的置中(15px-9px=6px):

#header li {  float:left;  background:url("right.gif")   no-repeat right top;  margin:0;  padding:0 0 0 9px;  }#header a {  display:block;  background:url("left.gif")   no-repeat left top;  padding:5px 15px 4px 6px;  }

仍未結束,因為加入了9個像素的padding使左邊映像與標籤的左邊之間產生了一段空白。現在,左側與右側,可見“doorway”的邊緣接在一起,我們再不需要將左邊映像保持在上方。於是,交換兩幅背景映像的順序,相反過來。同樣交換“當前”標籤中使用的兩幅映像:

#header li {  float:left;  background:url("left.gif")   no-repeat left top;  margin:0;  padding:0 0 0 9px;  }#header a, #header strong, #header span {  display:block;  background:url("right.gif")   no-repeat right top;  padding:5px 15px 4px 6px;  }#header #current {  background-image:url("left_on.gif");  }#header #current a {  background-image:url("right_on.gif");  padding-bottom:5px;  }

完成這些後,我們到達了效果4。要注意的是,透明的角落在標籤的左側產生了一段不能點擊的無效地區。這個地區在文本以外,但仍然是可以察覺到的。在標籤的兩邊都使用透明的映像是沒有必要的。如果我們不希望產生這種無效的地區,那麼我們必須使用在標籤後面使用顏色,然後用這種顏色來代替標籤角落的透明映像。現在我們僅保持這種透明角落。

---

對於剩下的問題,我們將一次性完成全部的修改:加重標籤文本,將普通標籤中的文本改為棕色,“當前”標籤文本改為深灰色,去掉連結的底線,最後將懸停文本色彩改為同樣的深灰色。經過一系列的改變,我們將看到目前為止的效果5。

一致性的解決

在效果2之後,我們公認的一個問題就是在IE5/Mac瀏覽方式下,每個標籤延伸並佔據了整個瀏覽器的寬度,以致標籤垂直的堆在了一起。這不是我們所希望的。

在大多數的瀏覽器中,浮動一個元素會有收縮,收縮最小至它所包含內容的大小。如果一個浮動元素包含一幅映像或其本身即映像,便會收縮至映像的寬度。如果僅僅包含文本,那麼將會收縮至最長的,不可被頂開的那文本的寬度。

一個問題出現在IE5/Mac中的圖片中,當一個auto-width的塊對象元素被插入到一個浮動的元素中時。其他的瀏覽器仍舊將浮動縮小至最小,而無視容器內的塊對象元素。但IE5/Mac並不按照這種情況,相反它將浮動和塊對象元素擴充至儘可能的寬度。為解決這個問題,我們將錨鏈同時浮動起來,但僅僅對於IE5/Mac,以免放棄其他的瀏覽器。首先,我們為錨鏈設定浮動規則。然後,我們使用反斜線注釋法來隱藏這種規則,讓它僅僅對IE5/Mac生效,而無視其他的瀏覽器:

#header a {  float:left;  display:block;  background:url("right.gif")   no-repeat right top;  padding:5px 15px 4px 6px;  text-decoration:none;  font-weight:bold;  color:#765;  }/* Commented Backslash Hack   hides rule from IE5-Mac \*/#header a {float:none;}/* End IE5-Mac hack */

現在IE5/Mac瀏覽器將按我們所期望的那樣來顯示標籤,看效果6。對於非IE5/Mac的瀏覽器什麼都不需要改變。注意到IE5.0/Mac的一系列解釋上的bug在IE5.1中解決。因此,滑動門技術在5.0版本中所遭遇的問題超出了hack的限度。既然升級到IE5.1/Mac已不成難題,OS 9 Macs/IE5.0的佔有率應逐漸縮減至很低。

舉一反三

我們剛剛演練了滑動門技術,用純文字和無序列表來創造導航標籤,加以少量的樣式。它的裝載速度快,具有可維持性,並且文本的大小可以在不破壞外觀的情況下進行較大的伸縮。不必我們再重申在創造複雜樣式的導覽列中,滑動門技術所表現出來的彈性了。

只有想不到,沒有做不到。最終效果向我們展示了一例,但我們設計不可能因此而被限定死。

在某些場合,標籤不一定是對稱的。我很快就製作了這種標籤的第二個版本,也有陰影3D的樣式,有角的邊緣,和具有特色的左邊部分。依據第二個版本,我們甚至可以交換左右兩幅映像的位置。以這種細緻的布局和靈巧的映像控制,我們可以去掉按鈕的下邊框以便標籤映像更好的去適應背景,如第三個版本所顯示的那樣。如果你的瀏覽器支援多個樣式表的切換,你甚至可以靠它在多個版本的導覽列之間自由切換。

仍有許多我們沒有提到的其他的效果。快速的提一下,我改變滑鼠移至上方的文本色彩,但是真箇映像可以替換掉以創造出更有趣的變換效果。即使標記中兩個嵌套的HTML元素,也可以用CSS來達到一些我們還未想到的效果。我們在此例中創造的僅僅是水平的標籤欄,但滑動門亦可應用於許多其他的情形。閣下覺得如何呢?

本文的其他語言版本
英語(alistapart.com)

意大利語(gdesign.it)

俄語(id-as.com)

點擊此處參加關於本文的討論

Translated with the permission of A List Apart Magazine and the author[s].

譯者的話:第一次翻譯文章,對許多用詞不置可否,難免有一些錯誤,期待讀者們的指正。

Email:mencken.wong(at)gmail.com

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.