Internet Explorer 的 CSS Rendering Bug
昨天把 Movable Type 更新到 3.33 版, 想裝上 EnhancedEntryEditing 這個 plugin, 讓我們寫文章的時候可以用比較方便的編輯器來輸入. EnhancedEntryEditing 是一個利用 TinyMCE當作 Movable Type 編輯器的 plug in, 而 TinyMCE 則是一個用 JavaScript 寫的編輯器, 它可以讓網頁上的輸入區有像 Word 般的編輯能力.
幾年前開始用 So-net 的 web mail 時, 就覺得它的編輯區很神奇, 現在終於知道是怎麼一回事了, 原來都是 JavaScript 的功勞.
不過當我把 EnhancedEntryEditing 裝好後, 我的文章編輯頁 layout 居然跑掉了. 本來應該在功能表右邊的編輯區, 居然被擠到下面去了…
更有趣的是, 我在 Firefox 裡開同一個頁面, 沒有問題, 正確顯示, 像這樣:
這突然讓我想起一個老問題: 微軟的 IE 在計算 CSS 裡的寬度屬性時, 沒有照標準來. 我用一張圖來說明這個問題好了, 這張圖是從微軟的 MSDN 網站來的, 出處在這裡.
微軟自己招了, 在 IE 5.5 之前, 它的 browser 計算 "width" 這個 CSS 屬性時, 連 border 跟 padding 的寬度都一起算進去了, 但是照 CSS 的標準, width 指的是 block 物件本身的寬度.
這會造成的問題就是: 如果我設計一個 div, 設定它的寬度是 200px, border 是 50px, 在 IE 裡面我會得到一個大小是 100px, 連 border 總共寬 200px 的 div. 但是在 Firefox 裡, 我會得到一個連邊框總共寬 300px 的 div.
我猜是這問題造成 EnhencedEntryEditing 的版面 layout 混亂. 從圖上看來, 應該是編輯區在 rendering 時, 算出來的寬度超過它的 container 寬度, 放不下, 所以整個 container 就被往下擠了. 在 Movable Type 附的標準 CSS 裡, 針對 IE 的這個問題有一堆修正的 code.
靠近一點來看:
編輯區右邊的細框看起來比上面搜索文章的 banner 要凸出去一點點, 可能就是因為這個原因讓它的 layout 爆掉的. 在 Firefox 裡, 右邊界看起來是完全對齊的.
這種時候, Firefox 內建的 DOM Inspector 就超好用的, 它可以用來觀察版面上的每一個物件對應到 CSS 裡的哪個物件, 是什麼 ID 或是哪個 CLASS, 還可以直接看到 CSS 裡設定的屬性, 以及自動計算出來的屬性.
我用 DOM Inspector 從 <body> 一路往下找, 先找出整個 Movable Type 的畫面是被包在一個 class 是 .body-wrap 的 DIV 裡, 寬度是 750px. 這就是整個畫面的寬度.
.body-wrap 下面有兩個 DIV, 左邊的功能表用的 ID selector 是 #nav, 寬度是 110px; 右邊的的編輯區是一個 class 叫 .body-nav 的 DIV, 寬度是 625px. #nav 沒有設 margin, .body-nav 的 margin-left 是 15px, 所以這兩個東西中間空白的 15px 是算在 .body-nav 的帳上, 加起來剛好 750px, 不多不少. 所以只要有人出了一點點錯, 版面一定會亂掉.
IE 跟 Firefox 還有一個不一樣的地方是, 如果我設定一個 DIV 寬度是 625px, 但是它裡面包住的東西大於 625px, IE 會自動把外面的 DIV 變大, 但是 Firefox 不會. 我現在遇到的似乎是這個問題, 在 IE 裡面, 編輯區看起來明顯地 625px 多了一點點. 也就是說, 雖然 .body-nav 在 CSS 裡設的 width 是 625px, 但是因為裡面的東西比較大, 所以 IE 就把 .body-nav 的 width 調大了.
是誰把它撐爆了的 ? 應該是 EnhancedEntryEditing 的編輯區, 因為編輯區的大小在 IE 跟 Firefox 裡看起來不一樣. 我本來以為在 EnhancedEntryEditing 的 script 裡, 寬度是設死的, 我可以在 script 裡直接改它的寬度, 把它改小就好了. 沒想到去挖了 EnhancedEntryEditing.pl 後, 情況遠比我想像的複雜. 它似乎會去問 container 的寬度, 然後來決定自己的寬度.
如果是這樣的話, 它在 IE 問到的寬度, 就會跟在 Firefox 裡不一樣囉. 如果有設 padding 的話, 同樣的 width 設定下, 在 Firefox 裡問到的寬度是 width 減去左右 padding, 會比在 IE 裡問到的要小. 如果 script 在 IE 裡問到了比真正需要還大的寬度, 它就會把自己設得太寬, 讓 container 爆掉.
以上只是我的猜測, 因為 EnhancedEntryEditing 的 JavaScript 實在太複雜了, 我沒辦法搞懂它決定寬度的方法. 不過既然知道是 padding/border 計算方式不同惹的禍, 那就好辦多了, 我直接把編輯區 container 的 padding 縮小:
這樣左右各少 5 點, 總共少了 10 點, 果然塞得下了, 版面的問題解決啦.
另外根據微軟自己的說法, IE6 會根據 HTML 裡的 !DOCTYPE 宣告來決定要用哪種方法去計算 CSS 的寬度, 下次再來試試這個解法.
近期留言