CSS自定義屬性+CSS Grid網格實現超級的佈局能力

我在工做中使用CSS Grid已經有幾個月了,我很是喜歡它在頁面佈局時給個人靈活性。這麼長時間以來,咱們一直沒有一個真正的網格佈局解決方案——用浮動和flexbox老是有各類各樣的限制。但如今,我真的沒法想象沒有Grid的CSS!javascript

最近我還注意到的一件事就是CSS自定義屬性。CSS自定義屬性的工做方式有點像SASS和其餘預處理器中的變量,主要的區別在於其它方法都是在瀏覽器中編譯後生成,仍是本來的CSS寫法。CSS自定義屬性是真正的動態變量,能夠在樣式表中或使用javascript即時更新,這使得它們具備更多的可能性。若是你熟悉JavaScript,我喜歡把預處理器變量和CSS自定義屬性之間的區別想象成與const和let之間的區別類似——它們都有不一樣的用途。css

CSS自定義屬性能夠方便的實現不少功能(例如主題變化)。最近我一直在嘗試利用CSS自定義屬性和CSS網格的組合能實現什麼神奇的效果,我須要在不一樣的斷點處從新定義grid-template-rows和grid-template-columns屬性。下面的代碼中有一個例子,我使用SASS變量定義了頁面在不一樣的寬度下不一樣的列寬值,這些值將傳遞到grid-template-rows屬性中。我對grid-gap屬性也作了一樣的操做,這樣頁面寬度不一樣時元素之間的間距也是不一樣的:java

$wrapper: 1200px;
$col: 1fr;
$gutter: 20px;

$wrapper-l: 90%;
$col-l: calc((1000px - (13 * 40px)) / 12);
$gutter-l: 40px;

$col-xl: calc((1200px - (13 * 50px)) / 12);
$gutter-xl: 50px;

body {
    background-color: lighten(grey, 30%);
}

.wrapper {
    max-width: $wrapper;
    margin: 20px auto;
    
    @media (min-width: 1300px) {
        max-width: $wrapper-l;
    }
}

.grid {
    display: grid;
    padding: $gutter;
    grid-template-columns: 1fr repeat(12, $col) 1fr;
    grid-template-rows: repeat(2, minmax(150px, auto));
    grid-gap: $gutter;
    border: 1px solid grey;
    background: white;
    width: auto;
    
    @media (min-width: 1300px) {
        grid-template-columns: 1fr repeat(12, $col-l) 1fr;
        grid-gap: $gutter-l;
        padding: $col-l;
    }
    
    @media (min-width: 1500px) {
        grid-template-columns: 1fr repeat(12, $col-xl) 1fr;
        grid-gap: $gutter-xl;
        padding: $col-xl;
    }
}

.grid__item {
    border: 1px solid blue;
}

.grid__item--heading {
    grid-column: 2 / 11;
}

clipboard.png

點擊查看上圖的所有代碼和實時效果瀏覽器

就如你所看到的,基本上必須在媒體查詢中再次寫出整個代碼塊來改變樣式,由於變量一旦定義就固定了。(我固然可使用mixin,可是最終效果是同樣的——一大塊代碼。)sass

使用CSS自定義屬性,能夠減小代碼量,由於我只需更新媒體查詢中的變量,瀏覽器就會從新計算網格。十行(sass)代碼可能看起來不是一個巨大的節省,但代碼的可讀性要高得多,由於沒必要在好幾個地方添加媒體查詢來處理咱們的新變量,我只需在該組件的代碼開頭聲明它們,而且無需擔憂是否已替換了正在使用的哪一個值:app

:root {
    --wrapper: 1200px;
    --col: 1fr;
    --gutter: 20px;
    
    @media (min-width: 1300px) {
        --wrapper: 90%;
        --col: calc((1000px - (13 * 40px)) / 12);
        --gutter: 40px;
    }
    
    @media (min-width: 1500px) {
        --wrapper: 90%;
        --col: calc((1200px - (13 * 50px)) / 12);
        --gutter: 50px;
    }
}

body {
    background-color: lighten(grey, 30%);
}

.wrapper {
    max-width: var(--wrapper);
    margin: 20px auto;
}

.grid {
    display: grid;
    padding: var(--gutter);
    grid-template-columns: 1fr repeat(12, var(--col)) 1fr;
    grid-template-rows: repeat(2, minmax(150px, auto));
    grid-gap: var(--gutter);
    border: 1px solid grey;
    background: white;
    width: auto;
}

.grid__item {
    border: 1px solid blue;
}

.grid__item--heading {
    grid-column: 2 / 11;
}

.grid__item--body {
    grid-column: 2 / 8;
    grid-row: 2 / span 1;
}

.grid__item--media {
    background: hotPink;
    grid-column: 11 / 14;
    grid-row: 1 / span 2;
}

clipboard.png

點擊查看所有代碼和實時效果佈局

我發現使用CSS Grid的一個特色是,語法很是冗長,並且並不容易快速、輕鬆地看到正在發生的事情,特別是在複雜的網格中。可是在這個例子中,使用CSS自定義屬性,能夠爲網格項的大小和座標設置變量,而且只寫一次grid-column和grid-row屬性。對我來講,這比每次都寫出完整的屬性要清楚得多,並且很容易一目瞭然地看到網格項的位置。測試

這裏有一個隨機動態改變自定義變量的DEMO,在這個示例中,我使用javascript循環網格項,並在每次單擊按鈕時使用隨機值更新變量。沒有添加類或額外的CSS。flex

在這個的示例DEMO中,使用用戶輸入的值動態更改網格項。這裏要更新的只是x和y座標的三個變量以及網格項的大小。flexbox

太多的可能性了!

瀏覽器支持
目前,全球88%的瀏覽器都支持CSS自定義屬性——Internet Explorer 11及如下版本是明顯的例外。這與對CSS Grid網格佈局的支持大體相同,這意味着要使用特性查詢來區分支持與不支持的瀏覽器。

能夠這樣使用@supports聲明來測試對css自定義屬性的支持:

@supports(--css: variables) {
        .my-div {
            --size: 2;
            --posX: 3;
            grid-column: var('--posX') / span var('--size');
        }
    }

圖片描述

相關文章
相關標籤/搜索