2015年7月24日

跨瀏覽器套版列印:根據不同的瀏覽器載入不同的CSS

圖片來源:browserwork
最近因為螢幕尺寸越來越多元,網頁設計師不只要處理大家螢幕尺寸不同,網頁呈現要根據螢幕尺寸加以調整的問題(可參考:基本RWD版型設計),更進一步的,現在連瀏覽器的選擇都很多種,

有的人習慣用chrome,有的習慣用safari,還有的喜歡用火狐或IE,可是這些瀏覽器在解釋CSS的時候,都會有些微差異,進而使得在Chrome設計的版型,可能用IE看會有些不同的問題,也就是說,現在的網頁設計師不只要解決跨螢幕的問題,還要解決跨瀏覽器的問題。

前陣子一直在苦惱一件事,當我寫好了一份套版(例如,宅急便,台灣宅配通),然後要透過瀏覽器列印時,卻發現每一個瀏覽器列印出來的樣式都不相同,但是又不能夠限制客戶只能用哪一個瀏覽器,苦思多日後,總算想到了一個方法—何不根據不同的瀏覽器,讓它去套用不同的CSS就可以了呢?

我目前想到的辦法是這樣的,如果其他人有想到其他解法,有歡迎提出一同討論。

為了要根據不同的瀏覽器套用不同的CSS,我們將依序做幾件事:

透過javascript偵測瀏覽器類型


偵測瀏覽器的類型有很多不同的方法(可參考這篇:[HTML][CSS][PHP][JavaScript][JSP] 判斷使用者瀏覽器版本),在這裡我選擇使用javascript的方法。

寫法如下:
     var isFirefox = navigator.userAgent.match("Firefox") //判斷是否為 FireFox
     var isIE = (/Trident\/7\./).test(navigator.userAgent);
     var isOpera = navigator.userAgent.match("Opera") //判斷是否為 Opera
     var isSafari = navigator.userAgent.match("Safari") //判斷是否為 Safari 或 Google Chrome
    if (isIE) {
        alert("你使用的是IE")
    }
    if (isFirefox) {
        alert("你使用的是FireFox")
    }
    if (isOpera) {
        alert('你使用的是Opera');
    }
    if (isSafari) {
        alert("你使用的是Chrome或Safari");
    }         

基本上都是透過Navigatoruseragent這個屬性(可參考:W3Shools的說明),useragent這個屬性是用來回傳瀏覽器寄送給伺服器表頭的內容(Returns the user-agent header sent by the browser to the server),接著我們可以透過match來判斷回傳的表頭中是否包含特定的關鍵字,以此來判斷使用者使用的是那個瀏覽器。

比較特別的是由於IE的版本眾多(這個code確定可以偵測IE11),建議在偵測瀏覽器是否為IE的地方,可以先試試看有沒有錯誤,如果偵測不到,就google一下其他版本的IE要用什麼javascript去偵測吧。

透過javascript引用css的寫法


一般我們在HTML文件中,引用CSS文件時,我們會寫這樣子:
<link href="external.css" rel="stylesheet" type="text/css">
如果現在我們要把這段語法套用到javascript當中,我們可以使用這個function(語法參考自腳本之家):
function includeLinkStyle(url) {
 var link = document.createElement("link");
 link.rel = "stylesheet";
 link.type = "text/css";
 link.href = url;
 document.getElementsByTagName("head")[0].appendChild(link);
}
基本上就是先建立一個element叫做link,裡面要有rel、type和href,最後則是透過appendChild將link放在head的裡面(關於appendChild的使用可參考W3School)。

根據不同的瀏覽器套用不同的CSS


最後結合上面兩個,我們就可以根據不同的瀏覽器套用不同的CSS,語法如下:
        var isFirefox = navigator.userAgent.match("Firefox"); 
        var isIE = (/Trident\/7\./).test(navigator.userAgent);
        var isOpera = navigator.userAgent.match("Opera"); 
        var isSafari = navigator.userAgent.match("Safari"); 
        if (isIE) {
            includeLinkStyle("print_css_ie.css")    //  引入IE使用的css
        }
        if (isFirefox) {
            includeLinkStyle("print_css_firefox.css")   // 引入Firefox使用的css
        }
        if (isOpera) {
            alert('目前不支援以Opera列印');
        }
        if (isSafari) {
            includeLinkStyle("print_css_chrome.css")    // 引入Chrome或Safari使用的css
        }              

後記


其實,如果各個瀏覽器所套用的css只是些微的不同的話,其實也可以不用根據不同的瀏覽器每個都去套不同的css,而是可以使用一套css,然後透過上面的作法,在不同的瀏覽器時,幫不同的class做些些微的調整就好。

像是這樣子
 var isFirefox = navigator.userAgent.match("Firefox") 
 var isIE = (/Trident\/7\./).test(navigator.userAgent);
 var isOpera = navigator.userAgent.match("Opera") 
 var isSafari = navigator.userAgent.match("Safari") 
    //  Firefox和IE的css做些微調整
    if (isFirefox || isIE) { 
        //  針對contianer這個css去改變寬度
        var container = document.querySelector(".container");
        container.style.width="5cm";
      
        //  針對barcode這個css去調整寬度,跑回圈是因為很多地方用到barcode這個class
        var barcode = document.querySelectorAll(".barcode");
        for (var i = 0; i < barcode.length; i++) {
           barcode[i].style.width="5cm";
        }
    } 
    if (isOpera) { 
        alert('目前不支援以Opera列印'); 
    } 
    if (isSafari) { 
        //套用原本的css樣式。
    }      
要注意的是,如果是使用最後這段語法,要記得把script放在/body前面,之所以要這樣做是因為要確認每一個DOM元件已經被讀取到後,javascript才能順利讀到那個元素。 另外,如果會寫jQuery的話,裡面的語法也可以和jQuery做搭配,不一定要完全用javascript寫。

2 則留言:

  1. 你好,請問引用各瀏覽器的CSS,那CSS是自己設定的嗎?
    為了因應不同瀏覽器的解析度,所以CSS分成不同的瀏覽器,然後再用你提供的方法引入,是嗎?

    回覆刪除
    回覆
    1. Hello,
      是的,可以根據不同的瀏覽器去套用不同的CSS,
      我不確定這是不是最好的方式,但是是我目前想到的方法

      刪除