R·ex / Zeng


音遊狗、安全狗、攻城獅、業餘設計師、段子手、苦學日語的少年。

【教程】用JavaScript控制CSS規則

相容性:IE≥9

難度:中等

有時候網頁要適配多種解析度,我們自然想到用百分比來控制大小。但是百分比不是萬能的。例如,你想讓一螢幕顯示十行表格,但是你並不知道螢幕有多高,因此需要用 JavaScript 的 window.innerHeight 獲取螢幕高度。但是如何修改 CSS 呢?

第一種方法:直接設定某元素的屬性

document.getElementById('xxx').style.height = window.innerHeight / 10 + 'px';

元素的 style 屬性是一個 CSS 集合,裡面的內容可以直接調。對於 margin-left 這樣的複合詞,要用 marginLeft 代替。注意要用小駝峰寫法(第一個單詞小寫,其餘的單詞首字母大寫,中間無連字元)。

此方法唯一的不足之處在於,每次只能修改一個元素的樣式。

第二種方法:修改元素擁有的 class 的樣式

表示之前不會。經過各種搜尋之後,在 這個網站 上找到了解決方案。大體內容是這樣如下。

document 這個大的物件裡,有個叫 styleSheets 的陣列,是引入的 CSS 檔案列表,例如 document.styleSheets[0] 是引入的第一個檔案。用 Chrome 的終端看一下效果:

樣式表

其中 disabled 表示該樣式表是否啟用,href 是樣式表路徑……其實我們關心的是 rules 的值。

CSS規則

很清楚了吧,這就是一條條 CSS 的規則。其中物件的 style 跟上一個方法的 style 是一個東西,可以直接呼叫了。例如我要把這個 .popupdisplay 設成 block,可以這麼寫:

document.styleSheets[0].rules[2].style.display = 'block';

有點麻煩呢。更麻煩的是,在 IE 中對 rules 的解釋還不一樣(一般比 Chrome 多出幾條,不知道為什麼),還有在 Firefox 中壓根就沒有 rules 這個東西,取而代之的是 cssRules!瀏覽器們,能不能統一一下標準啊……

不過還好,可以寫一段 JavaScript 來簡化工作(程式碼經我簡化過,與網站上的程式碼功能完全相同):

function getStyle(sname) {
    var rules;
    for (var i = 0; i < document.styleSheets.length; i++) {
        if (!(rules = document.styleSheets[i].cssRules))
            rules = document.styleSheets[i].rules;
        for (var j = 0; j < rules.length; j++)
            if (rules[j].selectorText == sname)
                return rules[j].style;
    }
}

解釋一下用法好了。sname 是我們需要找的 CSS 選擇器(例如 .icon_add),返回的結果是最終的那個 style,所以用起來很簡單,例如:getStyle('.icon_add').display = 'block'。當然副作用還是有的,畢竟是直接呼叫我們的 CSS 檔案,所以當我們的選擇器比較特殊的時候(例如 html, body, #content > div),我們必須完整地敲出這個選擇器(只敲 body 是沒法匹配的哦)。

下面的內容是解釋程式碼含義的,沒興趣的可以跳過了。

首先,外層迴圈是在列舉 styleSheets 陣列的元素,裡面那個 if 是為了相容 Firefox 的(我沒有犯將 == 打成 = 的錯誤,那裡就是 =)——如果沒有 cssRules 的話,就用 rules 吧。

內層迴圈就是列舉 rules 啦,用 selectorText 跟你的 sname 進行比較,如果相同的話就返回該條規則的 style,用起來很方便的。

Disqus 載入中……如未能載入,請將 disqus.com 和 disquscdn.com 加入白名單。

這是我們共同度過的

第 3887 天