1. 程式人生 > >pseudo-class, pseudo-element, pseudo-CSS

pseudo-class, pseudo-element, pseudo-CSS

偽元素和偽類

這篇文章打算總結偽類和偽元素的 bugs 以及在 IE6/Win 和 IE7 beta3 中表現的不一致性。 

The :first-letter pseudo-element

語法

IE6: 在選擇器 selector 和 宣告塊 declaration block 之間必須得有一個空格 blank- 這與在標準模式下正常解析的行為是不一致的。(fixed id IE7b2) 。

IE6,IE7b2 : 還有另外一個問題:"逗號前面沒有空白"的問題,請看


Specificity

IE6 : 偽元素會匹配其他的 #id rules ,這種奇怪的行為違背了規範。在下面的例子中,就算在頁面上沒有 id=nonexistent ,#content 所有的 block-level links 在 hover 時也會出現綠色的 first-letter 。(fixed in IE7b2)


如果是 inline-level ,當hover時就不會變成綠色。

在IE6,7b3 : 這裡還有一個奇怪的行為 : IE把 first letter 渲染為 2em ,但是 link 是藍色的斜體。


偽元素的表現篡改著規範 - 除錯者的慘狀。通常,不推薦使用 !important 這個 workaround 來修復 IE6,因為 !important 本身在 IE6下就存在bug 。

繼承 Inheritance

IE6,7b3 : 如果偽元素未設定尺寸 undimensioned (non-layout) ,那麼它通過 em 來設定 margin 的話  (em-margin) ,會繼承它自己的 em font-size 。下面的例子,first-letter 顯示 3em margin-left 。 (也就是說 p 如果不具有 layout ,那麼如果用 em 來設定 margin ,字型也用em,那麼 margin 實際上是 font-size 的大小。)


一個解決辦法 (workaround) 是讓 p 元素獲得 "layout" 。

應用的不穩定性:另外一個元素毗連偽元素 Application instability: another element adjacent to the pseudo-element

IE6,7b3: 更糟糕的是,當你讓一個偽元素成為另外一個元素的一部分,或馬上在偽元素後面跟另外一個元素,這可能燒燬你的 Win XP SP2 PC/Virtual PC 。看看這個例子,當排版時,強調首個字的句子。



first-letter錯誤的繼承了 left margin 。span也繼承了,導致一個 (font-size:) 2 X (margin-left:) 3em 的空白 (gap) 。另外,從span開始3em的地方,有一個區域繼承了margin,padding,border和background-image!

的現在,當 .ipsm 通過獲得layout的子集中 (position:absolute;/float:any value;/display:inline-block;/zoom:1;)獲得了 "layout" ,將會發生什麼呢?是的。有些要停止程序,有些要重啟,資料會丟失。別這樣做。


的解決方法是使用下面規則 rules 中的一個,也許是因為這回又一次改變特徵所以 span 不會試著去繼承。


The bug is already tracked by Quirksmode's Bug Report and was filed to MS once more in Feb. 2006.

有序和無序列表

IE6,7b3 : 在有序列表中,li:first-letter 作用在列表項和序號上。有序列表也是一樣的。 


浮動

IE6,IE7 : 看起來 first-letter 偽元素只支援 float : left  。它不能被 float: right 重寫,也不能被 float:none; 重置。


The :link and :visited pseudo-classes

A human bug

人們語言的理解有時會導致一些錯誤,但是這跟瀏覽器無關。

:link 偽類 (pseudo-class) 作用在那些還沒有被訪問過 (visited) 的元素上。一旦link 被使用者訪問過,:visited 偽類就會生效。這兩個狀態相互排斥。

:visited but not visited

IE6: 當我們在設計頁面的時候使用 "#" 的時候 <a href="#">link</a> , 一旦頁面載入完成,IE 宣告這些連結為 visited (fixed in IE7b3)。這可能導致當一些引用被包含進來時出現一些驚人的差異。


The :active adn :focus pseudo-classes

IE6 ,7b3 : :active 被實現了。

IE6,7b3 : :focus 沒有被實現。

因為 :focus 沒有被實現,一個解決方法是使用 :active 偽類。

a:focus, a:active {property: value;}

當用戶通過返回按鈕返回時,連結仍然保持 :active 

只有IE6,7b3這樣,其它瀏覽器都不相容。

The :hover pseudo-class

:hover is limited to links in IE6

IE6: Well tested workarounds to achieve whatever:hover are csshover.htc and IE7 { css2: auto; }.

IE7b3: Implemented, see [ testcase ].

後代選擇器: 子元素不能獲得 :hover 傳遞

的IE6: 一個經常被問到的問題就是,為什麼下面的程式碼在 IE6 下不起作用,其他瀏覽器都可以用。

a:hover img {border: 1px solid fuchsia;}

還有為什麼這樣一個 bugfix 就會起作用?(And why can a bugfix like the following ever work?)

  1. a:hover img {border: 1px solid fuchsia;}
  2. a:hover {background-position: 0 0;}

One hypothesis (假設) looks at the signal chain of redraw events:

  1. a_hover(redraw=true)
  2. calls
  3. img(redraw=true)

這個假設是說,IE沒有把 hover 的傳遞(transition) 看作是一個整體除非存在 a redraw event triggered (一個重畫事件被觸發) - 外部通過重畫 the window ,內部通過重新設定      a:hover 的 background 位置或由於其它作用在 a:hover  上的屬性的子集。這些屬性將標誌著在 on hover 過程中有些東西會發生變化。

一個沒有任何邏輯的處理是 background-position:0 0; ,就算根本就沒有 background-image 它標誌著  a change on hover 。

Stuck on hover 

IE6:有時 background-images 在 on hover 時,當滑鼠移開後,好像被卡住了,不消失。根據background-iamge的大小與元素大小的關係和其它因素(不透明),當連結覺有 "layout" 時,hover-state 可能 "click in" 。當滑鼠指標離開 the hoverable area,背景被錯誤的 redrawn 。當 scrolling 或者 page reload 後,這種效果會消失。

一個修復的辦法是 "un-layout" the link ,但這大多數情況下不可能,由於 layout 進退兩難: 或者是因為寬度是必須的,或者是浮動,或者其它原因。當layout元素 "自己負責drawing 它們的內容",猜猜當 :hover-transition 被處理後誰來負責。

一個更好的修復方法,類似於上面的 "descendant selectors"-fix :我們可以強制它 redraw, a rearrange on hover。



作為一種選擇,如果 background-position 可以使用,我們也可以顯式的設定 background-repeat 或 background-color 。不管怎樣,IE6-flicker 問題依然存在,這個問題和不同的bug相關。

Sticky hover state on click

IE7 : 一個 stuck-on-hover 的變種,當 mouseclick 後 hover state 沒有變回來。Click on a drop down menu entry in a Son of Suckerfish drop down menu 。

同樣,修復辦法是改變 hover 本身。

#nav li:hover {background-position: 0 0;}

IE6沒有這個bug是因為 javascript 已經處理了 li 的滑鼠事件。

Part of a floated element disappears on :hover

IE6: 這最有可能是 Guillotine Bug相關 (fixed in IE7b2)。

Jump on :hover as a consequence of the re-flow 

IE6 : 一個CSS的基本概念就是,頁面是增量渲染的incrementally rendered,所以使用者不用等到所有元素都載入完成。在IE中一個非常特別的情況是允許容器自動擴充套件寬度和高度 ("expand-to-fit") ,甚至已經設定了尺寸來強制元素的範圍時也是如此。現在,概略的,假設是錯誤的。On :hover ,IE re-renders the elements of a "layout" block ,元素 re-flow ,但是這時,IE所有的尺寸 (他們在第一次就確定下來了)都知道了。這就導致了 a jump on hover ,特別是在用百分比設定 margins 和 paddings 時percentage margins and paddings(例如,Holy Grail layout jump)在其他 bug-related situations 也會看到。The jump 經常會修正初始化時的錯誤的擺放,我們必須在 hover 事件發生之前找出錯誤擺放的地方。

IE7 : 跟IE6一樣,憑經驗就是 相對定位的容器需要設定 hasLayout ,否則奇怪的事情,像消失或 子元素jumping 可能發生。 A :hover 事件可能是觸發器。在這種情況下檢查父元素的 haslayout-state 。

跟這個無關的是,有時 "trivial" 引起 a jump on hover 是在僅在 hover-state 時宣告 border ,這種情況的修復辦法是給 link 一個跟背景色一樣的邊框。  

The chaining of pseudo-classes

IE6: 這個有效的串聯在 IE6/Win 中不起作用。在這個例子中,所有的 hovered links become red (fixed in IE7b2) 。