為物件指定 hasLayout property

  • 說明: ie 專有用法 (ie only)。部分 ie 專有的特性 (property) ,如 filters and transitions ,有作用的必要條件就是指定 hasLayout 性質。 hasLayout 性質本來是微軟為了補救 ie 內部不完善所自創的,並非 w3c 標準,所以有時用起來覺得相當無厘頭。但神奇地, ie7 以前舊版衍生的網頁不正常呈現問題 (ie bugs),大多數竟可由指定 hasLayout 來解決。
  • 適合:有 htmlcss 語法撰寫基礎者。
  • 難度:等級4
  • 更新:
  • 適用:ie7 ~ ie5.5

hasLayout "property" 和 css property 雖然英文名稱一樣,但實際上不太相同。 hasLayout 本身並非 css 特性的一種,所以沒辦法直接定義物件的 css 特性 hasLayout 的值 (value),而是間接以其它的 css 特性指定在物件上,使該物件符合 hasLayout ,所以我比較傾向稱它是 hasLayout 「性質」。

符合以下任一種 css 特性及值的定義方式,物件即是 hasLayout (有編置) :
ie 7 增加了幾個新的指定方式:

認識 hasLayoutcss 規則

上述規則有的看起來有點含糊,有的好像又很陌生,那要怎麼正確定義物件 hasLayout 呢?

heightwidth 特性只需要指定一個「具體值」 hasLayout 就有效了,如 width:80%; ,甚至 height:0; 也可以喲。 min-height, max-height, min-width, max-width 等特性也可以如法炮製,如 max-width:100em; 或是 min-height:0;。需要注意的是依據 css 規則,這類特性在行內層級 (inline-level) 元素不會有作用。

float 特性通常有 float:left;float:right; 二種值都可以達成 hasLayout

position:absolute;position:fixed; 算是同類型的定義,二者都能使 hasLayout 有效,只是 "fixed" ie 6 沒支援。

zoom 特性看名稱就知道是縮放大小,像 height 之類一樣,只要有「具體值」 hasLayout 就有效了,而且行內層級元素也能作用,如 zoom:0.9; 。撰文時這個特性僅為 ie 專用 (ie only) ,非 w3c 標準,所以非 ie 瀏覽器 (firefox, opera, safari, …) 沒有支援也就不會有任何影響。

指定 overflow 特性通常有 overflow:auto;, overflow:hidden;overflow:scroll; 三種值,雖然 ie 6 有支援,不過目前只有 ie 7 會讓 hasLayout 有效。而 overflow-xoverflow-ycss3 的規則,撰文時僅 iefirefox 支援。

writing-mode 特性也是 css3 的規則,比較少會用這個特性指定 hasLayout ,撰文時也僅 ie 支援。

物件原則上預設都是不具 hasLayout 性質,所以我們才需要特別指定 hasLayout ,但是有部分元素在 ie 預先就已內定永遠為 hasLayout ,明細可參閱 Microsoft 官方文件

卸除 hasLayout 性質

當然,可以反向定義物件 hasLayout 性質為無效,不過部分元素已內定 hasLayout 就沒辦法使其失效的。會用到卸除 hasLayout 的時機,都是針對已指定過 hasLayout 的物件,卻可能因某些目的而必須轉回無 hasLayout 。所以,通常只要將原先定義 css 特性,再重新定義回「預設值」,就會讓物件的 hasLayout 性質無效了。

css 特性及值再定義成以下任一種方式,即可使 hasLayout 無效 (卸除) :
  • height: auto;
  • width: auto;
  • max-height: none;
  • max-width: none;
  • float: none;
  • position: static; (預設值)
  • overflow: visible;
  • overflow-x: visible;
  • overflow-y: visible;
  • zoom: normal;
  • writing-mode: lr-tb; (預設值)

舉例子看看就明瞭了:

xhtml
<div id="main">
 <p>漁舟逐水愛山春,兩岸桃花夾去津。坐看紅樹不知遠,行盡青溪不見人。</p>
 <p>山口潛行始隈隩,山開曠望旋平陸。遙看一處攢雲樹,近入千家散花竹。</p>
 <p class="extract">節錄自:王維的桃源行</p>
</div>
css (例一)
#main p {float:left;}
#main .extract {float:none;}
css (例二)
#main p {zoom:125%;}
#main .extract {zoom:normal;}

兩例的 css 都類似情形,前一條定義先讓全部三段 p 成為 hasLayout ,後一條再讓最後一段的 hasLayout 無效。需要了解的是,卸除 hasLayout 的規則是定義在 hasLayout 規則之後的另一組指標 (selectors) 裡,而且是取代先前「相同的」特性,前面用 float 指定,後面就要用 float 來卸除,這本來就是依循 css 的規則,只是再提醒一下而已。

無法卸除 hasLayout 的定義

display:inline-block; 指定 hasLayout 後,就沒辦法卸除,無論再定義回 display:inline;display:block;hasLayout 依然維持有效,所以上述卸除規則沒有這項,這點必須注意。

由於 min-heightmin-width 的預設值是 0,所以縱使再定義為 min-height:0; (具體值),也無法卸除 hasLayout 。但是 ie 卻接受 min-height:auto;min-width:auto; 來卸除 hasLayout ,特別須注意的是 auto 值並非 w3c 標準,所以沒有把它列在上述卸除規則。

思考 - hasLayoutcss hacks 拯救 ie bugs

本篇一開始就提到,為物件指定 hasLayout 性質就可以修復很多 ie 令人噴飯的 css bugs (hasLayout 大部分可修復背景不正常及 position 特性位移等問題) ,有幾種目前公認穩定又好的方式,但是有時必須搭配 CSS hacks ,才可以在不同瀏覽器正常地呈現,而如果需要通過 W3C validation ,用到非 w3c 標準語法時就需要運用 Conditional Comments 把語法隔離起來。

xhtml
<div id="main" class="hasLayout">
 <h2>早梅 張謂</h2>
 <p>一樹寒梅白玉條,迥臨村路傍溪橋。不知近水花先發,疑是經冬雪未銷。</p>
</div>
css
.hasLayout {min-height:0;} /* ie 7 hasLayout 生效 */
* html .hasLayout {height:0;} /* hack ie 6 hasLayout 生效 */

上面 css 語法例子符合 w3c 標準,是很穩定的好方法,只是語法感覺有點冗長。 min-height:0; 本來就是預設值,加了此項其實是多餘的,所以對任何瀏覽器不會有影響,也就不需要用到 hacks ;而 min-height:0;ie 7 可驅使 hasLayout 生效,難纏的 ie bugs 也就隨之解決了。但是, height:0; 在不同瀏覽器上呈現有很大差異,所以就必須採取 css hacks 的技巧。 ie 7 與 ie 6 的 bugs 未必會在同一個物件同樣發生,所以,上述語法並沒有要求一定兩項條件都要同時存在,比較常出現 bugs 會是在 ie 6 ,可以視狀況加入其中一項或兩項囉。另外需要提醒的是,依據規則此方法在「文字層級」物件沒有作用。

承上 xhtml 例,再看另一種 css hasLayout 作法。

css
#main {zoom:1;}

zoom 指定 hasLayout 算是精簡的好方法, ie 5.5 以後版本就有支援。 zoom:1; 維持物件原來大小不作任何改變,但可驅使 hasLayout 有效,而且不論區塊層級或行內元素都有作用;非 ie 瀏覽器尚未支援 zoom 特性,所以完全不受影響,也就不需要用到 hacks 。唯一的小問題只是 zoom 並未納入 w3c 標準。

再看不同的例子。

xhtml
<div id="nav">
<ul>
 <li><a href="#">王維-陽關曲</a></li>
 <li><a href="#">張謂-早梅</a></li>
 <li><a href="#">杜甫-客至</a></li>
</ul>
</div>
css
#nav li a {display:inline-block;} /* hasLayout 生效 */
#nav li a {display:block;}

此例在版面設計常會遇到,因設計需要必須將行內元素 a 轉換成區塊層級呈現 (改變物件的 display 特性) ,很明顯地,加了 display:inline-block; 這項其實是多餘的,因為元素 a 還是會依照其後定義的 dislpay:block; 呈現,所以任何瀏覽器的呈現也不會有差異;而 display:inline-block; 驅使 hasLayout 生效, ie bugs 也就隨之解決了。這個方式 ie 5.5 以後版本就有支援,完全符合 w3c 標準,精簡且不需要用到 css hacks ,適當地運用也是一個很好的技巧。

最後叮嚀,不要想偷懶企圖使用像 * {zoom:1;} 的方式一次指定所有物件,發生問題的時候恐怕沒人救得了你;指定 hasLayout 性質的方式算是不少了,學習在不同情況下,針對有問題的物件變換最恰當的語法來修復 ie bugs ,才是網頁設計者應有的態度。

參考資源
散佈、展示請參閱 Creative Commons 授權條文,禁止重混,引述請增加原文連結。
文章標籤

不惑仔 發表在 痞客邦 PIXNET 留言(1) 人氣()