本文由大漠根据creativebloq.com的《Create flexible grids using Sass》所译,整个译文带有我们自己的理解与思想,如果译得不好或不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://www.creativebloq.com/web-design/create-flexible-grids-using-sass-9134524,以及作者相关信息
——作者:creativebloq.com
——译者:大漠
Steve Hickey阐述了如何使用CSS和Sass设计自己的弹性网格系统。在理解这篇文章需要具备以下几个方面:
- 需要的知识:CSS,Sass和HTML基础
- 需要的工具:Sass,代码编辑器
- 项目时间:2~3小时
如果你是一个设计师,或者你和设计师一起合作,你就会常碰到在一个网站中实现网格布局。这个过程可能非常痛苦,但保持视觉上和一个精心设计的网格一致性是非常值得的。
但当你为一个响应式设计写样式的时候,你并不想在布局中为每个元素计算宽度。相反,您需要一个可伸缩的解决方案,在你的网格中可以指定匹配的宽度。
我们可以使用一个像960网格系统来解决这个问题,但是在我看来,框架有很多问题,我们可以让这些问题不存在。
他们需要将大量的代码添加到你的样式文件中,如果你需要得新计算你所有的宽度,或者如果你想修改你的系统,他们依靠的是标记和没有语义的类名。这可能有很少代码被再次使用。
在一个web布局当中实现一个网格系统并不意味着你需要一个框架。这暗示着我们在本教程中需要构建的是一个网格系统。
框架提供的速度和一致性足以让我们容忍这些缺点,但我想我样可以做得更好。Sass可以用一些特性,让我们可以快速创建一个网格系统,可以在几秒钟内对网格系统进行修改,编译出必要的CSS,使我们能在我们的标记中消除无义语化的类名。
设计一个好的网格系统
任何网格需要足够的内容来支持项目,但并非如此复杂,以至于使用变得笨拙。原因之一就是960网格系统已经非常的流行,允许划分大量同样的列,可以很容易的适应大多数内容的要求。这很重要,因为很多变量会影响一个网格系统。
在未来,媒体断点和行高和body中文本行高都将影响一个网格元素之间的间距和比例。
真正优秀的网格设计细节超出了本文的范围,但有一些工具可以帮助您入门。
我建议您看看Modular Grid Pattern和Gridulator。
我个人使用的是Gridulator,因为它会为你计算网格的最大宽度和为列提供各种列宽度和间距。主要的缺点是它不会计算流体网格所需的百分比,但对于工具而言是一个常见的问题。在本教程中,我们将把这些值实现成百分比值。
Elliot Jay Stock的简单的响应式Photoshop网格形成了我们的网格系统的基础。
对于本教程,我们将使用Elliot Jay Stocks的《Responsive Photoshop Grid》一文中介绍的,因为所使用的比例计算很容易理解。它的系统是基于六列网格,每列宽度为150px,相邻两列的间距为20px,网格总宽度为1000px。这些宽度的百分比,我们将使用Ethan Marcotte创建的伸缩性网格设计公式。
target / context = result
在这种情况下,我们的target=150px
和context=1000px
。根据这个公式,应该像这样:
150 / 1000 = 0.15
当这个结果转换为一个百分比时,我们的列的宽度为15%。使用相同的公式,应用到我们的列间距20px上,得出的值为2%。
在这一点上,你应该明白为什么我们使用Elliot的网格。我们不会有任何的长的十进制值的百分比宽度,这将它更容易专注于更重要的概念。
(当使用其他的网格系统,会具有抵抗长十进制值的冲动。提供适应的宽度时,浏览器计算会做得更好。提供越长的值,浏览器计算的时间越长。)
简洁的模板
接下来,让我们来看结构。我们要构建一个Web页面来演示该系统的各种特性。从下载的文件中,你可以打开01-markup
目录中的index.html
文件。
我们的结构开始使用的HTML5 Boilerplate project的结构,但为了简便起见,我们放弃了一些元素。
在这里,你大叫“有语义化类名”时看看。这些类是演示代码中的命名,因此事实上,他们是具有语义化的。你会看到当我们开始编写Sass时,其他的类名同样的好用。
<!doctype html>
<head>
<title>Flexible Grid Tutorial</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="css/styles.css" />
</head>
<body>
<div class="container">
<header role="banner">
<h1>Flexible Grid Tutorial</h1>
</header><!-- end of header[role="banner"] -->
<div role="main">
<section class="hero"></section><!-- end of section.hero -->
<section class="two-columns">
<h2>Two Columns</h2>
<div class="left-column"><p>Lorem ipsum dolor sit amet...</p></div>
<div class="right-column"><p>Lorem ipsum dolor sit amet...</p></div>
</section><!-- end of section.two-columns -->
<section class="six-columns">
<h2>Six Columns</h2>
<div class="first-column"><p>Lorem ipsum dolor sit amet...</p></div>
<div class="second-column"><p>Lorem ipsum dolor sit amet...</p></div>
...
每一个大型网格背后都隐藏着巨大的代码。我们这里算不错了,干净,一些空标签只是用来做演示使用。
创建Sass文件结构
我们像Ruby on Rails应用程序处理样式表一样,组织Sass文件。这种结构允许我们很明显的组织我们的代码,但仍然只编译一个CSS文件。
css/sass/styles.scss
文件输出css/style.css
文件,将以下种结构组织文件:
@import "variables";//全局变量,他们首要访问的变量
//其他样式
@import "mixins";//将样接近的样式,使用变量定义一个全局的mixins
@import "typography";//创建基本的排版系统
@import "grid";//网格系统的函数和mixin都将在这里定义
@import "global";//全局最后定义的样式规则,这样可以使用前面所有的样式
通常,重置样式表在导入mixins样式之后导入。
样式变量,Mixins和类型规则
接下来,打开你下载文件中的03-base-styles
目录中的css/sass/_variables.scss
文件。这些都是本教程中将要使用的基本变量。我们使用//
单行添加注释,因为这些规则在编译出来的CSS中不会编译出来。指定给网格的变量都在grid
样式表中定义。
如果你在相同的目录中打开css/sass/_mixins.scss
文件,你可以看到用于网格系统的mixin。因为他们除了使用于网格系统之外还可能被定义在全局范围使用。
根据Paul Irish的主张,我们要用box-sizing:border-box
来简化网格计算。(如果你的项目需要支持IE7以及IE7之下浏览器,他的文章链接接到一些适当的解决方案)。
最后,打开css/sass/_typography.scss
文件。这些规则是绝对是支持本教程中使用的元素。文档中的注释标明了样式的规则。
我们使用易于理解的方式组织我们正在使用的文件结构,但仍编译到一个样式表中。
定义伸缩性网格函数
现在,我们都设置好了,我们可以看到有趣的部分。我们要做的第一件事情在我们的网格样式表(打开04-grid-functions
目录中的css/sass/_grid.scss
文件)中声明一些用于网格功能的变量。这些都是基于设计网格系统计算所需的变量。
$max-width: 1000px; //设置页面的最大宽度
$column-width: 15%; //设置列的列宽度
$gutter-width: 2%; //设置列与列之间的间距
$maximum-columns: 6; //设置最大的列数
接下来,我们使用函数创建伸缩性的列和间距宽度。这些函数是从Bourbon的mixin中修改得来的。我们将引入创建我们的网格系统所需的mixin和修改变量的命名,更好的支持我们创建的函数功能。
@function columns($columns,$container-columns:$maximum-columns) {
$width: $columns * $column-width + ($columns - 1) * $gutter-width;
$container-width: $container-columns * $column-width + ($container-columns - 1) * $gutter-width;
@return percentage($width / $container-width);
}
@function gutter($container-columns: $maximum-columns, $gutter:$gutter-width) {
$container-width: $container-columns * $column-width + ($container-columns - 1) * $gutter-width;
@return percentage($gutter / $container-width);
}
在我们全局样式中,可以使用这些函数来设置元素的宽度(width
)和外边距(margin
)。作为一个例子,让我们看看下面的代码:
div.parent {
width: columns(3);
margin-right: gutter;
div.child {
width: columns(1,3);
margin-right: gutter(3);
}
}
编译出来的CSS:
div.parent {
width: 49%;
margin-right: gutter;
}
div.parent div.child {
width: 30.61224%;
margin-right: 4.08163%;
}
columns
函数至少需要一个参数,它才能正常工作,这就是我们希望该元素的列数。它会基于列数和间距计算元素的宽度。它接受一个可选参数(第二个参数),应用样式的元素是嵌套在另一个元素内。因为计算百分比宽度要根据父元素的宽度,所以我们需要调整我们的子元素上使用的百分比进行补偿。通过提供的跨父元素的列距做为第二个参数,我们Sass函数将重新计算所需的百分比宽度,并相应的调整。
非常基本的样式应用我们的模板中。我们现在准备开始有趣的教程:设置网格函数。
gutter
函数的工作方式也是类似的。如果我们不提供一个参数,它不会执行任何调整。当它给一个嵌套的元素做声明时,我们需要为其提供一个参数,指定它的父元素的跨列的宽度和间距来做计算。
支持mixins
现在我们可以为响应式计算列的宽度和间距。但是让效果有用之前,我们仍然需要更多的样式用于其他元素上。
一般来说,创建一个网格框架,使用.row
来包裹列。如果他存在,可以适用于父元素,或者一个添加了这个类的div
容器。
现在我们的布局完全是弹性的。我们将加点工作扩展这个网格,以适应不同的用例。
我们要给他创建一个mixin,被包含在父元素中。这仍然可以应用于容器div
中,但为了阻止添加表象的标记,可以把他作为mixin嵌套到一个类中。mixin row
需要横跨整个容器的宽度,没有内距,而且里面也必须清除浮动。
@mixin row {
width: 100%;
max-width: $max-width;
margin: 0 auto;
@include clearfix;
@include nesting;
}
row的mixin包了一个清除浮动的clearfix的mixin,还包括了一个nesting的mixin,清除内距padding。所以嵌套的列可以填满整个容器,并且让子元素浮动和有一个适应的列间距。我们还将在这里设置一个border-box
属性。以后,如果我们需要支持的不只是一个div元素,我们可以将他们添加选择器中。这个mixin可让包含在元素内的任何元素在网格系统中对齐。
@mixin nesting {
padding: 0;
& > div {
float: left;
margin-right: gutter();
@include border-box;
}
}
我们也希望我们的网格系统支持列的偏移,因为空白的空间是个好东西,我也想这样使用。当我们想要让一个元素进行偏移时,我们将在我们的样式表中使用一个offset的mixin。他将接受两个参数:一个是元素偏移的方向和元素偏移所占的列数。我们还定义了一个offset-columns
函数,用来计算元素偏移量。
@function offset-columns($columns) {
$margin: $columns * $column-width + $columns * $gutter-width;
@return $margin;
}
@mixin offset($from-direction, $columns) {
@if $from-direction == left {
float: left;
margin-left: offset-columns($columns);
}
@if $from-direction == right {
float: right;
margin-right: offset-columns($columns);
}
}
行中让人讨厌的最后一个列元素
我们需要为每一行中最后一个元素做进一步的处理。如果不删除其margin-right
的值,元素会挤到他相邻的元素。有几种解决方案可以解决这个问题,不幸的是这些解决方法都是CSS的新特性,低版本的IE浏览器不兼容。
第一种方式是在我们的nesting的mixin中添加:last-child
选择器。这种方式,可以删除最后一个元素的margin-right
值。
不幸运,这种方式在IE8以下浏览器不被支持。
另一个解决方案是使用:first-child
选择器。把所有列的margin-right
用margin-left
代替,并且使用:first-child
选择器,删除第一列的margin-left
的值,这样我们也能实现相同的结果。
但先别太高兴了。我们不是要在一个容器里删除第一个或最后一个元素的margin
。我们试图在任何行中删除第一个或最后一个元素的margin
值。我们不想在结构中添加一个div
容器里来实现这一目标,所以:first-child
就出容器了。
下一个更合乎逻辑的解决方案是使用:nth-child()
选择器,它可以完美的实现这一目标,但也像:last-child
一样在IE低版本浏览器中不被支持。下面进入我们的解决方案:定义mixin。
百分比宽度不总是转为人整数像素,在一些浏览器中会有一些错误。我们可以将最后一个元素向右浮动来解决这个问题。
在大多数网格框架中都会有一个.last
或.end
类名,其唯一的目的是为了消除margin
。仅从责任的角度来看,这是完美的,但它也将需要将类名添加到结构中。然而,我们可以使用它作为一个mixin,而不是一个类,我们可以在我们的样式中将它应用到更具语义化的类名里。这种方法虽然没有:nth-child()
选择器那样优越,但也是可以解决问题的。
@mixin last {
margin-right: 0;
float: right;
}
我们在last的mixin中定义元素向右浮动,并且设置margin-right
值为0。这里隐藏了一个如何计算百分比的问题。基本上,百分比并不能像像素一样精确计算,因为不同的浏览器引擎对些计算略有不同。
合并在一起
现在,我们有了自适应网格系统的功能,我们可以将它们应用于我们的结构中。我们先给body元素和容器设置基本样式。
body {
padding: 0 1em;
margin: 0;
}
.container {
width: 100%;
max-width: $max-width;
margin: 0 auto;
padding: 0;
}
给body
元素设置左右内距(padding
)为1em,让我们的内容在小型设备上留有一定的空间。你们注意到,虽然有很多相同的样式,我们并没有在容器中使用@mixin row
。这是因为我们不想@mixin row
的子选择器受影响。我们很舒服,不用重复写代码,因为它只会用在一个地方,这些都是常见的样式,并且只适用于一个容器元素。
接下来,我们会让一些区域就像行,给包含的元素设置一些基本的列样式。
.two-columns,
.six-columns,
.varying-columns,
.nested-columns,
.more-nested-columns,
.offset-columns {
@include row;
}
最后,我们可以给元素定义一些自己的样式。这些都可以基于flexible-column
和flexible-gutter
函数和任何有必要的@mixin nesting
。在这里,我们没有空间放置所有需要的代码,但你可以在我们的05-final
目录中查看css/sass/_global.scss
文件。
我们不仅创建一个自适应的网格布局系统,而且还可以很轻松的修改适用于任何用例。
注意,在实际生产代码,应该会有一些更有效的Sass代码,但在本教程中,我们使用的是在每个元素声明,说明他们的使用。
结束
让我们回顾一下我们所做的。我们开始通过设计一个响应式网格系统并生成所需的分比宽度值。然后,我们创建一个简洁的模板和一个没有太多类名的演示页面。建立我们网站目录后,我们使用Sass编写高效、可维护的所需的代码。然后我们创建必要的函数功能和mixin,生成列和间距的宽度、处理嵌套和列的偏移以及处理容器中每行的最后一列。最后我们应用这些功能在我们的全局样式中,使我们能够把我们页面的元素在网格系统中对齐。
最重要的是,在这里创建的网格功能可以在网格样多表中通过改变变量用于新项目中。总之,我们已经为我们的下一个项目建立了一个网格系统。
译者手语:整个翻译依照原文线路进行,并在翻译过程略加了个人对技术的理解。如果翻译有不对之处,还烦请同行朋友指点。谢谢!
英文原文:http://www.creativebloq.com/web-design/create-flexible-grids-using-sass-9134524
中文译文:http://www.w3cplus.com/preprocessor/create-flexible-grids-using-sass.html