有关css栅格系统的故事

说到栅格系统grid system),你也许见过这样的概念:css

grid system for design

像这样,经过固定的格子结构,来进行布局设计。这是一种设计风格,并且一直以来很普遍地应用于网页设计领域。这样的风格清晰、工整,可让网页具备更友好的浏览体验。前端

而随着响应式设计responsive design)的流行,栅格系统开始被赋予新的意义,那就是,一种响应式设计的实现方式sass

栅格与响应式

响应式的要点是为同一个页面设计多种布局形态,分别适配不一样屏幕尺寸的设备。通常来讲,是这样的感受:前端框架

responsive design impression

能够看到,一个页面能够拆分红多个区块来理解,而正是这些区块共同构成了这个页面的布局。根据不一样的屏幕尺寸状况,调整这些区块的排版,就能够实现响应式设计。另外,屏幕宽度较大的时候,区块倾向于水平分布,而屏幕宽度较小的时候,区块倾向于竖直堆叠。框架

这些方方正正的区块是否是和栅格系统的格子挺类似?对的,为了让响应式设计更简单易用,因而有了不少称为“栅格”(grid)的样式库。工具

栅格样式库通常是这样作的:将页面划分为若干等宽的列(column),而后推荐你经过等宽列来建立响应式的页面区块。布局

虽然看起来都是这样的思路,但不一样的栅格样式库,在作法上倒是各有各的点子。下面,本文将介绍几个比较有表明性的栅格样式库,讲述它们的简要原理和用法(正确的打开方式)。post

Bootstrap中的栅格

Bootstrap[]。默认分为12列。测试

容器、行与列

要理解Bootstrap中的栅格,最好从掌握正确的使用方法开始。这其中有2个要点。字体

第1个要点是容器(container),行(row)和列(column)之间的层级关系。一个正确的写法示例以下:

<div class="container">
    <div class="row">
        <div class="col-md-6"></div>
        <div class="col-md-6"></div>
    </div>
</div>

Bootstrap栅格的容器有两种,.container(固定像素值的宽度)和.container-fluid(100%的宽度),在这里,把它们都称为container。须要注意的是,row(.row)必须位于container的内部,column(如.col-md-6)必须位于row的内部。也就是说,container、row、column必须保持特定的层级关系,栅格系统才能够正常工做。

为何须要这样?查看这些元素的样式,会发现container有15px的水平内边距,row有-15px的水平负外边距,column则有15px的水平内边距。这些边距是故意的、相互关联的,也所以就像齿轮啮合那样,限定了层级结构。这些边距其实也是Bootstrap栅格的精巧之处,若是你想进一步了解,推荐阅读[The Subtle Magic Behind Why the Bootstrap 3 Grid Works][]。

若是要嵌套使用栅格,正确的作法是在column内直接续接row,而后再继续接column,而再也不须要container:

<div class="container">
    <div class="row">
        <div class="col-md-8">
            <div class="row">
                <div class="col-md-6"></div>
                <div class="col-md-6"></div>
            </div>
        </div>
        <div class="col-md-4"></div>
    </div>
</div>

断点类型

第2个要点,是不一样的断点类型的意义及其搭配。

Bootstrap栅格的column对应的类名形如.col-xx-yy是数字,表示该元素的宽度占据12列中的多少列。而xx只有特定的几个值可供选择,分别是xssmmdlg,它们就是断点类型。

在Bootstrap栅格的设计中,断点的意义是,当视口(viewport)宽度小于断点时,column将竖直堆叠(display: block的默认表现),而当视口宽度大于或等于断点时,column将水平排列(float的效果)。按照xssmmdlg的顺序,断点像素值依次增大,其中xs表示极小,即认为视口宽度永远不小于xs断点,column将始终水平浮动。

有时候,会须要将多种断点类型组合使用,以实现更细致的响应式设计。此时不一样的断点类型之间会有怎样的相互做用呢?

先看看Bootstrap的sass源码是如何定义栅格的:

@include make-grid-columns;
@include make-grid(xs);
@media (min-width: $screen-sm-min) {
  @include make-grid(sm);
}
@media (min-width: $screen-md-min) {
  @include make-grid(md);
}
@media (min-width: $screen-lg-min) {
  @include make-grid(lg);
}

能够看到,用了min-width的写法,并且断点像素值越大的,对应代码越靠后。因此,若是有这样的一些元素:

<div class="container">
    <div class="row">
        <div class="col-sm-6 col-lg-3">1</div>
        <div class="col-sm-6 col-lg-3">2</div>
        <div class="col-sm-6 col-lg-3">3</div>
        <div class="col-sm-6 col-lg-3">4</div>
    </div>
</div>

那么它们应该是这样的效果:

结合前面的源码,能够想到,在上面这样视口宽度由小变大的过程当中,首先是保持默认的竖直堆叠,而后超过了sm的断点,sm的样式生效,变为一行两列的排版,再继续超过lg的断点后,lg的样式也生效,因为lg的样式代码定义在sm以后,因此会覆盖掉sm的样式,从而获得一行四列的排版。

因此,结合使用多个断点类型,就能够引入多个断点变化,把响应式作得更加细致。

适度使用

Bootstrap栅格虽然很强大,但也不该过分使用。例如,当你须要一个占据一整行宽度的元素时,请不要也想着让Bootstrap栅格参和进来,加入相似.col-xs-12这样的元素。实际上,你不须要任何栅格类,你须要的只是一个块元素。

Foundation中的栅格

Foundation[],它和Bootstrap栅格的设计十分近似,只是在类名和结构上有所差别。Foundation栅格一样默认12列。

行与列

类比以前Bootstrap栅格的例子,Foundation栅格的一个正确的写法示例以下:

<div class="row">
    <div class="medium-6 columns"></div>
    <div class="medium-6 columns"></div>
</div>

Foundation栅格的行用.row表示,而列由至少两个类名组成,一是.columns.column(2种写法彻底相同,单纯为了支持语法偏好)代表这是列元素,二是.medium-6这种用于表示断点类型和对应宽度。在默认状况下,Foundation栅格的断点类型从小到大依次是smallmediumlarge,其中small相似Bootstrap栅格的xs,也是指任意屏幕尺寸下都水平排列。

Foundation栅格没有container,只须要row和column,所以显得比Bootstrap栅格更简单一些。其中row定义了最大宽度(能够认为承担了container的部分功能),column定义了0.9375rem的水平内边距。若是要嵌套,仍然是column内续接row,再继续接column。

组合使用多个断点类型,其方法也和Bootstrap栅格相同。须要注意的是,Foundation栅格的断点值是用的em而不是px,对应的,它们转换后的像素值也有别于Bootstrap栅格。

Block Grid

做为栅格系统的补充,Foundation还提供了另一个叫作[Block Grid][]的栅格。不过,它并非一个超出传统栅格的新东西,而只是一个针对特定栅格应用场景的方法糖。

下面是一个Block Grid的示例:

<ul class="small-block-grid-2 medium-block-grid-3 large-block-grid-4">
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

其中,ulli这样的特定标签组合是必须的。在这个示例中,屏幕宽度从小到大的变化过程当中,列元素将依次是一行两列、一行三列、一行四列的排版方式。

能够看到,Block Grid的结构也是行和列,但只须要在行上有一个类名。和Foundation的Grid相比,它的确有一些不一样。一方面,Block Grid的行并无定义最大宽度。另外一方面,Block Grid的列必定是等宽的(毕竟li不须要任何类名)。

Toast栅格

前面介绍的两个栅格样式库都来源于流行前端框架,并非独立的。本文接下来要介绍的[Toast][],则是一个独立的、颇有想法的栅格样式库。

特别的实现方式

为何说颇有想法呢?请看它的一个正确的写法示例:

<div class="grid">
    <div class="grid__col grid__col--1-of-2"></div>
    <div class="grid__col grid__col--1-of-2"></div>
</div>

相似的,这也是一行均分两列的排版。能够看到,Toast栅格的结构一样是行(.grid)与列(.grid__col)。可是,不一样于始终以12列为参考的模式,它能够用1-of-2这样更为直观的类名。事实上,这里用3-of-66-of-12等也能够,它们是相同的。

固然,这并非Toast最特别的地方。如今,请想一下,Bootstrap及Foundation的栅格系统的column本来都是块元素,它们是如何实现水平排列的?

对的,用的是float。但Toast是如何作的呢?它想法独特,选用了display: inline-block;。若是你有了解过这个属性,你应该知道inline-block的元素会彼此之间存在缝隙。Toast在选择这个属性的基础之上,巧妙使用了负外边距(例如margin-right: -.25em;),消除了缝隙对栅格column水平排列的影响。在我作了一些测试和应用后,我只能说,这个强行完成的策略要给个赞。

非Mobile First

在前面Toast栅格的示例中,并无相似mdmedium这样体现断点类型的词。这是由于,Toast采用了“存在默认”的风格。绝大部分状况下,只须要使用形如.grid__col--x-of-y的类名。Toast已经为这个类设置了断点(默认700px),低于这个断点为display: block;,高于这个断点为display: inline-block;

意外的是,不一样于Bootstrap和Foundation默认取block的mobile first原则(竖直堆叠更符合小尺寸屏幕的排版要求),Toast则是把display: inline-block;放在了@media范围以外,当作默认属性。这应该只是风格偏好差别,就我我的而言,我仍是更赞同mobile first的设计风格的。

有关mobile first的响应式设计的实现,推荐阅读Grid

若是要加入多个断点变化,Toast是这样作:

<div class="grid">
    <div class="grid__col grid__col--1-of-4 grid__col--m-1-of-2">
    </div>
</div>

上面这段代码的效果是,该栅格列在480px如下为block,占据满宽,481px~700px之间为inline-block,占据1/2宽度,701px以上为inline-block,占据1/4宽度。

对栅格系统的补充

前面介绍的这些栅格样式库,源码都使用Less、Sass这些css预编译工具,所以其中的12列、断点值、列间距等都是可配置的,只不过大部分状况下默认的就足够使用。

虽然栅格样式库很棒,但它们并非响应式设计的所有。要使同一个应用在不一样屏幕尺寸的设备上都具备较好的浏览体验,还有不少其余手段可用(好比在尺寸更大的屏幕上使用更大的字体),栅格系统只是方式之一。

结语

借助css栅格系统,咱们能够很容易地建立响应式的页面布局。但在这个过程当中,理解各种栅格样式库的工做原理,正确使用它们,才能作出稳定、可靠的页面结构。

(从新编辑自个人博客,原文地址:http://acgtofe.com/posts/2015/07/a-story-of-grid

相关文章
相关标签/搜索