close

樹狀選單加入樹狀線條的設計

  • 說明:設計具有樹狀線條的資料夾選單或樹狀選單 (folder menu or tree menu)。本篇的討論僅適用一層子選單,更多層子選單的設計方式,以後再討論。
  • 適合:有設計網頁及撰寫 css 語法經驗者。
  • 難度:等級5
  • 更新:

以下將會討論如何巧妙運用 css 基本特性 (property) 來完成這個實例。

先了解 xhtml 這部分內容的安排。
<div class="TreeMenu">
 <div class="section">
  <h1>古文今讀</h1>
  <ul>
   <li><a href="#">上古神話</a></li>
   <li><a href="#">詩經</a></li>
   <li><a href="#">楚辭</a></li>
   <li><a href="#">諸子散文</a></li>
   <li><a href="#">漢賦選輯</a></li>
   <li><a href="#">樂府</a></li>
   <li><a href="#">駢文</a></li>
   <li><a href="#">唐詩</a></li>
   <li><a href="#">宋詞</a></li>
   <li><a href="#">元曲</a></li>
   <li><a href="#">章回小說</a></li>
  </ul>
 </div>
 <!--.section-->
 <div class="section">
  <h1>現代文藝</h1>
  <ul>
   <li><a href="#">小說</a></li>
   <li><a href="#">散文</a></li>
   <li><a href="#">性靈小品</a></li>
   <li><a href="#">新詩</a></li>
   <li><a href="#">翻譯小說</a></li>
  </ul>
 </div>
 <!--.section-->
</div>
<!--.TreeMenu-->

本篇範例的完整 css 設計內容

思考 - css 設計的構思與佈局

我們儘量以探討方式介紹,引導如何構思及擴展 css 設計,希望能激發更多設計想法為主,避免陷入步驟式或教條式的悲慘學習模式。

開始:定義一些基本的 css 設計

最外圍的 .TreeMenu 指定寬度 (width) 、背景顏色 (background)、邊線 (border) , 而 h1 指定字體大小 (font) , a 去掉底線, ul, h1 去除周圍距離 (padding, margin) 等等。

css
h1, ul {
 margin: 0;
 padding: 0;
}
.TreeMenu {
 width: 10em;
 background: rgb(92%,86%,100%);
 border: 1px solid rgb(60%,60%,80%);
}
.TreeMenu .section h1 {
 font-size: 100%;
 font-weight: normal;
}
.TreeMenu .section ul {
 list-style: none;
}
.TreeMenu .section li a {
 text-decoration: none;
}

line-height (行高) 是設計的主要概念

視覺性的瀏覽器通常會預先賦予每行「大於一個字」的行高 (line-height) ,為了避免不同瀏覽器間產生的差異,以及後面設計 css 時有所依據,先將整個選單內 line-height 定義為「字高度」的倍數,例中為 1.1 倍,看起來行距應該會較原來更緊一點。由於 line-height 特性 (property) 有繼承性 (inheritance) ,所以只需要定義一次在 .TreeMenu.section 就可以;這裡也順便為分類標題 h1 加背景色修飾一下。

接續前面,增加 一點 css 定義 (紅字)
.TreeMenu .section {
 line-height: 1.1;
}
.TreeMenu .section h1 {
 font-size: 100%;
 font-weight: normal;
 background: rgb(85%,70%,90%);
}

我們只以倍數定義行高,也沒有指定字體的尺寸 (font-size),如此是為了使全部的設計,單純地以字高 (em) 的倍數來計算,不用去管字體到底幾個像素 (pixel) 大,或者一行有多少像素高。想指定 font-size 當然可以,不過行高最好還是以倍數的方式指定,設計時才不至於太難計算;這只是建議囉,全部都用像素為單位也沒問題,計算清楚,小腦袋瓜別爆掉就好。

產生樹狀的垂直線條

ul 左側加上線條,當做樹狀結構的垂直線,並且左邊空出一點距離,讓子選項內容 li 看起來向內縮排。這個距離應該是要對應分類標題 h1 來設計,我們指定了向內縮半個字 (0.5em),所以線看起來像是由標題第一個字中間向下延伸;標題最前面如果變成小圖示 (icons) ,那就以圖示寬度的一半去定義縮排距離也可以。這裡應該以 margin 來指定內縮距離,因為我們必須讓垂直線緊貼著 li 。線條寬度沒有使用 em 定義,是因為 1px 寬幾乎沒什麼影響,但是如果需要設計較粗的線,單位最好一致。

在前面已指定的 ul 增加 css 定義 (紅字)
.TreeMenu .section ul {
 list-style: none;
 margin-left: 0.5em;
 border-left: 1px dotted;
}

我們沒有特別指定線條 border 的顏色,將會與該區域字的顏色相同,如果想另外定義顏色,可以像這樣,

border-left: 1px dotted rgb(255,0,0);

線條要改成實線也可以, dotted → solid ,當然其它形式的線條也可有更多變化。

產生樹狀的水平連接線條

在子選項 li 下方加上線條,當做樹狀結構子選項的橫連接線。這裡也讓 li 的內容 a 向內縮排,不過,不同於前面,我們必須保持每個 li 下方的線與左側 ul 的線緊緊相接,所以在 li 指定 padding ,僅讓內容 a 向內縮,但 li 本身沒有縮排。

接續前面,增加 licss 定義
.TreeMenu .section li {
 padding-left: 0.5em;
 border-bottom: 1px dotted;
}

border 也沒有特別指定顏色,這樣可以對應前面 ulborder 顏色,如果想另外定義顏色,方法同前。

css position:relative;a 向下位移 (offset)

css position:relative; 主要的特點就是,元素可以由本身的 Box 位移,並且保留其它元素原來的排版。利用這個特點,只要讓 a 向下位移半行,而 li 會維持原來的位置及下方的橫線, a 的中間就會剛好壓在 li 的線上。前面已經指定 line-height:1.1; (1.1倍的字高),所以半行就是 0.55em ,太棒了,只有 a 向下移,所有 a 以外的東西都不會動。

在前面已指定的 a 增加 css 定義 (紅字)
.TreeMenu .section li a {
 text-decoration: none;
 position: relative;
 top: 0.55em;
}

由於水平線條只有 1px 厚度,對整個位置並無影響,可以不需考量;但是如果指定了較粗的線條,就需要顧慮到線條的厚度會佔掉空間,向下位移的距離應該多加半個線的厚度,這也是為什麼前面有提醒要注意單位一致的原因,如果線的單位是 px ,而行高em,那還真有點難算。

背景顏色蓋掉重疊的線

明顯地,現在面臨兩個問題:一、字的背面不應該有線。二、因為 a 的向下位移,造成與下一個分類重疊。第二個問題稍後再討論。第一個問題比較容易處理,我們為 a 指定背景色就可以蓋住 li 的橫線了,由於 a 本身為行內層級元素 (inline-level elements) ,所以背景色只會在有字的區域呈現。如果 a 不想有背景顏色,只要指定與 .TreeMenu 相同的背景色, a 看起來就像沒有背景色的樣子。

在前面已指定的 a 增加 css 定義 (紅字)
.TreeMenu .section li a {
 text-decoration: none;
 position: relative;
 top: 0.55em;
 background: rgb(80%,85%,100%);
}

如果想讓字之後的整條線都蓋掉,只要把 a 轉換成區塊層級 (block-level) 呈現即可。

繼續為 a 增加 css 定義 (紅字)
.TreeMenu .section li a {
 text-decoration: none;
 position: relative;
 top: 0.55em;
 background: rgb(80%,85%,100%);
 display: block;
}

此時會看到子選項內容 a 之間有 1px 的間隔,這是因為 a 的實際高度本來就比 li1px 高 (lia 多了線條的高度)。

增加距離避免重疊,就算完成了。

只要在分類間加一點距離,重疊的問題就解決了,為 .section 下方加上 padding 應是較恰當的方式。為了分類裡面的上下距離看起來一樣 ([上古神話]上方與[章回小說]下方) ,我們指定了 padding-bottom:1.1em; ,與行高相等的距離。

在前面已指定的 .section 增加 css 定義 (紅字)
.TreeMenu .section {
 line-height: 1.1;
 padding-bottom: 1.1em;
}

換成在 ul 下方增加距離也可以,不過,只能以 margin 來定義,因為 padding 會使左側的線跟著向下延長,就不會與最後一個 li 的橫線緊接了。

目前應該已經算是完成囉,只剩下修飾更好而已。

hasLayout 處理 ie bugs

ie 7 或 ie 6 ,在 ula 可能會發生高度失準或背景圖片移位的問題,解決這類的 bugs 常用的方式是 hasLayout property 。由於目前在 ie 8 都還正常,為了清楚區隔,我們最好運用 css hacks 技巧。

視問題的區域,自行斟酌增加 css 定義
*+html .TreeMenu .section ul {
 zoom:1;
} /*hack ie7*/
* html .TreeMenu .section ul {
 zoom:1;
} /*hack ie6*/
*+html .TreeMenu .section ul a {
 zoom:1;
} /*hack ie7*/
* html .TreeMenu .section ul a {
 zoom:1;
} /*hack ie6*/
如果 a 還是有高度或不正常間隙問題
*+html .TreeMenu .section ul a {
 zoom:1;
 vertical-align:top;
} /*hack ie7*/
* html .TreeMenu .section ul a {
 zoom:1;
 vertical-align:top;
} /*hack ie6*/

在子選項前加小圖示,並且做最後修飾

以小圖示作為 a 的背景,並且指定左邊 padding 距離,讓 a 的內容文字向內縮排,才不會與小圖示重疊。例中的小球圖示 (ic008.png) 寬度 10px ,我們指定它的位置在 a 的最左側並且上下居中,這樣會讓小球剛好緊接在 li 的線後,然後左側 padding 距離為 15px ,讓字不要與圖看起來太緊鄰。另外,把 a 的背景顏色指定成與 .TreeMenu 相同。

我們也在 a 及標題 h1 上下加了一點 padding 距離,讓字看起來不會與邊緣太緊鄰。不過, a 上下各增加了 0.25em ,表示整行的高度也增加了,所以,向下位移的 top 定義也需要對等增加 0.25em 的距離 (0.55 + 0.25 = 0.8em) ;而 .section 下方的 padding 距離也應該增加為 1.6em (1.1em + 0.25em + 0.25em) 。

範例完整的 css 設計
h1, ul {
 margin: 0;
 padding: 0;
}
.TreeMenu {
 width: 10em;
 background: rgb(92%,86%,100%);
 border: 1px solid rgb(60%,60%,80%);
}
.TreeMenu .section {
 line-height: 1.1;
 padding-bottom:1.6em;
}
.TreeMenu .section h1 {
 font-size: 100%;
 font-weight: normal;
 background: rgb(85%,70%,90%);
 padding-top: 0.25em;
 padding-bottom: 0.25em;
}
.TreeMenu .section ul {
 list-style: none;
 margin-left: 0.5em;
 border-left: 1px dotted;
}
*+html .TreeMenu .section ul {
 zoom:1;
 padding-bottom:1px;
 margin-bottom:-1px;
} /*hack ie 7*/
* html .TreeMenu .section ul {
 zoom:1;
 padding-bottom:1px;
 margin-bottom:-1px;
} /*hack ie 6*/
.TreeMenu .section li {
 padding-left: 0.5em;
 border-bottom: 1px dotted;
}
.TreeMenu .section li a {
 text-decoration: none;
 position: relative;
 top: 0.8em;
 background: rgb(92%,86%,100%) url(ic008.png) no-repeat left center;
 display: block;
 padding: 0.25em 4px 0.25em 15px;
 margin-bottom: -1px;
}
*+html .TreeMenu .section ul a {
 zoom:1;
 vertical-align:top;
} /*hack ie 7*/
* html .TreeMenu .section ul a {
 zoom:1;
 vertical-align:top;
} /*hack ie 6*/

前面提到由於 li 的下方線條使 a 之間會有 1px 間距,只需要在 ali 指定 margin-bottom:-1px; (綠字),就會使 li 之間有 1px 重疊, a 之間就沒有間距了,不過, ie 7, ie 6 最後一個 li 的線會看不見,修正方式也加在 hacks 裡了 (綠字) ,有興趣可以自行試試。

 
散佈、展示請參閱 Creative Commons 授權條文,禁止重混,引述請增加原文連結。
arrow
arrow
    文章標籤
    css 設計 樹狀 li ul
    全站熱搜
    創作者介紹
    創作者 不老師 的頭像
    不老師

    網頁藝術思考 - CSS 網頁設計藝術

    不老師 發表在 痞客邦 留言(4) 人氣()