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');
        }
    }

图片描述

相关文章
相关标签/搜索