原文链接:https://zellwk.com/blog/how-to-write-mobile-first-css/


构建响应式网站是如今前端开发者的必备技能,当我们谈到响应式网站时,“移动端优先”这个词立刻就会出现在脑海中。

我们知道从“移动端优先”这个角度开始设计很重要,但我们很少谈到使用“移动端优先”的方法来写代码。

今天,我想与你分享“移动端优先”添加样式的方法,为什么这种方法更好,以及如何发挥它的魔力。

贴士:如果你在学习使用Susy来建立响应式布局,这篇文章会对你帮助非常大。


#什么是“移动端优先”和“桌面优先”方法?

在开始讨论为什么“移动端优先”方法更好之前,我们先了解下“移动端优先”与“桌面优先”之间的区别。

“移动端优先”添加样式的方法指的是首先在移动设备上应用样式,然后通过媒体查询在样式表中加入应用于大屏幕的高级样式和其他覆盖样式。

这个方法使用min-width媒体查询。

这里是一个简单的例子:

// 这个样式在0px到600px应用
body { background: red; }

// 这个样式在大于600px时应用
@media (min-width: 600px) {
    body { background: green; }
}


在上面的例子中,当视口小于600px时,<body>的背景是红色的,当视口等于或大于600px时,背景变成绿色。

另一方面,“桌面优先”添加样式的方法指的是首先在桌面设备上应用样式,然后通过媒体查询在样式表中加入应用于小屏幕的高级样式和其他覆盖样式。

这个方法使用max-width媒体查询。

这里是一个简单的例子:

// 这个样式在大于600px时应用
body { background: green; }

// 这个样式在0px到600px应用
@media (max-width: 600px) {
    body { background: red; }
}


在任意宽度下,<body>会有一个绿色的背景,但当屏幕小于600px时,背景颜色会变成红色。


#为什么要写“移动端优先”代码?

为大屏幕编写的代码通常会比为小屏幕编写的代码更复杂,所以编写“移动端优先”代码可以简化你的代码。

设想这样一个场景,你的网站有一个“内容-边栏”布局,.content在移动端占会100%的宽度,在桌面则占60%的宽度。



大部分情况下,在小屏幕中,我们可以依赖默认属性给内容应用样式,在这个例子中,<div>的默认宽度为100%。

如果我们用的是“移动端优先”方法,Sass代码会是这样的:

.content {
    // 为小屏幕设置属性
    // 这里不需要设置任何属性,因为我们可以使用默认样式

    // 为大屏幕设置属性
    @media (min-width: 800px) {
        float: left;
        width: 60%;
    }
}


如果我们用的是“桌面优先”的方法,大部分情况下我们需要为小视口重写默认样式,Sass代码会是这样:

.content {
    // 为大屏幕设置属性
    float: left;
    width: 60%;

    // 为小屏幕设置属性
    // 注意我们需要重写两个默认属性才能使这个布局正常显示
    @media (max-width: 800px) {
        float: none;
        width: 100%;
    }
}


在这个例子中,我们节省了两行代码以及几秒钟的思考时间(不用思考令人头疼的CSS)。想象下如果你在建立一个更大的网站,这个方法会给你省下多少时间和努力。

大多数时候min-width查询足够帮助你写一个网站,然而,在只使用min-width无法满足需求的情况下,min-width和max-width的结合使用能够帮助你减少麻烦。

让我们来研究一下这些情况。


#使用“移动端优先”方法和max-width查询

当你希望在小于特定视口大小时应用某样式的时候,max-width查询就能发挥它的作用了。min-width和max-width媒体查询的结合使用则可以在两个不同视口大小间控制样式。

设想一个缩略图库例子,在小视口中,这个图库每行显示3个缩略图,在大视口中,每行4个。



因为每个缩略图之间没有间隔,所以代码很简单:

.gallery__item {
    float: left;
    width: 33.33%;
    @media (min-width: 800px) {
        width: 25%;
    }
}


如果每个缩略图之间有空白间隔,情况会变得稍复杂。



假设这些间隔占整个宽度的5%:

.gallery__item {
    float: left;
    width: 30%;
    margin-right: 5%;
    margin-bottom: 5%;
}


我们还需要把每行最后的(第3个)缩略图的margin-right设为0,以免它被推到下一行。

.gallery__item {
    float: left;
    width: 30%;
    margin-right: 5%;
    margin-bottom: 5%;
    &:nth-child(3n) {
        margin-right: 0;
    }
}


当每行有4个缩略图时也应该是这样,但如果我们还是使用之前所用的min-width查询.....

.gallery__item {
    float: left;
    width: 30%;
    margin-right: 5%;
    margin-bottom: 5%;
    &:nth-child(3n) {
        margin-right: 0;
    }

    @media (min-width: 800px) {
        width: 21.25%; // (100% - 15%) / 4
        &:nth-child(4n) {
            margin-right: 0;
        }
    }
}

 



情况并非预想中的那样,这是因为我们指定第3n(3的倍数)个缩略图的margin-right为0,由于层叠效应,这个属性在大视口中依然起作用,破坏了我们的预想中的模式。

我们可以通过重设第3n(3的倍数)个缩略图的margin-right为5%这个方法来解决问题:

.gallery__item {
    // ...
    @media (min-width: 800px) {
        // ...
        &:nth-child(3n) {
            margin-right: 5%;
        }
        &:nth-child(4n) {
            margin-right: 0;
        }
    }
}


这个方法并不是太好,因为如果我们需要修改大视口中缩略图的数量,我们要重复margin-right: 5%;

我们应该尽可能使代码保持DRY(Don't Repeat Yourself. 不要重复代码。)。

更好的解决办法是使用max-width查询把选择器nth-child(3n)限制在对应的视口中。

.gallery__item {
    float: left;
    margin-right: 5%;
    margin-bottom: 5%;
    @media (max-width: 800px) {
        width: 30%;
        &:nth-child(3n) {
            margin-right: 0;
        }
    }

    @media (min-width: 800px) {
        width: 21.25%; // (100% - 15%) / 4
        &:nth-child(4n) {
            margin-right: 0;
        }
    }
}

 



这个办法能起作用是因为max-width属性把选择器限制在小于800px的视口中,其中定义的样式不会影响其他视口的样式。

现在想象一下有一个更大的视口,你想要在图库中每行显示5个缩略图,这时候该min-width和max-width查询联手出动了。

.gallery__item {
    float: left;
    margin-right: 5%;
    margin-bottom: 5%;
    @media (max-width: 800px) {
        width: 30%;
        &:nth-child(3n) {
            margin-right: 0;
        }
    }

    // min-width和max-width查询结合使用
    @media (min-width: 800px) and (max-width: 1200px) {
        width: 21.25%; // (100% - 15%) / 4
        &:nth-child(4n) {
            margin-right: 0;
        }
    }

    @media (min-width: 1200px) {
        width: 16%; // (100% - 20%) / 5
        &:nth-child(5n) {
            margin-right: 0;
        }
    }
}

 




#视频!

Webucator上一群很好的小伙子自愿制作了一个视频来总结这篇博客,所以如果你觉得视频更适合你,一定要去看看他们的视频。


#总结

建立响应式网站时,min-width媒体查询非常有用,因为它减低了代码复杂度。不过,从上面的例子中可以看出,min-width查询并非所有问题的解决方案,有时在样式表中使用max-width查询也是有益的,它能帮助你保持代码更DRY。