再會了,CSS Hack

此篇文章最近更新時間為2009-05-31 06:38:00 目前共有15篇留言

關於作者 - JosephJ

任職於 Faria。喜好戶外運動、2008 年 5 月完成「跑步環島」。對於新技術跟程式碼有著強烈的偏執狂。

每天都會用到的 CSS Hack

之前當前端工程師 (F2E) 時,常得對不同瀏覽器的 CSS 樣式做非常細微的處理,以知識+ 的某個 Rule 為例:
.ykpmodule .hd div h3 {
     padding:9px 7px 0;
     *padding-bottom:4px;
     _padding-bottom:0;
}
第 1 行是所有瀏覽器、第 2 行是所有 IE、第 3 行是 IE6 含以前,但第二行被第三行影響到後,只有 IE7 以後會套到,這樣的方法算簡單。加上公司有規定 DOCTYPE 套用 YUI Reset 與 Fonts,建立了良好的 CSS 撰寫環境,所以一直以來都只用到這兩種 CSS Hack 就幾乎可以滿足所有需求。

此 CSS Hack 所碰到的問題

之前覺得此方法不方便時是在 Study 一套叫 CSSTidy 的工具:它不但可以做最小化(去除換行與空白)、也可以整理多個相同的 Rule 成一個、及把屬性與屬性值縮減成最短。但就是死在 * 這個 Hack,改了好久都不成功,反正只是 Nice to have,放棄不用也沒差。
而最近 IE8 一直都沒有好的 CSS Hack 可以應用,只能在 Header 裡面切換到 IE7 Compatible,不是個好的或標準的解法。同事中肯兄是建議用 Conditional Comment 來解決:
<!--[if lt IE 7 ]> <body class="ie6"> <![endif]-->
<!--[if IE 7 ]> <body class="ie7"> <![endif]-->
<!--[if IE 8 ]> <body class="ie8"> <![endif]--> 
<!--[if !IE]>--> <body> <!--<![endif]-->
這種方法還不錯,因為可以只用一個 CSS 檔案、不同的 Class 來做,針對 IE 不需要使用任何的 Hack:
.ykpmodule .hd div h3 {padding:9px 7px 0;}
.ie6 .ykpmodule .hd div h3 {padding-bottom:0;}
.ie7 .ykpmodule .hd div h3 {padding-bottom:4px;}
.ie8 .ykpmodule .hd div h3 {padding-bottom:2px;}

但是用 Conditional Comments 的問題就在於不標準,此外僅 IE 支援,我個人也很討厭在 HTML 裡面還要有一些奇怪的邏輯判斷。就在想有沒有一些更好的解法...

什麼是 browscap?

先前老爹有吩咐,叫我花點時間瞭解一下 browscap,研究後才發現這是解決 CSS Hack 的王道啊!browscap 是由 Microsoft 提出,藉由 Web Server 定期的自動更新一個叫 browscap.dll 的檔案,讓程式可以從 Header 的 User Agent String 中對應出正確的 Browser 與 Operation System、以及其版本。但微軟提出了這個計畫後並沒有持續地更新這個檔案。還好有位叫做 Gary Keith 的好心人,藉由每個禮拜日分析自己網站上的 Log 檔、更新 browscap.ini 檔案並提供其他人下載使用。(browscap 官網

安裝 browscap 的步驟

使用起來很簡單,我是 Apache 2.0 + PHP5 + Debian 的環境,依照以下步驟執行即可:
  1. 將檔案 copy 回自己的機器:
    > curl http://browsers.garykeith.com/stream.asp?Lite_PHP_BrowsCapINI > ~/browscap.ini
    > sudo mv ~/browscap.ini /etc/php5/apache2/.
    
    
  2. 修改 php.ini
    > sudo vim /etc/php5/apache2/php.ini
    
  3. 把 browscap 的註解拿掉,改為:
    [browscap]
    browscap = /etc/php5/apache2/browscap.ini  
    
    
  4. 重新啟動 Apache:
    sudo /etc/init.d/apache2 restart
    
  5. 裝好之後,你可以寫個簡單的 PHP 來看看是否正確:
    <?php
        $browser = get_browser();
        print_r($browser);
    ?>
    
PHP 官方的 get_browser 的 function 頁面也有特別推薦要更新此檔案才能讓 get_browser() 取得正確的資料。

著手解決 CSS Hack

只要寫短短的 PHP Code 就可以做到上面 Conditional Comments 的所有工作,經過測試即使不做 Cookie 的 Cache、每次載入頁面都執行 get_browser() 也花不到什麼資源!
<?php
    $browser = get_browser();
    $browser = strtolower($browser->browser . $browser->majorver);
?>
<body class="<?php echo $browser; ?>">

更棒的是,管你是 IE 還是 Safari 甚至是 Chrome,我們都可以用不是 Hack 的作法來解決:
.ykpmodule .hd div h3 {padding:9px 7px 0;}
.ie7 .ykpmodule .hd div h3 {padding-bottom:4px;}
.ie8 .ykpmodule .hd div h3 {padding-bottom:2px;}
.safari2 .ykpmodule .hd div h3 {padding-bottom:10px;}
.chrome1 .ykpmodule .hd div h3 {padding-bottom:1em;}


延伸的想法

其實 browscap 還可以用來作為 Device 的判定,像是可以依據手機的不同就吐不同的網頁。另外就是既然沒有 CSS Hack 的存在,那麼我就可以使用 CSSTidy 讓 CSS 檔案達到更有效率的最小化。對了,記得還自己做 Cron Job 每個禮拜把最新的 browscap.ini 抓回來喔!


Comments

  1. 佳佳 2012-05-22 17:30:45
    很好用
    借我轉!!!!
  2. Vincent 2012-04-09 16:49:56
    板主您好, 請問這站還有在維護嗎?
  3. no_css_hack_user 2012-03-01 17:25:39
    我也是用這樣的css hack strategy(心中無劍、手中也無劍),
    不過實作是用前端css_browser_selector.js在<html>加入css class。

    但裕波提到太浪费代码,這點確實。

    不過no css hack好處是,
    向『後』相容、
    交接時不費時(code is everything/document)、
    腦容量可空出裝別的前端知識~~

    so還是看個人需求、公司需求來決定css hack strategy。

    在css hack strategy之前,
    還有「重構html structure或css login」此方法可能可以不用到hack。

    FYI~
  4. 裕波 2009-12-30 23:55:52
    这样太浪费代码了吧

    其实我们平常按照web的方式进行书写,基本没有什么问题
    而且按照你的这种写法,其实和hack没有什么区别,只是使用了一个标识更强的class,这样反而对性能有影响,因为这样会对css层级增加一层。

    而且更麻烦的是,是需要对服务器端的程序进行配置。

    个人愚见。
  5. something wrong ? 2009-06-15 16:41:14
    in this page top block.
  6. something wrong ? 2009-06-15 16:40:38
    Array
    (
    [HTTP_ACCEPT] => image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, application/vnd.ms-excel, application/x-shockwave-flash, application/vnd.ms-powerpoint, */*
    [HTTP_ACCEPT_LANGUAGE] => zh-tw
    [HTTP_ACCEPT_ENCODING] => gzip, deflate
    [HTTP_USER_AGENT] => Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; EmbeddedWB 14.52 from: http://www.bsalsa.com/ EmbeddedWB 14.52; .NET CLR 1.1.4322; .NET CLR 2.0.50727; MAXTHON 2.0)
    [HTTP_HOST] => josephj.com
    [HTTP_CACHE_CONTROL] => max-age=259200
    [HTTP_CONNECTION] => keep-alive
    [PATH] => /usr/local/bin:/usr/bin:/bin
    [SERVER_SIGNATURE] => <address>Apache/2.2.9 (Debian) DAV/2 SVN/1.5.1 PHP/5.2.6-1+lenny3 with Suhosin-Patch Server at josephj.com Port 80</address>

    [SERVER_SOFTWARE] => Apache/2.2.9 (Debian) DAV/2 SVN/1.5.1 PHP/5.2.6-1+lenny3 with Suhosin-Patch
    [SERVER_NAME] => josephj.com
    [SERVER_ADDR] => 61.57.130.241
    [SERVER_PORT] => 80
    [REMOTE_ADDR] => 219.90.40.13
    [DOCUMENT_ROOT] => /var/www/josephj
    [SERVER_ADMIN] => josephj6802@gmail.com
    [SCRIPT_FILENAME] => /var/www/josephj/entry.php
    [REMOTE_PORT] => 12698
    [GATEWAY_INTERFACE] => CGI/1.1
    [SERVER_PROTOCOL] => HTTP/1.0
    [REQUEST_METHOD] => GET
    [QUERY_STRING] => id=249
    [REQUEST_URI] => /entry.php?id=249
    [SCRIPT_NAME] => /entry.php
    [PHP_SELF] => /entry.php
    [REQUEST_TIME] => 1245055053
    [argv] => Array
    (
    [0] => id=249
    )

    [argc] => 1
    )
  7. josephj 2009-06-06 15:00:59
    露人甲,

    剛跟同事討論了一下,對於你所說的還得驗證一下
    例如百分比、誰會這樣做
    另外 User Agent 在 Proxy Cache 的情況是不是會被拔掉
    晚點測試完再加上你的意見囉
  8. josephj 2009-06-06 14:35:24
    露人甲,

    有道理!
    真是一語驚醒夢中人,我的確沒想到 Proxy 的問題

    剛剛想了一下幾種作法,像是另外加上 JavaScript 的驗證
    不過還是會有漏網之魚,用 browscap 來解的確不是個成熟的作法
    這篇會在最前面標註你的意見
    謝謝 ^^
  9. 露人甲 2009-06-06 12:42:36
    這樣遇到使用 proxy 的不就破功了,感覺中肯兄的建議比較中肯喔~
  10. josephj 2009-06-05 12:03:58
    will,
    對我來說,未來這會是基本民生必需品囉 :)
  11. josephj 2009-06-05 12:02:57
    exterry,
    作法一樣吧,IIS 也支援 browscap.dll,也會有類似的 function
  12. will 2009-06-04 15:19:03
    这个很cool!但是根据情况来决定有什么方式解决这种问题比较好!
  13. exterry 2009-06-04 11:04:28
    最看翻看M站写成:<html lang="en-US" dir="ltr" class="ua-ff ua-ff3 ua-win bkt830">
    减少hack使用哦 不知道后端如何实现的 请教下:)
  14. josephj 2009-06-01 21:00:33
    這兩個 CSS Hack 好難辨認啊.... QQ
  15. 貝姬 2009-06-01 17:28:05
    因為compat mode聽說只是模擬IE7也和真正的IE7不同 所以目前我們是不採取這個方法來修IE8...

    不過CN有找到 IE8有一個怪怪的 CSS hack
    .class {property:setting\9;} 使用 \9 在setting 裡面就可以了

    或是之前我以IE8為準然後調整FF2/3
    .class, x:-moz-any-link {property:setting;}

    FYI~
暱稱: 必填。
Email: 非必填。若填寫為不公開欄位,僅供站長參考聯繫。
內容: 必填。限 255 個字元以內。
驗證碼:
送出

Facebook Comment