首页 前端知识 CSS3 布局技巧高级教程(二)

CSS3 布局技巧高级教程(二)

2024-09-14 23:09:12 前端知识 前端哥 248 743 我要收藏

原文:Pro CSS3 layout techniques

协议:CC BY-NC-SA 4.0

六、CSS 网格布局

CSS 网格布局为标准布局范式提供了一个明智的解决方案,自从远离基于表格的布局和采用 CSS 布局以来,标准布局范式一直是 web 设计者的挑战。

Note

CSS 网格布局可能是新模块中最难使用的,因为浏览器支持仍在开发中。在撰写本文时,唯一可靠的渲染供应商是微软,尽管在您阅读本书时,这种情况可能已经发生了变化。

什么是 CSS 网格布局?

W3C 将 CSS 网格布局模块描述为定义了一个二维布局系统,为用户界面设计进行了优化。至关重要的是,也是对布局设计者最有用的是,他们继续阐明“在网格布局模型中,网格容器的子容器可以被放置到灵活或固定的预定义布局网格中的任意位置。”我将在接下来的几页中讨论这意味着什么,但这是个好消息!

在讨论技术方面之前,有必要反思一下在布局设计中使用网格的问题。您已经对网格系统很熟悉了,因为您每天都会遇到它们。书籍和杂志使用网格系统来创建它们的布局,使得页面上的元素看起来彼此有某种关系。你见过的每个数据表都使用完全相同的原则来帮助确保数据点正确地归属于它们的图例。事实上,可以说基于网格的布局是 Web 的第一个主要设计步骤:HTML <table>元素被用于布局而不是数据显示。

然而,与表格不同,网格应该能够以基于布局的偏好而不是数据偏好来显示内容,这正是 CSS 网格布局规范要实现的目标。在某些方面,你可以认为它类似于 CSS Flexbox 但是在 CSS 网格布局中,不是所有的事情都发生在一个轴上,而是使用两个维度:块和行(或者,如果你喜欢,列和行)。

当用于布局时,CSS Grid Layout 是一个非常令人兴奋的模块,它使实现灵活流畅的布局变得轻而易举,并保持页面上元素之间的指定关系。这与您在使用浮动元素或表格时可能遇到的有时不可预测和违反直觉的行为形成了鲜明的对比,尤其是在涉及压缩的设备或窗口宽度时。图 6-1 显示了网格布局的典型使用场景。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-1。

A grid-based layout in action

Web 上的网格布局

W3C CSSWG 自 2012 年发布第一份工作草案以来一直致力于 CSS 网格布局模块。在此期间,规范和语法发生了实质性的变化。撰写本文时的当前规范发布于 2015 年 9 月,此处讨论的语法基于在 www.w3.org/TR/css-grid-1/ 找到的文档。

请务必检查在您阅读时是否有更新的规范版本。尽管整体语法正在(缓慢地)向稳定发展,但模块的语法和结构可能会有一些变化。

重申一下,该规范目前被认为是一个工作草案,这意味着在为 1.0 版本的 CSS3 网格布局确定一切之前还有几个阶段要走。你现在是在网络设计的西部,所以穿上你的牛仔靴吧!

Note

理解 CSS 网格布局仍在开发中是至关重要的。您可以在 www.w3.org/TR/css-grid-1/ 查看当前的工作草案规范。

为什么要使用网格?

为了理解为什么你会为你的布局选择一个网格系统,在你的脑海中有一个网格可能是什么样子的图片是有帮助的。W3C 使用了我在这里借用的两个场景来帮助说明 Web 上网格背后的思想和概念。

我已经谈到了设计者对网格作为一种布局工具的固有的熟悉,但是理解 Web 工具没有提供任何有目的的解决方案来创建基于网格的布局是有用的——直到 CSS 网格布局!历史上,设计者使用表格、脚本和像素完美的浮动元素的组合来构建具有网格系统外观的布局。这对于固定宽度的布局非常有效,在这种布局中,设计者可以控制或指定最小的视口宽度。然而,随着智能手机、平板电脑和其他网络连接设备的出现,那些日子已经一去不复返了。布局需要能够适应各种各样的设备配置文件和屏幕方向。

网格布局的基础

CSS 网格布局就是专门为解决这个问题而设计的。在它的基础上,它允许你把可用的空间分成一系列的区域,每个区域都可以用于布局。然后,可以对特定的内容进行定位和调整大小,以占据该网格中的各个列、行和单元格。图 6-2 借用了 W3C 的示例布局来展示一个可以用 CSS 网格布局创建的基本布局。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-2。

A typical application layout that could be achieved with CSS Grid Layout

固有的灵活性

CSS 网格布局背后的核心原则之一是调整布局以适应可用空间不需要额外的工作。响应式设计的好处是 CSS 网格布局的标准!让我们看看 W3C 用来解释这个概念的例子。(此后,我坚定地转向新的例子!)

CSS 网格布局被设计成响应性工作。这意味着随着可用视口空间的定义,元素会在页面内智能地重排。图 6-3 显示了我对 W3C 例子的解释:一个游戏屏幕,在布局中有五个不同的元素。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-3。

My interpretation of the game screen used in the W3C’s example project

注意图 6-3 中显示内容区域划分的虚线。这些是网格线!设想的设计概要中指定了布局的一些基本目标:

  • 统计区域总是出现在游戏标题的正下方。
  • 游戏面板出现在统计数据和标题的右边。
  • 游戏标题和游戏板的顶部应该总是对齐。
  • 当游戏达到最小高度时,游戏板的底部和统计区域对齐,否则游戏板会伸展以利用所有可用的屏幕空间。
  • 得分区域应该与游戏和统计区域创建的列对齐,控件在棋盘下方居中。

传统上,这种布局可能使用具有指定宽度和高度的绝对定位元素、浮动元素和内联元素的组合。由此产生的代码很难破译,也很容易被破解。更糟糕的是,它在不同的分辨率下通常是不可靠的。

通过使用 CSS 网格布局,你可以实现 brief 的所有要求!您将在下一节中详细了解属性和语法;但是首先检查图 6-4 ,它显示了与图 6-3 相同的图,但是在视口中增加了宽度。清单 6-1 展示了使用 CSS 网格布局实现这种布局的一种方式。(现在还不用太担心语法是如何工作的。)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-4。

The same layout you saw in Figure 6-3, but with additional width and height, allowing the board to grow

<style>
#grid {
 display: grid;
 grid-template-columns: auto minmax(min-content, 1fr);
 grid-template-rows: auto minmax(min-content, 1fr) auto
}

#title { grid-column: 1; grid-row: 1 }
#score { grid-column: 1; grid-row: 3 }
#stats { grid-column: 1; grid-row: 2; align-self: start }
#board { grid-column: 2; grid-row: 1 / span 2; }
#controls { grid-column: 2; grid-row: 3; justify-self: center }
</style>

<div id="grid">
 <div id="title">Game Title</div>
 <div id="score">Score</div>
 <div id="stats">Stats</div>
 <div id="board">Board</div>
 <div id="controls">Controls</div>
</div>

Listing 6-1.Achieving the Layout Shown in Figures 6-3 and 6-4 Using CSS Grid Layout

请注意,通过一些额外的造型,该设计可以重新分页以适应纵向屏幕,如图 6-5 所示。您将在本章后面看到如何使用@media查询来实现这种级别的响应。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-5。

The same layout as in Figures 6-3 and 6-4, orientated to work in portrait Note

使用 CSS 网格布局规范有很多方法可以实现这种布局。这个例子摘自 www.w3.org/TR/css-grid-1/ 的工作草案,目的是说明网格的力量,而不是建议最佳实践。

理解术语

我希望你的胃口被激起。让我们继续了解这个模块是如何工作的。与每个 CSS 模块一样,CSS 网格布局也有其特有的术语和语言。它部分是由 W3C 定义的,但是大部分是从传统的图形设计和关于网格系统的讨论中发展出来的。

任何应用了网格布局的元素都被称为网格容器。网格本身是一组相交的水平线和垂直线,将网格容器的空间分成一系列的行和列。因此,有两种类型的线:一组定义沿块轴(也称为列轴)延伸的列,另一组定义沿内嵌轴(也称为行轴)正交延伸的列。

术语 block 和 inline 直接指的是 CSS3 Writing Modes 模块,这意味着列轴不一定是从上到下垂直的,行轴不一定是从左到右水平的。然而,对于大多数基于拉丁语的语言,这是列和行的主要经验;因此,为了理解模块如何工作,可以从这些方面考虑。图 6-6 显示了刚刚定义的术语。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-6。

The key terms used when describing grids in context

在开始探索定义和使用 CSS 网格布局的属性之前,您需要了解一些额外的技术语言。网格轨迹用于定义网格列或网格行。这类似于 CSS Flexbox 使用的语言,所以如果你已经读过第五章,应该听起来很熟悉。

网格单元是每个轴上相邻的两组网格线之间的空间。网格单元是可以放置内容的区域,是网格中的最小单位。同样,这最好用图表来说明,所以请看图 6-7 ,它显示了上下文中的术语。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-7。

The terms grid track and grid cell in context

我们不要忘记网格线。这些是将网格划分成网格区域的线,正如你所看到的,你可以用它们运行的轴来描述它们。在 CSS 网格布局中,还可以使用数字索引或 CSS 代码中指定的名称来显式引用单独的行。

网格项目是分配给网格中的网格区域(或网格单元)的单个元素。网格区域由两对四条网格线定义,可以跨越多个网格单元。每个网格容器包含零个或多个网格项目;网格容器的每个子元素都自动成为网格项目。

图 6-8 显示了上下文中的网格线、网格区域、网格单元和网格项目。您会很高兴地听到,这是在您开始使用代码之前需要的最后一个与网格相关的术语!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-8。

Grid lines, grid areas, and grid items

在 CSS 中定义网格

现在你知道了在 CSS 中谈论网格时应该使用什么语言;让我们直接进入规范,探索如何使用该模块建立一个网格。清单 6-2 展示了一个简单的网格定义,以及用作网格容器和网格项的 HTML 元素。你马上就会看到每一行代码做了什么,但是首先看看图 6-9 ,这是一个根据规范应该如何渲染的图示。请注意,如果您在最新版本的 Internet Explorer 或当前版本的 Microsoft Edge 之外的任何地方进行测试,您将会非常失望!这个特性最近出现在 WebKit nightlies 中,但是只有一个-webkit-前缀。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-9。

An illustration of how the code shown in Listing 6-2 should render in the browser

<style type="text/css">
 #gridcontainer {
 display: grid;
 grid-template-columns: 150px 1fr; /* two columns */
 grid-template-rows: 50px 1fr 50px; /* three rows */
 }
#griditem {
 grid-column: 2;
 grid-row-start: 1;
 grid-row-end: 4;
}
</style>

<div id="gridcontainer">
 <!-- begin the grid item -->
 <div id="griditem">
  <p>Some content or other...</p>
 </div>
 <!-- end the grid item -->
</div>

Listing 6-2.CSS and HTML Markup Defining a Grid

图 6-9 显示了它在浏览器中呈现时的样子(或者至少是我对它应该是什么样子的说明)。我添加了一些额外的阴影,使行更清晰。

Note

需要一些额外的非网格代码来定义图 6-9 中所示的颜色、边框和印刷样式。

让我们看看这个例子的不同元素。

网格容器

网格容器是根据网格布局的规则和属性放置网格项目的元素。通过使用设置为值gridinline-griddisplay属性,将元素定义为网格容器。清单 6-3 突出显示了用于定义网格容器的代码。

#gridcontainer {
 display: grid;
}

Listing 6-3.Defining the gridcontainer Element as Being a Grid Container by Assigning display: grid;

当您使用display: griddisplay: inline-grid定义一个网格容器时,您为该容器的内容创建了一个新的网格格式上下文。该上下文只影响该容器的网格项子元素。外部元素不会影响嵌套的网格项目。

网格容器的两个显示选项

display: griddisplay: inline-grid的区别在于display: grid将容器定义为 CSS 2.1 块级项目,而display: inline-grid将容器设置为内联级元素。如果这听起来很熟悉,那是因为您熟悉 CSS Flexible Box Layout,它使用了关于容器及其在页面流中的处理的类似方法和语法。

定义行和列

当使用display: griddisplay: inline-grid将一个元素作为网格容器时,默认情况下,它有一列和一行,这构成了网格容器的完整大小。这并不是非常有用,所以您可以使用grid-template-columnsgrid-template-rows属性将一个网格容器分成列和行。

在清单 6-4 中,您可以看到如何将网格容器分成两列三行。每行或每列都是依次定义的,每行或每列定义之间用空格隔开。可以使用任何测量单位来设置值,包括fr单位,它定义了一个灵活的空间,该空间由固定大小的项目计算后剩余的空间量来确定。

#gridcontainer {
 display: grid;
 grid-template-columns: 150px 1fr; /* two columns */
 grid-template-rows: 50px 1fr 50px; /* three rows */
 }

Listing 6-4.Defining the Number of Rows and Columns in the Grid, Along with Their Proportions

这定义了两列。第一个被设置为总是占据内嵌轴中 150 像素的空间,第二个被允许填充该轴中剩余的可用空间。

定义了三行。第一个和最后一个都被设置为在块轴上占据 50 个像素的空间。中间一行被设置为填充该轴中剩余的可用空间。这意味着您已经有效地创建了一个流体布局,它总是在第一列的开头有一个 150px × 50px 的单元格,后面是一个流体单元格,然后是另一个固定大小的单元格。第二列再次分为三个单元格,但每个单元格在内嵌轴上都是流体,中间的单元格在两个轴上都是流体。图 6-10 更清楚地说明了这一点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-10。

The effect of the CSS definition of rows and columns in Listing 6-4; incorporating both fixed and fluid sizing Note

fr单元表示可用空闲空间的一部分,但是因为这个例子在每个轴中使用了一次fr,所以它等于所有可用的空闲空间。

The Flexible-Length fr Unit

值得花点时间来谈谈fr单元。fr(或<flex>)单位被定义为可用空间的一部分。每个列或行的空闲空间份额可以根据 W3C 计算为列或行的<flex> * <free space> / <sum of all flex factors>.

最简单的方法是将你在一个轴上使用的所有 fr 单元相加,然后在使用这些单元的元素之间分配空闲空间。因此,一个带有3fr的元素占用的空间是一个带有1fr单元的兄弟元素的三倍。如果只有这两个元素被定义为沿着该轴的fr单元,那么总的可用空间将被计算为分成四部分,其中三个相等的部分被分配给第一个元素,剩余的相等部分被分配给第二个元素。

在容器内定位网格项目

清单 6-3 对#griditem 元素应用了一些代码,将它放在第二列,占据了第 1 到第 4 行。清单 6-5 重复了这段代码,所以你可以明白我在说什么。

#griditem {
 grid-column: 2;
 grid-row-start: 1;
 grid-row-end: 4;
}

Listing 6-5.Positioning of the 
#griditem Element

清单 6-5 显示了我还没有讨论的三个属性。grid-column定义网格项目应该占据的列。这里,您使用一个数字引用来定义一个项目应该位于的列,但是正如您稍后看到的,您也可以使用一个名称。

grid-column一样,你也可以用grid-row定义一个单行来占用。然而,在这种情况下,您跨越了多行,因此您使用grid-row-startgrid-row-end来定义项目所占据的空间的开始和结束。

您可能想知道为什么代码只定义了三列,却引用了第 4 列。答案在于你如何看待列和行。出于 CSS 网格布局的目的,每一列都由开始该列的网格线定义;行以同样的方式工作。如果有三根柱,实际上有四条柱网轴线。请看图 6-11 来看看这是怎么回事。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-11。

There are four grid lines to define three columns

grid-columngrid-row使用了相同的原理,但是因为每一列和每一行前面都有相同编号的网格线,所以这并不能立即看出编号系统是如何工作的。这是需要注意的,尤其是当你开始使用装订线栏和行来分隔内容区域的时候。

清单 6-6 给出了一个例子。它总共定义了五列和三行,但目的只是将内容放入定义为宽度或高度大于 10px 的主要内容区域。

#gridcontainer {
 display: grid;
 grid-template-columns: 150px 10px 150px 10px 150px; /* five columns */
 grid-template-rows: 150px 10px 150px; /* three rows */
}

Listing 6-6.CSS Defining Five Columns and Three Rows, Including Gutter Columns and Rows to Separate Content

该定义的结果如图 6-12 所示;为了清楚起见,主要内容区域都用阴影表示。请注意,即使看起来只有三列两行,您也必须将间距定义为网格容器中的列。理解这一点很重要,因为如果开始使用grid-column属性定位网格项,就需要考虑这些额外的间距列。在本例中,将一个网格项放在列 2 中会导致它占用前两个主要内容列之间的 10px 空间。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-12。

A total of five columns and three rows, with the second and fourth columns set to be 10px wide, and the second row similarly set to occupy 10px of height. This creates the effect of a gutter around the content areas shown shaded

速记网格项目定位

键入grid-column-startgrid-column-end会很快变得令人厌倦;但是和以前一样,CSS 有一个简化的语法来加速开发。只需使用grid-column属性指定开始和结束列(或grid-row的行),用正斜杠分隔两个值。清单 6-7 显示了应用于图 6-12 所示示例的这种简写。最终元件的位置如图 6-13 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-13。

The positioning of element #griditem when the code shown in Listing 6-7 is applied to it

#griditem {
 grid-column: 1 / 4;
 grid-row: 1;
}

Listing 6-7.Position and Span of the #griditem Element, Spanning Three Columns and One Row

Caution

术语“行”和“列”可能会让你分别想到水平布局和垂直布局。但是在 CSS 网格布局中,和 Flexbox 一样,这只适用于水平书写模式。在日语等垂直语言中,row从上到下布局内容。

使用网格区域定位

grid-area属性使用边界网格线显式地控制网格项目的位置,而不是使用列和行的隐喻。语法如下:

grid-area: row-start / column-start / row-end / column-end

通过使用基于坐标的定位方法,这为在网格中放置元素提供了更快的方法。让我们修改清单 6-7 中的代码,以利用grid-area属性,而不是grid-columngrid-row属性。结果代码如清单 6-8 所示。

#griditem {
 grid-area: 1 / 1 / 1 / 4;
}

Listing 6-8.Same Effect as in Listing 6-7, but with Significantly Less Code

跨越多列或多行

如果您希望 CSS 网格布局更像基于表格的布局,可以使用span属性达到同样的效果。这是通过对列数或行数求和,并分配网格项目自动占据正确的行数和/或列数来实现的。继续这个例子,清单 6-9 使用span而不是显式使用grid-areagrid-column-startgrid-column-end。终点是根据起点和跨度计算的。当您希望从视觉上跨越多个列而不是在头脑中记住数字的角度来考虑时,这是非常有用的。你需要记住的是,任何装订线栏仍然有效!

#griditem {
 grid-column: 1 / span 3;
 grid-row: 1;
}

Listing 6-9.Same Result as Listings 6-8 and 6-9, but Using the span Keyword to Define the Grid Item’s Size Occupying Three Columns Total

命名网格线

如果您发现自己因为需要考虑所有多余的列和行而感到沮丧,CSS Grid Layout 允许您根据自己的需要命名各个跨度,从而为这个问题提供了一个实用的解决方案。这是非常灵活和有用的,一旦你习惯了使用命名网格线,它对于代码的易维护性和易读性有很大的实际意义。语法如下所示:

grid-template-columns: [name-of-line1] <width> [name-of-line2]

解释这一点最简单的方法是在上下文中展示它,所以让我们重温一下清单 6-6 中五列三行的早期定义:

#gridcontainer {
 display: grid;
 grid-template-columns: 150px 10px 150px 10px 150px; /* five columns */
 grid-template-rows: 150px 10px 150px /* three rows */
}

可以通过在方括号中指定名称来命名每条网格线。清单 6-10 展示了这在实践中的样子。这些名称几乎可以是任何适合您的名称(保留关键字除外)。

#gridcontainer {
 display: grid;
 grid-template-columns: [col1start] 150px [col1end] 10px [col2start] 150px [col2end] 10px [col3start] 150px [col3end];
 grid-template-rows: [row1start] 150px [row1end] 10px [row2start] 150px [row2end]
}

Listing 6-10.CSS from Listing 6-6, with the Sddition of Named Grid Lines

通过命名网格线,您现在可以在定义网格项目的位置时使用这些名称而不是数字。清单 6-11 显示了来自清单 6-7 、 6-8 和 6-9 的相同网格项目,使用清单 6-10 中的名称进行定位和定义。

#griditem {
 grid-column: col1start / col2end;
 grid-row: row1start;
}

Listing 6-11.Size and Positioning from Listings 6-7, 6-8, and 6-9, Using the Named Lines Defined in Listing 6-10

列表 6-11 的结果如图 6-14 所示。正如您从代码中看到的,当您使用合理的命名策略并根据您对列和行的看法而不是它们相对于装订线列和行的位置来分配名称时,这要直观得多。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-14。

The same net result as shown in Figure 6-13, but the underlying code is potentially easier to understand than earlier listings

此外,值得指出的是,您可以继续对命名的网格线使用span关键字,从而允许进一步的布局灵活性。span继续观察每个定义的列或行,但是。

用重复定义网格

网格容器中网格的定义可以通过使用关键字repeat来自动完成。其语法如下:

grid-template-columns: repeat(<number of times to repeat>, <column definitions to repeat>);

清单 6-12 显示了一个使用中的repeat关键字的例子,它定义了一个总共有 6 列 6 行的网格容器。

#gridcontainer {
 grid-template-column: repeat(3, 150px 10px);
 grid-template-row: repeat(2, 75px 75px 10px);
}

Listing 6-12.Defining Six Columns and Six Rows Using the repeat Keyword

清单 6-12 中代码的结果如图 6-15 所示。同样,为了清晰起见,我给网格加了阴影。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-15。

Six columns and six rows defined using the repeat keyword in combination with grid-template-column and grid-template-row

您还可以使用带有关键字repeat的命名网格线,提供更大的灵活性。清单 6-13 给出了一个例子,它定义了一个网格容器和一个网格项。

#gridcontainer {
 grid-template-column: repeat(3, [column] 150px [colgutter] 10px);
 grid-template-row: repeat(3, [row] 150px [rowgutter] 10px);
}

#griditem {
 grid-column: column 2;
 grid-row: row 1;
}

Listing 6-13.Combining the repeat Keyword with Named Grid Lines to Create a Grid, and Positioning a Grid Item Within It

列出 6-13 的结果如图 6-16 所示。很酷吧。您可以创建一个网格系统,并在网格中定位一个项目,只需几行 CSS 代码!如果你愿意,你仍然可以使用span关键字。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-16。

The result of Listing 6-13, with shading added for emphasis

还有更多!repeat关键字不一定是grid-template-column属性的唯一参数,因此您可以在重复的部分之前或之后添加额外的列(或grid-template-row的行)。这允许你用最少的代码设计一个非常灵活但是精确的网格系统。清单 6-14 中显示了一个例子。另外,请注意,您不必命名每一条网格线。

#gridcontainer {
 grid-template-column: [sidebarstart] 200px [sidebarend] 10px repeat(3, [column] 150px [colgutter] 10px);
 grid-template-row: repeat(3, [row] 150px [rowgutter] 10px);
}

Listing 6-14.Building on the Previous Example to Add a Sidebar Column Before the Repeating Section

列出 6-14 的结果如图 6-17 所示。有一点没有明确显示出来,但是您应该知道,当重复定义导致相邻的命名网格线时,这两个名称会连接成一个名称。举个例子grid-template-column: repeat(2, [a] 20px [b])。这相当于grid-template-column: [a] 20px [b a] 20px [b];

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-17。

The result of Listing 6-14, incorporating a sidebar defined outside the repeating section of the column specification

定义网格区域

我已经提到了网格单元和网格区域之间的区别。一个区域由四条网格线定义:两条列线和两条行线。这些线不需要紧邻,因此一个网格区域可以包含一个或多个网格单元。网格区域对于定义页面布局不同部分之间的语义关系很有用,允许您指定页面的哪个部分包含页眉、侧栏、内容区域和页脚。使用grid-template-area属性定义区域,该属性映射到一组现有的网格轨迹定义上。清单 6-15 展示了一个这样的例子。

<style>
#gridcontainer {
 display: grid;
grid-template-areas: "header header"
                     "sidebar content"
                     "sidebar content";
grid-template-columns: 150px 1fr;
grid-template-rows: 50px 1fr 50px;
}
</style>

Listing 6-15.
grid-template-area Defining a Header, Sidebar, and Content Area in the Grid That’s Already Defined by the grid-template-columns and grid-template-rows Properties

一旦创建了网格区域,就可以通过使用grid-area属性直接分配网格项来占据这些区域;参见清单 6-16 。组合列表 6-15 和 6-16 的结果如图 6-18 所示。请注意,该图人为地分解了网格单元的位置,以使每个网格区域的边界易于识别。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-18。

The defined grid areas. Note that I have exploded this diagram, adding extra space between the grid cells to illustrate the bounds of each area

#item1 { grid-area: header; }
#item2 { grid-area: sidebar; }
#item3 { grid-area: content; }

Listing 6-16.Assigning Three Items to the Three Grid Areas Defined in Listing 6-15

控制网格项目的顺序

正如我所展示的,您可以通过使用grid-columngrid-row属性在网格中任意定位网格项目。此功能的主要好处之一是,它允许您控制页面上元素的视觉顺序,而与它们在代码中的顺序无关。就像 Flexbox 一样,这使得重新分页内容以适应不同的设备配置文件变得容易:响应式设计变得简单。它也促进了风格和结构的分离,并带来了搜索引擎优化的好处。

除了能够直观地定位网格项目之外,您还可以控制它们在屏幕上的呈现顺序。该功能使用 Flexbox 中可用的相同的order属性。通过使用order属性,您可以覆盖缺省值,并指定特定项目在网格呈现流中的位置。order取整数值,较低的值呈现在较高的值之前。负值也是允许的。order在绘制元素的过程中确实会影响 z-index,所以请注意,除非您专门为元素声明了 z-index 值,否则更改它的order属性将会使它在堆栈中向前或向后移动。

自动流动的网格项目

我还没有提到的是,如果你没有为每个条目明确指定一个grid-columngrid-row坐标,网格条目会发生什么。回想一下,默认情况下,网格容器的任何子容器都是一个网格项。没有明确定位和定义的网格项目会自动定位和调整大小,以类似于 flex 项目在 Flexbox 容器中流动的方式流入网格容器。

默认情况下,浏览器在流动网格项目时采用阅读方向规则。在基于拉丁语的语言中,这意味着行从左到右填充整个列,直到一行填满,然后开始新的一行。为了帮助说明这一点,清单 6-17 中的代码包含一个网格容器和九个子元素。

<style>
 #gridcontainer {
 display: grid;
 grid-template-columns: repeat (3, 150px);
 grid-template-rows: auto;
 }
</style>

<div id="gridcontainer">
 <div class="item">1</div>
 <div class="item">2</div>
 <div class="item">3</div>
 <div class="item">4</div>
 <div class="item">5</div>
 <div class="item">6</div>
 <div class="item">7</div>
 <div class="item">8</div>
 <div class="item">9</div>
</div>

Listing 6-17.Creating a Grid Container: Child Elements Become Grid Items by Default

默认情况下,列表 6-17 的结果如图 6-19 所示。注意,使用auto关键字允许浏览器决定需要创建多少行来容纳容器中的网格项。通过使用 grid 容器元素上的grid-auto-flow属性,您可以显式地要求浏览器将项目流入行上下文。默认是row,所以显式设置这个属性的代码是grid-auto-flow : row。将该属性更改为使用值column的结果如图 6-20 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-20。

The result of Listing 6-17, but with the grid flow set to a column specifically. grid-auto-flow: column has been applied to the #gridcontainer element

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-19。

The result of Listing 6-17. Grid items are automatically flowed into the row context, although this can also be explicitly set using grid-auto-flow: row

auto-flow 的另一个很好的特性是,它可以处理您显式放置在网格上的任何网格项目。这意味着你可以将重要元素推到它们指定的位置,然后让你的页面或应用程序中的所有其他内容自动流入周围的空间,完成布局。

子网格

与 Flexbox 一样,单独定义的网格容器相互之间没有渲染效果。这意味着,如果在同一个页面上有两个网格容器,那么在每个网格中呈现和放置内容时,它们不需要(也不会)相互引用。这在大多数情况下是有用的,但有时让一个网格明确引用并遵循另一个网格的比例也是有帮助的。对于这些情况,CSS 网格布局规范中提供了subgrid赋值。

关键字subgrid指定一个网格容器元素,它是一个现有网格容器的子元素,与父网格的布局相关。因此,子栅格中的栅格轨迹观察并符合父栅格的轨迹。这有助于实现表单的完美对齐,如清单 6-18 中的示例代码所示。

<ul>
 <li><label>Name:</label> <input name="fn">
 <li><label>Address:</label> <input name="address">
 <li><label>Phone:</label> <input name="phone">
</ul>

<style>
ul {
 display: grid;
 grid-auto-flow: row;
 grid-template-columns: auto 1fr;
}
li {
 display: grid;
 grid: subgrid;
 margin: 0.5em;
 border: solid;
 padding: 0.5em;
}
label {
 grid-column: 1;
}
input {
 grid-column: 2;
}
</style>

Listing 6-18.Defining a Grid on the <ul> Element and Again on Each <li> within the <ul>; the <li> Elements Are Defined as Subgrids, Allowing Them to Achieve Coherent Alignment with Each Other as Well as with the Overall Parent Grid Defined on the <ul>

列表 6-18 的结果如图 6-21 所示。我使用 auto-flow 选项在父网格中沿着行轴流自动布局每个列表项。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-21。

The result of the subgrid in action in Listing 6-18

在这个例子中,子网格<li>项目的跨度没有被明确地设置。渲染引擎自动注意到子网格中网格单元的使用,并将其映射到父网格上,遵守在父网格上定义的网格轨迹定义。可以用与常规网格项目相同的方式定义轨迹跨度。

显式与隐式网格

至此,您已经专门处理了显式定义的网格,将网格项分配到预定义的网格位置。CSS 网格布局提供了动态定义网格的选项,但是,只需将网格项分配到尚未显式创建的位置。

在这些情况下,会自动创建附加栅格轨迹。例如,如果您将一个网格容器定义为grid-template-columns: 100px 100px 100px 100px,然后应用一个网格项来占据grid-column: 5,则定位网格项所需的额外列将被创建来容纳该网格项。清单 6-17 专门使用关键字auto来请求浏览器将这种行为应用于网格行,但是,严格来说,这不是必需的。就我个人而言,我认为如果有助于避免疑问,具体甚至详细是很好的,所以我倾向于不依赖默认值或行为。什么适合自己,你可以自己拿主意!

将项目与网格对齐

使用应用于网格容器的align-items属性,网格项可以相对于网格对齐。align-items的可能值如下:

  • stretch:默认。扩展项目以填充单元格定义的空间。
  • start:相对于流上下文,将内容与网格单元的开头对齐。项目的大小可以容纳内容。
  • end:和start一样,但是对齐到单元格的末尾而不是开头。
  • center:将内容与网格单元格的中心对齐,根据需要扩展以填充单元格,从而容纳网格项目的内容。

除了沿着流上下文工作的align-items,CSS 网格布局还允许跨流上下文工作的justify-items。对于这两个属性来说,相同的一组值是可以接受的,并且它们以完全相同的方式工作,或者与流动方向一致,或者与流动方向垂直。

图 6-22 显示了align-items的四个对准选项的结果。注意,在这个例子中,流上下文是沿着列轴的,每个网格项占据了 5 行。我调整了单个项目的大小,就好像它们装满了足够的内容,可以有效地占据这五行所提供的空间的一半。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-22。

The four alignment options

最后,还可以选择使用justify-selfalign-self属性在每个项目的基础上设置对齐。这些属性支持相同的四个值,但是被分配给网格项而不是网格容器。

如何使用 CSS 网格布局

到目前为止,您应该已经清楚 CSS 网格布局是多么强大和有用了。它可以单独解决许多常见的布局问题,在许多方面,它是自 Web 诞生以来 CSS 模块设计者一直渴望的。因此,很容易把 CSS 网格布局看作是为所有布局需求提供最终解决方案。

的确,CSS 网格布局将为经验丰富的网页设计师提供一个天堂。注意我对 will 这个词的强调!一旦我将要讨论的问题得到解决,CSS Grid Layout 将会是您的工具集的一个极好的、非常有用的补充。常见的使用场景包括:

  • 杂志风格的布局
  • Pinterest 类型的网络应用
  • 您想要从标记顺序重新排序内容的页面区域(尽管注意 Flexbox 也允许您这样做)
  • 应用程序,尤其是在使用网络视图和针对一系列设备配置文件时
  • 表单和表单元素布局

当然,这仅仅是网格布局好处的开始。如果能够在不同的浏览器上可靠地使用 CSS 网格布局,那么目前 Web 上的许多设计都可以使用 CSS 网格布局来呈现。

浏览器支持

正如我在本章开始时提到的,目前浏览器对 CSS 网格布局的支持很差。微软帮助定义了该规范,并且是迄今为止唯一一家已经准备好部分工作实现并可用于在面向消费者的浏览器版本中测试的供应商,但是一旦该规范变得完全稳定,这种情况将会迅速改变。请注意,在撰写本文时,您可以在 Chrome 的金丝雀版本中访问一些当前规范。

和以往一样,对于目前的情况,你应该参考并定期检查 http://caniuse.com/#search=grid 。维护此站点是为了提供 CSS 网格布局的最新浏览器支持的快照。

后备选项和聚合填充

与所有不支持的 CSS 一样,不理解 CSS 网格布局属性的浏览器会对每个元素使用默认值。这意味着,通常情况下,<div><section><article>等结构项显示为块级元素,而<span>等内联元素则恢复为默认的内联级行为。您可以利用这一点来处理较旧的浏览器,或者如果您喜欢使用众多依赖 JavaScript 来定位和调整元素大小的网格系统中的一个来进行聚合填充。请注意,由于 Flexbox 有一些共同的交叉属性,回退选项可能比您预期的更难预测。Modernizr JavaScript 库允许您测试浏览器支持;您可以在 http://modernizr.com 了解更多信息。

摘要

CSS 网格布局潜在地提供了所有新的到 CSS3 模块中最令人兴奋的布局选项。但是,它还不能在野外使用——除非您愿意编写大量的 JavaScript 回退和/或聚合填充。

然而,我们正处于网格革命的风口浪尖。一旦主流浏览器提供支持,设计者将拥有一个极其灵活的布局工具,它被设计成可以快速响应。CSS Grid Layout 将解决过去 20 年来困扰设计师的许多布局难题,让我们摆脱过去必须的费力而复杂的工作。不幸的是,浏览器支持还不存在,所以在 Web 上使用 CSS 网格布局还不安全。

七、CSS 区域布局

CSS 区域布局使内容从一个框流到另一个框变得容易,而不必担心内容如何适合每个容器。

Note

此模块仍处于编辑的草稿状态,可能会有更改。请务必在 www.w3.org/TR/css3-regions/ 查看最新的 W3C 文档,了解当前语法和规范的详细信息。在Apress.com/9781430265023的图书页面上的源代码选项卡中,也可以查看这本书的代码。

什么是 CSS 区域布局?

CSS 区域布局为控制不同容器之间的内容流提供了一个高级解决方案。各个容器在布局中不必彼此相邻,因此很容易创建杂志风格的布局,这种布局可以灵活地适应内容的变化。

CSS 区域布局不控制页面上元素的布局,只控制内容在元素之间流动的方式。这允许该模块与 CSS 规范中的任何布局模型一起使用。

也就是说,通过添加一个有用的伪元素选择器,您可以使用许多属性来设置流入区域的内容的样式。我将在本章后面讨论::region()选择器和它所替代的selector方法。

如果你现在想使用 CSS 区域布局,你面临的最大挑战是不完整的浏览器支持。Safari 和 Chrome 都提供支持,但 Chrome 默认不支持 CSS 区域布局。Internet Explorer 10 也支持 CSS 区域布局,但源内容只能来自一个iframe。当然,正如许多新的 CSS3 布局模块一样,您可以使用 polyfill 解决方案来支持所有浏览器;我将在本章的后面讨论这些选项。

一个例子

理解 CSS 区域布局能做什么的最简单的方法是直接跳到一个例子中。图 7-1 显示了一个有三个盒子的简单布局。使用 CSS 区域布局来控制每个框的内容,但是使用 CSS2.1 绝对定位和 CSS3 转换的组合来设置布局。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-1。

The layout is controlled by CSS2.1 and CSS3 transformations. The content is controlled by CSS Regions Layout.

清单 7-1 显示了用于创建这个例子的 HTML 标记。请注意,标记中有两个不同的区域:

  • 一个<article>元素中页面的文本内容
  • 不包含可呈现内容的三个<div>元素
<body>
 <article>
  <h1>Lorem Condimentum Fringilla</h1>
  <p>Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec id elit non mi porta gravida at eget metus. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.</p>
   <p>Nullam id dolor id nibh ultricies vehicula ut id elit. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Donec sed odio dui. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Curabitur blandit tempus porttitor.</p>
   <p>Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Nullam id dolor id nibh ultricies vehicula ut id elit. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Maecenas faucibus mollis interdum. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
   <p>Maecenas faucibus mollis interdum. Nulla vitae elit libero, a pharetra augue. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
   <p>Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Etiam porta sem malesuada magna mollis euismod. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Nullam quis risus eget urna mollis ornare vel eu leo. Nulla vitae elit libero, a pharetra augue.</p>
 </article>
 <div id="box1"><!-- no content --></div>
 <div id="box2"><!-- no content --></div>
 <div id="box3"><!-- no content --></div>
</body>

Listing 7-1.HTML Markup for the Example Shown in Figure 7-1

使用 CSS 区域布局时,内容从一个元素(或一系列元素)流入一个或多个区域。提供内容的元素没有在浏览器中呈现,所以清单 7-1 中的<article>没有直接出现在图 7-1 所示的呈现中。

让我们看看用来创建这个布局的 CSS 代码。清单 7-2 展示了呈现这个页面的完整样式表。你可以在 http://www.apress.com 下载这个例子以及本书中所有其他例子的源代码。

body {
 font-family: 'Noto Sans', sans-serif;
 font-size: 62.5%;
}
article {
 -webkit-flow-into: article;
 -ms-flow-into: article;
 flow-into: article;
 font-size: 1.2em;
}
#box1, #box2, #box3 {
 -webkit-flow-from: article;
 -ms-flow-from: article;
 flow-from: article;
}
#box1, #box2, #box3 {
 padding: 4em;
 border: 10px solid #fff;
 position: absolute;
 width: 200px;
 height: 400px;
 background: #fff;
 box-shadow: 0px 0px 10px #999;
}
#box1 {
 background: #f9e719;
 top: 100px;
 left: 100px;
 -webkit-transform: rotate(-5deg);
 transform: rotate(-5deg);
}
#box2 {
 background: #92f919;
 top: 100px;
 left: 370px;
}
#box3 {
 background: #19d2f9;
 top: 120px;
 left: 640px;
 -webkit-transform: rotate(5deg);
 transform: rotate(5deg);
}

Listing 7-2.CSS Code Used in Conjunction with Listing 7-1

这个例子使用了flow-intoflow-from属性来创建区域。id 为box1box2box3的三个<div>各自成为一个区域,而<article>元素实际上成为一个内容存储,并不直接呈现在页面上。

在这里使用 CSS 区域布局的好处是,如果以后想要更新内容,可以简单地编辑<article>元素中的 HTML。内容将在三个定义的区域中重排,无需任何手动格式化。

Note

第一个例子显示了不同厂商前缀版本的flow-intoflow-from属性。其余的例子省略了这些特定于供应商的前缀版本的属性,以避免混乱。在规范完成之前,您需要在自己的代码中包含属性的前缀版本。

浏览器支持

CSS 区域布局是一个相当新的规范,最初由 Adobe 在 2011 年提出并推广。尽管如此,这个提议已经有了几次迭代,一些浏览器提供了相当成熟的支持。Safari 及以上版本支持厂商前缀,Chrome 也是如此(在地址栏中输入about:flags并启用实验性网络平台功能即可启用支持)。Internet Explorer 10 和更高版本也支持 CSS 区域布局,尽管源标记必须包含在一个iframe中。在本文发表时,Firefox 还没有对 CSS 区域布局的任何支持,一些从事 Firefox 工作的工程师公开表示,他们没有实现该提议的计划。这是因为 Firefox 背后的开发团队认为 CSS 区域布局规范存在问题,特别是当提议的 CSS 溢出模块处理一些类似的布局问题时。因此,在这一点上有理由相信这可能是未来发展的一个问题。

Tip

勾选 http://caniuse.com/#feat=css-regions 查看显示最新浏览器支持级别的表格。

语法和结构

CSS 区域布局的语法非常简单。只有两个主要属性:

  • flow-into
  • flow-from

这些属性中的每一个都接受一个命名的参数,该参数在flow-into的情况下定义一个流上下文,或者在flow-from的情况下调用一个流上下文。流上下文可以被赋予任何名称,只要它以字母开头并且包含有效的 CSS 字符。

流入

一旦定义了流上下文,所有分配了与该分配相匹配的flow-into属性的元素都会将其内容贡献给流。它们也从页面的可视布局中删除。

内容分配到流中的顺序由 HTML 标记的顺序决定,按时间顺序排列。清单 7-3 显示了这一点,其中三个不同的内容区域以不同于它们在标记中的位置的顺序被分配给同一个流上下文。

<article id="article1"> <h1>Article 1</h1>
 <p>...</p>
</article>
<article id="article2"><h1>Article 2</h1>
 <p>...</p>
</article>
<article id="article3"><h1>Article 3</h1>
 <p>...</p>
</article>
<div id="layout"><!-- single content container --></div>
<style>
 #article1, #article3 {
 flow-into: reorderedcontent;
}
#article2 {
 flow-into: reorderedcontent;
}
#layout {
 flow-from: reorderedcontent;
}
</style>

Listing 7-3.Order of Content in the Flow Is Determined by the Markup Alone

列出 7-3 的结果如图 7-2 所示。请注意,文章在输出中没有被重新排序,尽管在分配flow-into属性时,它们是按照#article1#article3#article2的顺序定义的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-2。

The order of content is defined by the HTML markup, not the CSS assignment to a named flow.

在将元素分配到流中时要小心,以避免意想不到的后果,这一点很重要。以一个表格为例,可以使用清单 7-4 中所示的代码将它分配给一个流。

table {flow-into: table-content}

Listing 7-4.Moving a Table and Its Contents into a Flow Named table-content

如您所料,该规则将文档中的所有表格移动到名为table-content的流中。除了将所有内容移动到流中之外,表本身也保持了与其他元素的分离。清单 7-5 中显示的代码只选择表中的直接子元素移动到流中。

table > * {flow-into: table-content}

Listing 7-5.Moving All Direct Children of the Table Element(s) into the Flow

这允许文档中来自多个源表的所有表行一起呈现在单个表中。这是一个非常有用的功能。但是,请注意,它留下了作为空元素的<table>,该元素仍然呈现在文档中;因此,如果应用了样式,它们仍然会出现。

不过,考虑一下清单 7-6 ,你会发现这种力量可能会被意外使用,带来意想不到的后果。

table * {flow-into: table-content}

Listing 7-6.Moving All Descendants of the Table Element(s) into the Flow at the Same Level

清单 7-6 中代码的净效果是在一个平面列表中呈现所有表格的内容,而不是像表格通常呈现的那样呈现一个嵌套树。这几乎肯定不是你所期望的。

要吸取的教训是,在处理 CSS 区域布局时,特殊性尤其重要。尽可能具体,以避免意想不到的结果。

Note

CSS 区域布局的另一个潜在的意外后果是,元素周围的任何空白都不会移动到流中,从而导致添加到流中的行内元素彼此相邻。

流动来源

属性允许任意定位的容器形成一系列区域,通过这些区域呈现内容流。图 7-3 展示了如何使用它来创建杂志风格的布局,而不需要将内容呈现到单独的容器中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-3。

Two named flows forming a magazine-style layout

flow-from属性只有两个限制:

  • 命名流必须存在,并且已经使用文档中的一个或多个元素上的flow-into属性进行了定义。
  • 应用了flow-from属性的容器不能已经是区域。

一个页面可以包含无限数量的命名流和无限数量的区域。如果定义了一个已命名的流,但该流为空,则该元素不会以可视方式呈现。值得注意的是,命名流的循环赋值也不能使用;元素不能包含具有相同命名流的flow-intoflow-from属性。

控制断点

当内容从文档流移动到 CSS 区域布局流上下文中时,内容在不同容器区域之间的断点由这些区域的大小决定。当内容跨多个区域流动时,这可能会产生不希望的中断。为了帮助解决这个问题,该规范定义了与flow-from一起支持的三个附加属性:

  • break-before
  • break-after
  • break-inside

这些属性中的每一个都可以应用于 CSS 区域中呈现的任何 HTML 元素,控制跨不同区域呈现的中断。有许多不同的潜在价值:

  • auto
  • always
  • avoid
  • left
  • right
  • page
  • column
  • region
  • avoid-page
  • avoid-column
  • avoid-region

break-beforebreak-afterbreak-inside的属性和可能值已从 CSS3 多列布局模块扩展而来,这将在第四章中讨论。我没有详尽地重复第四章的解释,而是在这里总结并强调 CSS 区域布局引入的附加选项。

除了auto之外,每个中断选项都定义了一个特定的点,在链中的下一个区域中继续呈现之前,内容可以或不可以在该点中断。例如,leftrightpageavoid-page值仅适用于打印页面,强制内容在打印时呈现,以便内容落在左侧页面上。

columnregionavoid-columnavoid-region值每个都允许元素在列或区域之前、之后或内部断开,或者避免这样做。region选项是 CSS 区域布局所特有的。图 7-4 显示了break-before:region选项应用于标题标签时的效果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-4。

s are forced to break before a region

选择何时以及如何在页面上的区域之间分割内容可以提供对页面外观的精细控制,同时保留抽象内容的好处。默认情况下,所有 CSS 布局容器都会扩展以适应其内容,就像普通的内联 HTML 内容一样。这在处理未知数量的内容时很有用,但在目标是基于像素的布局时不太实用。图 7-5 显示了将height属性结合break-after属性应用到一个区域的效果。这个例子的源代码如清单 7-7 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-5。

The second region does not expand to fit its contents

<article>
 <h2>This is the first heading</h2>
 <h2>This is the second heading</h2>
</article>
<div id="region1"><!-- empty --></div>
<div id="region2"><!-- empty --></div>
<style>
 article h2 {
  flow-into: overfloweg;
  break-after: always;
 }
 #region1, #region2 {
  flow-from: overfloweg;
  float: left;
  width: 10em;
  margin-right: 1em;
 }
 #region1 {  border: 1px solid #333; }
 #region2 {
  border: 1px solid #ccc;
  height: 2em;
 }
</style>

Listing 7-7.Applying a Fixed Height to the Second Region <div>

Note

由于break-after: always的问题,这个例子不能在 WebKit 浏览器中正确显示。

区域碎片和溢出

region-fragment属性提供了对命名流的最终区域行为的控制。假设你有一股水流穿过图 7-6 所示的区域。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-6。

A simple CSS Regions Layout flow example

region-fragment属性定义了如果内容占据的空间超过了最终区域(在图 7-6 中标记为区域 4)所能容纳的空间,该如何呈现内容。region-fragment有两个可能的值:

  • auto
  • break

auto允许溢出的内容作为最终区域的一部分进行渲染。break从最后一个区域移除溢出的内容,就像有另一个区域要流入一样。

这和overflow: hidden不一样,它保留了区域内的内容,但隐藏了溢出的内容。图 7-7 结合overflow: hidden显示了两个可能值之间的差异。请注意,region-fragment并不影响最终区域的大小,因此它对调整大小以容纳内容的区域没有任何影响(也就是说,在本例中没有设置height属性)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-7。

Examples of how different region-fragment options render in the browser

因为 CSS 区域布局不处理用于呈现内容的元素的位置或布局,所以理解区域根据应用的布局属性呈现区域片段是很重要的。例如,如果将 CSS 灵活盒子布局与 CSS 区域布局结合使用,内容可能会在水平轴上溢出,而不是在垂直轴上溢出。

新的区域样式方法

如果你还记得本章的介绍,我说过 CSS 区域布局不处理内容看起来的样子——只处理它如何流动。这是事实,但不是全部。

新的::region()伪选择器允许在特定区域呈现的流中的内容上设置视觉特征。这些可视属性大部分是内联的,不会影响文档流,但有些会影响块级呈现。清单 7-8 中显示了使用::region()选择器的语法。

<region-element>::region(selector) {
 // styles
}

Listing 7-8.Syntax to Assign Rules to Content Rendering in a Specific Region Element

清单 7-9 展示了一个真实世界使用场景的例子,它选择了#region1中从流中呈现的所有段落,并应用了2emmargin-right

#region1::region(p) {
 margin-right: 2em;
}

Listing 7-9.Applies a Right Margin of 2em to All <p> Elements Rendered from the Flow in #region1

不幸的是,目前很少有浏览器支持 CSS 区域布局规范的这一部分。

旧区域样式方法

当 CSS 区域布局的原始规范在 2011 年起草时,它要求一个选择器方法,允许以类似于@media查询的方式设计区域中的内容。虽然这已经被::region()取代了,但是 Web 上的很多例子都在继续使用这种语法,三种支持良好的浏览器(Safari、Chrome 和 Internet Explorer)都支持较老的方法。

@media一样,@region使用一个参数来选择应用一组样式的区域。清单 7-10 显示了基本语法。

@region #region1 {
 p {
   margin-right: 2em;
 }
}

Listing 7-10.Example Syntax for the Now-Deprecated @region Selector Method

这个例子使用旧的语法重新创建了清单 7-9 中的例子。CSS 选择 ID 为region1的区域,并将2emmargin-right应用于其中呈现的任何段落。

我建议您避免对生产网站使用这种语法;但是在本文发表时,浏览器对::region()的支持是不存在的。相比之下,Safari 和 Chrome 对@region的支持都不错。您需要自己决定是使用旧的还是新的语法,或者完全避免使用它。

可用选择器

不是每个 CSS 属性都可以应用到用::region()@region选择的元素。可以分配的属性如下:

  • font属性
  • color
  • opacity
  • background
  • word-spacing
  • letter-spacing
  • text-decoration
  • text-transform
  • line-height
  • alignment和对齐属性
  • border
  • border-radius
  • border-image
  • margin
  • padding
  • text-shadow
  • box-shadow
  • box-decoration-break
  • width
CSS 区域布局的视觉特征

CSS 区域布局对于如何在页面上设置区域样式或位置没有任何限制。该模块可以很好地与所有的 CSS2.1 和 CSS3 布局方法结合使用,因此您可以将 CSS 区域布局与 CSS 多栏布局、CSS 网格布局、CSS 灵活盒子布局以及浮动和绝对定位元素结合使用。

多填充选项

正如您所看到的,浏览器对 CSS 区域布局的支持并不像是通用的,而且这在不久的将来也不太可能改变。作为一个网页设计师,这是看到新的 CSS 模块被开发时最令人沮丧的方面之一;我们都渴望尝试新功能,但它们还没有准备好迎接黄金时间。

作为 CSS 区域布局的主要支持者,Adobe 开发了一种 polyfill,在尚未采用该提议的浏览器中为大部分规范提供支持。可以从 http://adobe-webplatform.github.io/css-regions-polyfill/ 下载 polyfill 源代码。除了使用–adobe-作为 CSS 区域布局代码的前缀之外,您可以完全按照打印的内容使用本章中显示的代码示例。

真实世界的例子

如前所述,CSS 区域布局对页面设计中的元素布局没有影响。它可以与本书中讨论的任何其他 CSS 布局模块一起使用。因此,我没有提供其中一个模块的示例,而是结合了 Adobe 为这个简单示例提出的另一个新模块:CSS Shapes。

CSS 形状模块在第十章中有进一步的讨论,所以我在这里不做详细介绍,但是它是一个有趣的,虽然有点古怪的例子,说明 CSS 区域布局如何帮助解决特殊的布局问题。图 7-8 显示了在 Adobe Illustrator 中创建的一个模型:一个简单的杂志风格的布局,其中两个文本区域完美地围绕着一个吉他图像。此示例使用 CSS 区域布局呈现内容,以便内容自动流经两个文本框和 CSS 形状,从而创建包含文本的框。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-8。

A mockup of a magazine-style layout, created in Adobe Illustrator

HTML 标记

这个页面所需的 HTML 标记非常简单。您有一个页面容器,它本身有两个文本框。清单 7-11 显示了页面的 HTML 代码,并包含了取自维基百科关于该主题的文章的文本内容。

<div id="container">
 <div id="title"><h1><span>the development of</span> <br />The Gibson Les Paul</h1></div>
 <div id="box1"><!-- left side of the guitar --></div>
 <div id="box2"><!-- right side of the guitar --></div>
</div>
<article id="content">
 <p> The Gibson Les Paul was the result of a design collaboration between Gibson Guitar Corporation and the late jazz guitarist and electronics inventor Les Paul. In 1950, with the introduction of the radically innovative Fender Telecaster to the musical market, solid-body electric guitars became a public craze (hollow-body electric guitars have more acoustic resonance but are, therefore, more prone to amplifier feedback and have less natural note duration "sustain".) In reaction, Gibson Guitar president Ted McCarty brought guitarist Les Paul into the company as a consultant. Les Paul was a respected innovator who had been experimenting with guitar design for years to benefit his own music. In fact, he had hand-built a solid-body prototype called "The Log", a design widely considered the first solid-body Spanish guitar ever built, as opposed to the "Hawaiian", or lap-steel guitar. This guitar is known as "The Log" because the solid core is a pine block whose width and depth are a little more than the width of the fretboard; conventional hollow guitar sides were added for shape (Image 2), a design similar to the popular Gibson ES-335 semi-hollowbody guitar introduced in 1958\. Although numerous other prototypes and limited-production solid-body models by other makers have since surfaced, it is known that in 1945–1946, Les Paul had approached Gibson with "The Log" prototype, but his solid body design was rejected.[8][9]</p>
 <p>In 1951, this initial rejection became a design collaboration between the Gibson Guitar Corporation and Les Paul. It was agreed that the new Les Paul guitar was to be an expensive, well-made instrument in Gibson's tradition.[10] Although recollections differ regarding who contributed what to the Les Paul design, it was far from a market replica of Fender models. Founded in 1902, Gibson began offering electric hollow-body guitars in the 1930s, such as the ES-150; at minimum, these hollow-body electric models provided a set of basic design cues for the new Gibson solid-body, including a more traditionally curved body shape than offered by competitor Fender, and a glued-in ("set-in") neck, in contrast to Fender's bolt-on neck.</p>
 <p>The significance of Les Paul's contributions to his Gibson guitar design remains controversial. The book "50 Years of the Gibson Les Paul" limits Paul's contributions to two: advice on the trapeze tailpiece, and a preference for color (stating that Paul preferred gold as "it looks expensive", and a second choice of black because "it makes your fingers appear to move faster on the box", and "looks classy―like a tuxedo").[11]</p>
 <p>Additionally, Gibson's president Ted McCarty states that the Gibson Guitar Corporation merely approached Les Paul for the right to imprint the musician's name on the headstock to increase model sales, and that in 1951, Gibson showed Paul a nearly finished instrument. McCarty also claims that design discussions with Les Paul were limited to the tailpiece and the fitting of a maple cap over the mahogany body for increased density and sustain, which Les Paul had requested reversed.</p>
</article>

Listing 7-11.HTML Code for the Magazine-Style Layout Page (Content from Wikipedia)

CSS 形状和 CSS 区域布局代码

如前所述,我不打算解释这个例子中的 CSS 形状代码;你可以在书的后面读到更多关于这个提议的内容。清单 7-12 显示了创建形状和区域的 CSS 代码。和正文一样,吉他图像来自维基百科。

#container {
 position: relative;
 margin: auto;
 width: 960px;
 height: 1200px;
 background: transparent url(guitar.jpg) no-repeat bottom left;
}
#container h1 {
 position: absolute;
 top: 300px;
 left: 50px;
 font-weight: 100;
 font-size: 2.2em;
 text-transform: uppercase;
 margin: 0;
 padding: 0;
}
#container h1 span {
 font-size: 0.5em;
 text-transform: none;
}
article {
 -webkit-flow-into: article;
 flow-into: article;
}
#box1, #box2 {
 -webkit-flow-from: article;
 flow-from: article;
}

#box1 {
 position: absolute;
 top: 385px;
 left: 50px;
 width: 390px;
 height: 600px;
 overflow: hidden;
 -webkit-shape-inside: polygon(0% 0%, 100% 0%, 100% 36%, 70% 50%, 80% 70%, 50% 100%, 0% 100%, 0% 0%);
}

#box2 {
 position: absolute;
 top: 400px;
 right: 50px;
 width: 420px;
 height: 600px;
 overflow: hidden;
 -webkit-shape-inside: polygon(3% 0%, 5% 50%, 28% 50%, 20% 68%, 35% 85%, 45% 100%, 100% 100%, 100% 0%, 0% 0%);
}

Listing 7-12.CSS Used to Render Both CSS Regions Layout and CSS Shapes

Note

这个例子只能在 Chrome(启用了实验特性)或 WebKit 的夜间版本中正确呈现。

结果呢

图 7-9 显示了清单 7-11 中的 HTML 和清单 7-12 中的 CSS 的结果,以启用实验特性的 Chrome 呈现。这不是对我的原始模型的完美再现,但通过一些额外的特定于地区的内容样式,这将是一个非常接近的匹配。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-9。

The result of the code in Listings 7-11 and 7-12, rendered in Chrome

摘要

CSS 区域布局在设计者在页面上放置内容框的方式上提供了一个飞跃,从元素的表现中抽象出元素的内容。这开启了一系列潜在的令人兴奋的新布局可能性。

不幸的是,通用浏览器支持还有很长的路要走,特别是考虑到 Firefox 似乎不太可能在不久的将来实现这一提议。聚合填充选项可以在没有本机支持的浏览器中提供功能,但与任何解决方法一样,这些功能依赖于脚本(用户可以禁用脚本)。在未来的某个时候,CSS 区域布局可能会在 web 设计者的工具箱中扮演重要角色,但目前它只是对未来的一个令人兴奋的一瞥。

八、支持旧浏览器

网络的一个基本原则是有许多不同的设备类型,包括尖端、最新的智能手机、平板电脑和笔记本电脑,以及较旧的企业桌面系统。这对于整个互联网的民主来说是很棒的,但是它给网页设计者带来了头痛,特别是当我们都热衷于采用最新的标准并在我们的页面中充分利用它们的时候。

当你正在为一个网站设计一个新的布局,并且想要采用一个 CSS3 布局模块时,这个问题留给你什么?如何在使用新模块的同时,避免让旧浏览器的用户无法阅读页面?

幸运的是,在大多数情况下,可以采用一种渐进的增强方法(见图 8-1 )来支持这些旧的、过时的浏览器;通过应用一个不需要任何新布局模块就能工作的核心基本布局,您可以将好的东西放在上面。理解新模块的浏览器会遵守增强的规则,不理解的浏览器会忽略它们,坚持核心的后备布局。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-1。

A useful article on the A List Apart web site, found at http://alistapart.com/article/understandingprogressiveenhancement , that explains the concept of progressive enhancement in detail Tip

定期检查你的访问者统计数据,并做出明智的决定,决定投入多少精力来支持旧的浏览器,这是非常值得的。如果仍然运行 Internet Explorer 8 的人每年只访问你 5 次,那么是时候停止花费精力让你的网站为该浏览器服务了!

当别无选择时

尽管渐进式改进在许多情况下都有效,但它并不总是支持旧浏览器问题的令人满意的解决方案。有时项目要求你必须采用一种布局,如果没有对特定 CSS 模块或范例的某种程度的支持,这是不可能的。

在这种情况下,有一种替代方法,它与渐进式增强一起工作,要么以编程方式在旧浏览器中构建对模块的支持,要么使用脚本或黑客来解决缺乏支持的问题。这种处理旧软件不足之处的方法被称为多填充。

维基百科将聚合填充描述为“可下载的代码,它提供了不是内置于网络浏览器中的工具。它实现了开发人员期望浏览器本身提供的技术,提供了一个更加统一的 API 环境。例如,早于版本 8 或 9 的 Internet Explorer 版本不支持 HTML5 的许多功能,但如果网页安装了 polyfill,则这些网页可以使用这些功能。用于描述处理不支持浏览器的类似方法的相关术语包括 shiv 和 shim。然而,不管您如何命名该方法,基本前提是相同的。JavaScript 通常用于询问浏览器对特定功能的支持,如果不支持,它要么提供 CSS 挂钩以允许替代样式(在渐进增强的情况下),要么以伪本机遵守标准的形式提供工作区支持。

实现现代化

在本章的学习过程中,您将会看到,有许多不同的多填充解决方案和多填充方法可供使用,但它们都依赖于使用某种方法来检测浏览器对特定功能的支持,并在发现缺乏支持的情况下,提供一种替代方法。这种方法的基础是特征检测,也许最著名的工具是 Modernizr 库(见图 8-2 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-2。

The Modernizr web page: http://modernizr.com

Modernizr 是一个 JavaScript 库,允许您使用特性检测来确定用于访问您的网站的浏览器是否可以呈现特定类型的内容或支持特定的特性。该库通过一系列测试来检查浏览器中的支持。例如,如果您正在使用 CSS 转场,您可以测试浏览器渲染这些转场的能力,如果浏览器不处理动画,则提供一个后备或替代方案。

Modernizr 允许您编写条件 CSS 和 JavaScript 来根据用户 web 浏览器的功能定制您的网站体验。对于整个 CSS 规范来说,这是一种有用的技术,但是在这种情况下,它特别方便,因为您可以测试对新布局模块的支持。

该库安装快捷,使用简单。当加载带有 Modernizr 的页面时,会创建一个包含测试结果的 JavaScript 对象,并将 CSS 类添加到<html>元素中,允许您通过脚本或 CSS 检查特定的特性是否受支持。

正如我提到的,您可以对特性支持进行测试。这可能会让您想知道具体可以运行哪些测试,以及 Modernizr 支持哪些特性。这个库之所以如此有用和受欢迎,是因为它几乎是浏览器功能支持测试的一站式商店。Modernizr 允许您测试 40 多种下一代功能,包括font-facergba、CSS 动画、渐变、画布、HTML5 音频和视频、本地存储和 WebGL。最重要的是,它可以用来测试本书中讨论的 CSS3 布局模块!

这个库不会强迫你为每一个特性运行测试;Modernizr 的一大优势是它的模块化特性。你只需要测试你需要的特性,而不是必须进行每个单独的特性测试(见图 8-3 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-3。

Customizing the Modernizr library to suit the specific tests required for a given project THREE ALTERNATIVE METHODS TO TEST FEATURE SUPPORT IN BROWSERS

在服务器上

如果您担心依赖 JavaScript 来识别浏览器特性,您可以使用服务器端嗅探来代替。这种方法使用浏览器的user agent属性在页面被发送到浏览器之前将特定于浏览器的类注入到html元素中。请注意,这与任何类型的浏览器嗅探都有相同的潜在问题:它不能很好地伸缩。

条件注释

解决浏览器缺陷的另一个潜在解决方案是使用条件注释来有选择地加载样式表和脚本。这种方法通常用于 IE6 和 IE7,并允许根据版本号和供应商进行加载,尽管支持仅限于 Internet Explorer。

@支持

CSS3 被提议的新特性之一是@supports方法。这让您可以编写浏览器呈现特定 CSS 属性能力的条件测试,其工作方式类似于@media查询。具有讽刺意味的是,@supports最大的问题是缺乏浏览器支持。

现代化的替代方案

需要强调的是,Modernizr 并不是唯一一个解决浏览器中缺失支持的解决方案。事实上,Modernizr 本身只是询问浏览器是否支持特定的特性,并相应地更新 DOM 以指明哪些特性支持哪些特性不支持。

与网络上的任何图书馆一样,在你最喜欢的搜索引擎中做一点研究是值得的,因为形势正在迅速变化(见图 8-4 )。使用 Modernizr 的一个好处是,由于它被广泛采用,bug 修复往往会定期发布。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-4。

More than 20,000 results when searching for a polyfill for CSS Multi-columns Layout Note

在创作您的页面时,我再怎么强调在网上查找最新最好的 polyfill 解决方案的重要性也不为过。当你读到这本书的时候,情况已经足够多变,可能会有许多新的解决方案在现有的基础上有所改进。

夜明珠

YepNope 挂钩到特定 Modernizr 测试的结果,并使用它们将资源加载到浏览器中(参见图 8-5 )。这非常有用:如果您能够将代码分成单独的部分,那么添加的 YepNope 允许您有条件地加载脚本和样式表。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-5。

The YepNope download page at http://yepnopejs.com

因为它只有在 Modernizr 测试运行之后才会被调用,所以您可以根据浏览器特性支持有条件地加载脚本和样式,从而避免在每个浏览器中加载所有的解决方案。只有那些需要多填充物的人才能得到它们。当与本章稍后描述的预构建 polyfill 解决方案结合使用时,Modernizr with YepNope 几乎为您在生产网站中实现 CSS3 布局模块时所面临的许多兼容性问题提供了一个拖放式解决方案。

请注意,在撰写本文时,YepNope 已经停止使用,因为 Modernizr 已经更新,包含了足够的功能,使 YepNope 加载程序不再必要。如果您使用的是 Modernizr 的最新版本,几乎可以肯定您不再需要 YepNope,但我在这里提到了它,以防您在企业环境中坚持使用旧版本。

Tip

选择 http://caniuse.com 查看显示浏览器对单个 CSS 布局模块支持的最新级别的表格。

使用 Modernizr 的示例

让我们快速地看一个 polyfill 的例子,它使用 Modernizr 为不支持您正在使用的模块的旧浏览器提供类似 CSS3 的支持。这个例子使用 CSS3 多列布局模块设计了一个简单的无序列表,将列表的内容分布在一系列列中。在大多数现代浏览器中,这不需要任何供应商前缀或特殊的变通方法。查看 http://caniuse.com/#feat=multicolumn 了解最新的浏览器支持。请注意,Internet Explorer 8 和 9 不提供对此模块的任何支持。

该项目

首先,用一些非常基本的样式生成一个 HTML 文档,以创建一个简单的多列布局。你可以在清单 8-1 中看到代码,在图 8-6 中看到 Safari 的输出。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-6。

Output of Listing 8-1 in Safari on a Mac

<!DOCTYPE HTML>
<html>
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   <title>Multicol Polyfill Example</title>
   <style>
    body {
     font-family: arial, helvetica, sans-serif;
     font-size: 62.5%;
     background: #fff;
     color:#333;
     }
     article {
     background: #eee;
     position: relative;
     padding: 20px;
     width: 920px;
     margin: auto;
}
     article h1 {
     font-size: 2em;
}
     article ul {
     columns: 3;
     }
     article ul li {
     list-style: none;
     font-size: 1.2em;
     padding: 5px;
}

  </style>
 </head>
 <body>
 <article>
 <h1>Things that I like</h1>
 <ul>
   <li>Coffee</li>
   <li>Tea</li>
   <li>The Java Jive</li>
   <li>Lazy Sunday mornings</li>
   <li>A good book</li>
   <li>Nights at the movies</li>
   <li>The smell of baking bread</li>
   <li>Smiling</li>
   <li>Old-fashioned jazz and blues</li>
   <li>A freshly-made bed</li>
   <li>Hugs</li>
  </ul>
 </article>
</body>
</html>

Listing 8-1.Code to Achieve a Three-Column Layout with the CSS Multi-column Layout module

如您所见,代码通过将 CSS 代码columns: 3添加到样式表,将规则应用到ul元素,创建了一个基本的三列布局。这适用于除 Internet Explorer 8 和 Internet Explorer 9 之外的所有常用浏览器。然而,你不能绝对保证用户只能使用常用的浏览器。为了确保不支持 CSS 多列布局的浏览器用户也能看到呈现为三列的列表,您可以使用 Modernizr 来测试支持,如果没有找到支持,则使用 polyfill 来呈现列。

聚合填料

这是一个非常基本的布局,因此您不需要任何花哨或壮观的东西来解决缺乏浏览器支持的问题。您可以使用专门为呈现多列内容而构建的多列填充:多列多列填充,您可以在 https://github.com/hamsterbacke23/multicolumn-polyfill 找到并下载。

在使用这个脚本之前,您需要确保在您的页面上安装并激活了 Modernizr。向页面的<head>部分添加一行代码,以调用 CDN 托管版本的 Modernizr 库,如清单 8-2 所示。

<head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>Multicol Polyfill Example</title>
<script src="jquery.js"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>
 <style>
  body {
   font-family: arial, helvetica, sans-serif;
   font-size: 62.5%;
   background: #fff;
   color: #333;
  }

Listing 8-2.Adding a CDN-Hosted Version of the Modernizr Library

现在您已经在页面上安装了 jQuery 和 Modernizr 库,您可以使用一个简单的 JavaScript 测试来检查浏览器是否支持 CSS 多列布局模块。将它添加到代码中紧接在结束的</body>标签之前,如清单 8-3 所示。

  <li>Hugs</li>
  </ul>
  </article>
  <script src="polyfill/multicolumn.js"></script>
  <script>
   if (!Modernizr.csscolumns) {
     $('article ul').multicolumn();
   }
   </script>
 </body>
</html>

Listing 8-3.Test and Polyfill in Action 

这一额外代码的结果是,如果浏览器没有通过多列支持的 Modernizr 测试,则加载 polyfill。polyfill 使用浮动元素跨列呈现内容,并隐藏原始容器。就这么简单明了。

这个特定的示例解决了一个非常简单的多填充布局问题,但是无论您的需求变得多么复杂,同样的原则也适用。分解每个元素和聚合填充就是识别功能、测试支持,然后为这些布局元素提供备用方案。注意,不保证支持特定的浏览器。这取决于您选择的特定聚合填充,如 IE9 没有使用前面的示例呈现列所示。

Note

在撰写本文时,Modernizr 正在经历一个新的大版本。您可以复制并粘贴特定的测试代码,而不是下载或安装整个库,这些代码特定于您想要检查的特性。请务必访问 Modernizr 网站以获得该库的最新版本。

预建多孔填料

有时,现成的聚合填充解决方案无法满足您的特定需求,在这种情况下,您可能会发现自己需要构建自己的脚本,以提供功能来替代缺少的支持。然而,在大多数情况下,简单地使用 Modernizr、YepNope 和一个预构建的 polyfill 脚本就足够了。还要注意,还有其他不使用 Modernizr 的选项。

为了让您对涵盖布局模块的现有聚合填充的范围有所了解,以下是从 Modernizr 博客(其中有一个广泛的选项列表)中借用的一个略加整理的列表。要查看完整列表,请访问注释中的链接:

  • CSS 多列布局:塞德里克·萨瓦雷塞多列填充, http://alistapart.com/article/css3multicolumn
  • CSS 灵活的盒子布局:由理查德埃雷拉灵活, http://flexiejs.com
  • CSS 网格布局:弗朗索瓦·雷米的网格布局 polyfill, https://github.com/FremyCompany/css-grid-polyfill
  • CSS 模板布局:CSS 模板布局 jQuery 插件由 Alexis Deveria, https://code.google.com/p/css-template-layout/
  • CSS 区域布局:弗朗索瓦·雷米的区域填充, https://github.com/FremyCompany/css-regions-polyfill

Note

有关本书中每个布局模块特定的 polyfills 的完整列表,请参考 Modernizr 在 https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills 发布的关于该主题的博客文章。

摘要

虽然当新功能出现时,人们很容易被冲昏头脑,特别是在标准实现速度非常慢的 Web 上,但是不要忽视支持旧浏览器的需要,这一点很重要,因为旧浏览器在访问您的网站的用户中占很大比例。在许多情况下,聚合填充为提供支持提供了一个实用的解决方案。如果由于技术或资源原因,这样做不切实际或不可能,那么采用渐进式增强方法可以提供一种有用的替代方法,确保您的内容易于访问且用户友好。

随着浏览器支持的改进和用户更新他们的系统以利用最新的软件,polyfills 应该会变得不那么流行。但是就目前而言,当你想使用本书中讨论的布局模块之一,并且不能控制观众的操作系统和设备配置文件时,它们是值得使用的。

不要忘记通过你最喜欢的搜索引擎定期检查新的和改进的 polyfills。全世界有才华的 web 开发人员都在不断构建解决方案,以解决通用浏览器中尚未实现的模块问题。

九、加速工作流:CSS 库和框架

从事网页设计需要大量的重复工作:虽然每个页面都是独一无二的,但是大部分底层代码都依赖于相同的核心原则和构建模块。CSS3 引入的布局模块为许多不同的布局范例提供了一个整洁的解决方案,但是当你一遍又一遍地设计本质上相同的布局时,它们可能会变得不必要的复杂。在使用核心构建块时,您如何减少时间和复杂性开销?通过使用 CSS 库和框架,您可以简化布局过程,抽象一些复杂性,并提供一个一致、快速的开发平台。

您很可能熟悉许多这样的框架和库;它们不是新的,也不局限于 CSS3 布局模块。一些最受欢迎的网站是建立在开源框架之上的,这些框架是由 Twitter、微软、苹果和脸书背后的开发团队开发的。例如 Bootstrap,它提供了一种简单的解决方案,以响应方式创建许多布局元素,几乎适用于所有可能的设备。这些框架都倾向于去除与基础 CSS 代码的直接联系,使得开发成为将适当的结构和 CSS 类应用于页面结构中的单个元素的情况。

许多库和框架处理的不仅仅是布局。内置的许多功能还允许您以一致的方式制作小部件和按钮以及样式副本和标题。这可能有好处,但是如果你只想能够使用一套预定义的风格进行设计,你就不会有这本书在你的手中!这一章向你介绍了一些最好的 CSS3 布局库和框架,特别关注于保持样式的工作在你的控制之下。不可避免地,你会找到一个你喜欢的,你会坚持下去。有必要定期查看网络,看看在线社区开发了哪些新的框架(例如,见图 9-1 ),因为环境是如此的不稳定,事情可能会变化得非常快。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-1。

There are many web sites dedicated to showcasing CSS3 libraries and frameworks, such as SpeckyBoy ( http://speckyboy.com/2014/06/02/css-libraries-frameworks-tools/ ) Tip

一旦你找到了你喜欢的图书馆,花时间去了解它的细微差别会在以后带来巨大的回报。但是不要坐以待毙,接受你已经找到了库/框架选项的顶峰。货比三家是值得的!

不要从头开始

库和框架有多种形式。有些是全功能的网站开发工具,充当页面布局、设计实现和内容样式的脚手架。其他人采取更结构化的方法,提供构建模块,并从美学的角度处理页面上的元素。

这两种方法各有优缺点,但它们有一个共同的目标:加速页面的开发,使代码更容易实现一致性。您不需要从头开始设计每个新页面:相反,通过调用合适的库,您可以使用其他人的工作来减少重复工作。

开发人员和设计人员倾向于找到他们喜欢的工具并坚持使用。当您使用特定的库或框架时,这会带来好处,因为随着您对特定代码库的方法越来越熟悉,您可以充分利用它所提供的优势。忠于一个工具也有它的缺点,尤其是因为看不到其他可用的工具,您可能会错过其他地方提供的增强功能和能力。因此,我鼓励您尝试许多不同的库和框架,并不断进行采样。

经常反对使用其他开发人员代码的一个论点是,您可能会依赖于该供应商的意愿和能力来消除 bug 并提供更新和修订。学习每个特定代码库的细微差别也需要时间投入。我想让你相信,前期的一点投资可以在未来带来巨大的时间(和金钱)收益。

另一个值得讨论的问题是跨浏览器的可操作性,这也是库和框架倾向于缓解的一个问题,而您对此不必太担心。尽管(幸运的是)一些最糟糕的 CSS 实现差异已经成为过去,但是对于规范中的各个模块应该如何集成,仍然存在不同的解释。对于新兴的模块来说尤其如此,比如你在本书中看到的那些。通过使用一个库,你可以在图 9-2 中看到一个例子,你可以消除提供厂商前缀版本选择器的不确定性。这意味着你有更多的时间花在整体布局上,而不是浪费时间去弄清楚为什么一个特定的浏览器不像其他浏览器那样实现你的设计。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-2。

The YAML webpage, found at http://www.yaml.de

同样,与这种好处相反的是,库有时会变得臃肿和笨重,这意味着它们可能会影响网站的性能。当您只对公司的企业设备感兴趣时,支持世界上所有设备的额外代码可能会超过使用库的一些好处。

库和框架没有正确的答案

正如你所看到的,有支持和反对使用 CSS 库和框架的争论。它是否适合您的特定项目,这个问题只能通过您自己的分析来回答,而且通常需要您做出判断。

然而,认识到在某些情况下使用它们是有益的,本章的其余部分将致力于研究在写作时可用的一些选项。在本章快结束时,你还将重温在第五章完成的一个项目,看看如果你使用一个库而不是原始的 CSS 代码,它会如何被不同地解释和实现。

Note

一些库和框架使用 CSS3 布局模块和非 CSS3 布局技巧的混合方法。除非您是一个纯粹主义者,否则这可以为实现特定布局的问题提供一个好的、健壮的解决方案。

最好的 CSS 框架和库

考虑到你正在一个非常不稳定的时期使用 CSS3 布局模块,这一节的标题是加粗的,但是我挑选了一些目前可用的最好的 CSS 框架和库。我怎么知道他们是最好的?我对搜索引擎结果进行了一项完全不科学的研究,以确定大众观点。我会一直这么说:当你开始搜索一个图书馆的时候,你一定要看看网上社区是怎么说的。

如前所述,有两种基本类型的库和框架可用。区别就像一个普通的汽车旅馆房间和五星级酒店房间一样。有时候,你想要的不过是四面墙和一张床,能够自己做饭,可以随心所欲地使用自己的房间;其他时候,你希望奢侈地让其他人担心细节,并且把所有东西都放在银盘上带给你!

在最基本的层面上,CSS3 布局库只提供挂钩来允许您创建网格布局、呈现 flexbox 或调用多列布局,除了将适当的类名应用于一系列的<div><section><article>之外,无需做任何其他事情。这些类似于一个基本的汽车旅馆房间。他们只做一件事,仅此而已。剩下的就看你自己了!另一端是完成所有布局的解决方案,这些解决方案还提供小部件、样式和皮肤,它们基本上可以提供实现页面设计和布局所需的所有工具,包括所有的美学。

我在汽车旅馆的房间里犯了错误。但是,不要让这阻止你追求全面服务的选择,如果它能更有效地满足你的特殊项目的需求。

Flexbox 网格

Flexbox 网格系统是一个简单明了的库,旨在允许您使用元素上的类将不同的 Flexbox 属性分配给布局,而不必直接钻研 CSS(参见图 9-3 )。由 Kristopher Joseph 创建,这是一个非常轻量级的解决方案,几乎不抽象源代码 CSS3 Flexbox 代码;但正因为如此,也真的很容易学会使用。在本章的后面,您将使用这个库来重新创建原来的 Flexbox 项目。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-3。

Flexbox Grid, found at http://flexboxgrid.com

ptb/flexgrid

该框架也基于 Flexbox 模块,但它并没有提供框架,而是试图重新创建 Bootstrap 使用的相同布局范例(见图 9-4 )。由此产生的网格布局比其他选项要严格得多,但是如果您已经熟悉了 Bootstrap 12 列网格,您会立即有宾至如归的感觉。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-4。

ptb/flexbox, found at http://ptb2.me/flexgrid/

ptb/flexgrid 完全是为了在网格系统中布局内容而设计的——没有花哨的用户控制样式或额外的小部件。结果是,除了 Modernizr 库之外,整个框架占用的空间不到 2 KB,Modernizr 库是确保布局在所有浏览器上都能工作所必需的。

指南针

Compass 与本节重点介绍的其他库和框架的不同之处在于,它不仅仅使用单个 CSS3 布局模块,而是提供了一个解决方案,使得使用 CSS3 和 CSS 中的所有可用工具更加容易(参见图 9-5 )。前提很简单:减少与精心设计特定设计相关的代码混乱,并提供对 Web 上流行的可重用设计模式的轻松访问。这意味着您可以使用该框架,使用您熟悉的构建块来快速原型化和部署布局。还有许多扩展,涵盖了从排版控制到精灵生成的所有内容。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-5。

Compass, found at http://compass-style.org

CSS 区域聚合填充

尽管 Francois Remy 的 CSS Regions Polyfill 在技术上并不是一个框架,但我在这里包含了它,因为它为立即使用 CSS 区域布局规范提供了一个真正有用的解决方案(见图 9-6 )。使用 Francois 的 JavaScript 库的特别好处是,它允许您实现没有浏览器供应商前缀的区域,使您今天编写的代码仍然需要直接访问和理解 CSS 区域布局模块,但由于 JavaScript,它是面向未来的,同时仍然可以被旧浏览器访问。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-6。

CSS Regions Polyfill, found at https://github.com/FremyCompany/css-regions-polyfill

因为该库使用原始规范,所以除了本书所涵盖的内容之外,您不需要了解任何其他内容。这不会简化您的代码,但它消除了在提供跨浏览器支持和回退方面的一个令人头痛的问题。

反应灵敏的永旺

这个基于网格的库使用了与这里强调的其他一些库类似的方法,但是布局工程是完全抽象的,所以不能立即看出哪些模块被用来创建布局(见图 9-7 )。事实上,最新的更新使用了大量的 CSS2.1 来产生布局,同时使用了类似于 CSS3 网格布局的方法。请记住,当你使用 CSS 布局时,你是在调用几十年工作的组合;因此,如果您需要比“开发中”的 CSS3 模块更稳定的东西,这可能是迈向完全 CSS3 解决方案的一个很好的跳板。代码非常简单,因此也适合进行定制,以形成您可以在未来项目中重用的库的基础。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-7。

Responsive Aeon, found at http://newaeonweb.com.br/responsiveaeon/

仅仅是开始…

请记住,本章中强调的库和框架只是 Web 上可用选项的开始。为了加快工作流程,尽早投入时间检查和探索可用的选项至关重要。

Note

在这里,我再次强调,当你创作你的页面时,在网上查找最新最好的库和框架是非常重要的。当你读到这本书的时候,几乎可以肯定的是,在写作的时候,将会有许多选择加入到可用的组合中。

加速您的工作流程:一个例子

既然您已经看到了一些当前可用的使用 CSS 库和框架来加速页面开发的选项,那么让我们更详细地研究其中一个,看看使用其中一个库会是什么样子。出于这种探索的目的,让我们回到您在本书前面看到的一个示例项目。这是很有用的,因为它允许您看到如何通过使用框架来简化早期编写的代码。

现实世界的例子

如果你还没有阅读第五章的话,现在就快速浏览一下,熟悉 CSS Flexbox 以及它是如何填充空间的。此示例重新创建了该章中的项目;但是它没有使用原始的 CSS Flexbox 代码,而是利用了 Flexbox 网格库,并显示了该库对代码的影响。

让我们回忆一下您想要创建的布局。图 9-8 显示了第五章中的模型;这个例子使用了完全相同的元素来创建这个项目的另一个版本,但是一旦你熟悉了 Flexbox 网格库,这应该会容易得多。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-8。

The project to be re-created from Chapter 5 using a library instead of raw CSS flexbox code

如果你一直在关注,你会发现 Flexbox 被用来创建图 9-9 中的布局。为了提供公平的比较,您将使用相同的模块来呈现库支持的布局。这意味着调用本章前面强调的 Flexbox 网格库。我不是在支持那个特定的图书馆。但是正如您将看到的,它确实为精心设计布局提供了一个有效且实用的解决方案。正如前面的布局尝试一样,让我们专门关注页面的三个部分:导航栏、大屏幕区域和利益陈述。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-9。

If you’re eagle-eyed, you’ll notice that this is practically the same as the render in Chapter 5 following the native CSS attempt. The primary difference is that this version aligns to a grid

HTML 标记

让我们从第五章中使用的 HTML 标记开始,如清单 9-1 所示。这个页面的代码很简单,遵循的模式类似于过去使用浮动来排列设计元素时使用的布局。

<!—The navigation section -->
<nav>
 <ul>
  <li><a href="#">Home</a></li>
  <li><a href="#">Locations</a></li>
  <li><a href="#">Financing</a></li>
  <li><a href="#">Special Offers</a></li>
  <li><a href="#">About us</a></li>
  <li><a href="#">Contact Us</a></li>
  <li class="searchform"><form><input type="text" value="search" /></form></li>
 </ul>
</nav>

<!—The big icons/jumbotron section -->
<section id="jumbotron">
 <article>
  <h2>Free Advice</h2>
  <p>All our impartial advice is offered completely free of charge</p>
  <img src="img/bigicon-freeadvice.png" />
 </article>
 <article>
  <h2>Discounted Removals</h2>
  <p>Once you've found your dream…
...</article>
</section>

<!—The badge benefits section -->
<section id="benefits">
  <article>
   <h1> Looking for a beautiful new home that won't break the bank?</h1>
   <p> Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue. Cras mattis consectetur purus sit amet fermentum.</p>
  </article>
  <article class="badge">
   <div>
    <h3>Quality without compromise</h3>
    <p>We have homes that suit every budget without compromising on quality</p>
   </div>
   <img src="img/badge-quality.png" />
  </article>
  <article class="badge">...
  ...</article>
</section>

Listing 9-1.HTML Code for Three Parts of the Page Suited to Flexbox Layout

使用图书馆

不同的库有不同的实现方案。这个例子使用了 Flexbox 网格库,所以您下载了这个库,并按照说明将其插入到我的页面中。这就像在<head>部分创建一个<link>一样简单,如清单 9-2 所示。

<head>
  ...
   <link rel="stylesheet" href="css/flexboxgrid.min.css" type="text/css">
  ...
</head>

Listing 9-2.Installing the Library by Copying Files into the Web Site Folders and Using a <link> Statement

Tip

回想一下,由于新的 CSS3 模块是由浏览器供应商实现的,所以他们在实现中倾向于从特定于供应商的前缀开始。库和框架消除了你关心这些细微差别的需要。

导航

您需要处理的页面的第一部分是贯穿设计顶部的导航。如果你回头参考第五章,你会发现直接使用 Flexbox 非常简单。清单 9-3 重复了第五章中使用的 CSS 代码,来说明有多简单!使用 Flexbox 网格库同样简单,如清单 9-4 所示。

/* The navigation section */
nav > ul {
  display: flex;
  flex-flow: row wrap;
 }
 nav > ul > .searchform {
  margin-left: auto;
 }

Listing 9-3.Native Flexbox CSS Code to Create the Navigation Layout

<!—The navigation section -->
<nav>
 <ul class="row start-xs">
  <li class="col-xs"><a href="#">Home</a></li>
  <li class="col-xs"><a href="#">Locations</a></li>
  <li class="col-xs"><a href="#">Financing</a></li>
  <li class="col-xs"><a href="#">Special Offers</a></li>
  <li class="col-xs"><a href="#">About us</a></li>
  <li class="col-xs"><a href="#">Contact Us</a></li>
  <li class="col-xs-offset-2 col-xs searchform"><form><input type="text" value="search" /></form></li>
 </ul>
</nav>

Listing 9-4.Using the Flexbox Grid Library and Altering the HTML Code to Apply Specific Classes to Elements

如您所见,这两种方法的主要区别在于,当您通过直接编写 CSS Flexbox 代码来处理实现时,您使用 CSS 来创建布局。在 Flexbox 网格库的情况下,您可以将类名应用于 HTML。在这个例子中,差别是微不足道的;但是随着事情变得越来越复杂,如果您希望更改出现在布局中的项目数量,第二种方法会更加灵活。图 9-9 显示了实现 Flexbox 网格库后 Chrome 中的导航输出。

大屏幕

使用直接的 CSS,超大屏幕很容易制作。回想一下以下关于设计模型的内容,这些内容有助于将设计模型转化为功能性布局:

  • 每个<article>大小均匀。
  • 大屏幕中每个元素的内容在两个轴上居中对齐。
  • 图像在文本之前呈现,但出现在标记中的文本之后。

回头查看 HTML 代码,注意最后一点要求您在演示过程中对内容进行重新排序。Flexbox 让这变得简单明了,Flexbox 网格库也是如此。同样,通过将特定的类应用到标记中的元素来处理所有事情。清单 9-5 中显示了使用该库的代码。

<!—The big icons/jumbotron section -->
<section id="jumbotron" class="row">
 <article class="col-lg-4 col-xs-12">
  <div class="marginbox row">
   <h2 class="col-xs-12">Free Advice</h2>
   <p class="col-xs-12">All our impartial advice is offered completely free of charge</p>
   <div class="col-xs-12 first-xs"><img src="img/bigicon-freeadvice.png" width="52" height="41" /></div>
  </div>
 </article>
 <article class="col-lg-4 col-xs-12">
  <div class="marginbox row">
   <h2 class="col-xs-12">Discounted Removals</h2>
   <p class="col-xs-12">Once you've found your dream home we can help get you moved in</p>
   <div class="col-xs-12 first-xs"><img src="img/bigicon-removals.png" width="50" height="41" /></div>
  </div>
 </article>
 <article class="col-lg-4 col-xs-12">
  <div class="marginbox row">
   <h2 class="col-xs-12">Buying Incentives</h2>
   <p class="col-xs-12">Many of our homes offer additional benefits such as rebates</p>
   <div class="col-xs-12 first-xs"><img src="img/bigicon-incentives.png" width="24" height="41" /></div>
  </div>
 </article>
 <article class="col-lg-4 col-xs-12">
  <div class="marginbox row">
   <h2 class="col-xs-12">Locations nationwide</h2>
   <p class="col-xs-12">We have agents and properties across all 50 States</p>
   <div class="col-xs-12 first-xs"><img src="img/bigicon-locations.png" width="41" height="41" /></div>
  </div>
 </article>
 <article class="col-lg-4 col-xs-12">
  <div class="marginbox row">
   <h2 class="col-xs-12">Highest Quality Homes</h2>
   <p class="col-xs-12">Every single home we offer is guaranteed for quality</p>
   <div class="col-xs-12 first-xs"><img src="img/bigicon-quality.png" width="51" height="41" /></div>
  </div>
 </article>
 <article class="col-lg-4 col-xs-12">
  <div class="marginbox row">
   <h2 class="col-xs-12">No obligation</h2>
   <p class="col-xs-12">You can withdraw from the process at any time without penalty</p>
   <div class="col-xs-12 first-xs"><img src="img/bigicon-noobligation.png" width="45" height="41" /></div>
  </div>
 </article>
</section>

Listing 9-5.Flexbox Grid Classes Applied to the HTML Markup, Assigning Layout Attributes to the Elements on the Page

改变 HTML 也意味着原来的 CSS 不再相关。您可以删除所有的 Flexbox 代码,如清单 9-6 所示,留下清单 9-5 中分配的类。

/* The jumbotron section */
#jumbotron {
 background: #38CEB1;
 max-width:    960px;
 min-height:    380px;
 justify-content: center;
 padding-left: 1px;
}
#jumbotron article {
 /* Vertical align */
 justify-content: center;
 text-align: center;
}
.marginbox {
 /* Vertical align */
 justify-content: center;
 text-align: center;
 min-height: 190px;
 background: #EAEAEA;
 margin: 0 1px 1px 0;
}

#jumbotron article .marginbox * {
 align-self: center;
}

#jumbotron article .marginbox:hover {
 background: #efefef;
}

Listing 9-6.Removing the Flexbox Code from the CSS Used in Chapter 5, and Thus Simplifying the Code

在 Safari 中渲染的结果如图 9-10 所示。请注意,这种替代方法要求您在每篇文章的内容周围添加一个额外的<div>元素。这是考虑到文章之间的边距,否则将导致每行仅呈现两篇文章。我还将这个额外的<div>设置为嵌套的 Flexbox 网格行,确保三个元素按照设计要求伸缩。渲染的每个其他方面都是相同的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-10。

The output from Listing 9-6 is identical to the original version created in Chapter 5

如果您想知道当浏览器窗口比 960px 窄时会发生什么,Flexbox 的优势在这里仍然适用。当窗口变得更窄时,内容会重新分页。这得益于为每个元素分配多个类的能力。在这种情况下,我分配了一个额外的小屏幕,以 12 列的宽度显示每个<article>(填充整个行),这意味着每行只呈现一个<article>

福利区

最初使用 Flexbox 呈现的页面的剩余部分是底部的福利部分。你可能还记得,这是三个部件中最复杂的一个。

福利部分更复杂,因为左边的列是右边部分的两倍高。为了处理这个问题,HTML 嵌套了元素。您可以在清单 9-7 中看到实现 Flexbox 网格库时所需的代码。同样,除了库处理的布局挂钩之外,还需要一些额外的 CSS 代码,如清单 9-8 所示。产生的代码量与第五章中创建的原始版本大体相似,但是布局控制已经被移植到 HTML 元素上的类的使用上,而不是纯粹在 CSS 中。这意味着通过引入额外的元素来改变布局可以直接从 HTML 中控制。

<!—The badge benefits section -->
<section id="benefits" class="row">
 <article class="col-lg-4">
  <h1>Looking for a beautiful new home that won't break the bank?</h1>
  <p>Nulla vitae elit libero, a pharetra augue. Nulla vitae elit libero, a pharetra augue. Cras mattis consectetur purus sit amet fermentum.</p>
  <p>Curabitur blandit tempus porttitor. Aenean eu leo quam.
 </article>
 <div class="col-lg-8 row">
  <article class="badge col-lg-6 row">
   <div class="col-lg-9 row">
    <h3 class="col-lg-12">Quality without compromise</h3>
    <p class="col-lg-12">We have homes that suit every budget without compromising on quality</p>
   </div>
   <div class="col-lg-3 first-xs"><img src="img/badge-quality.png" width="38" height="38" /></div>
  </article>
  <article class="badge col-lg-6 row">
   <div class="col-lg-9 row">
    <h3 class="col-lg-12">Trade-up facilities</h3>
    <p class="col-lg-12">If you have a home to sell, we can help market it, and arrange bridging finance</p>
   </div>
   <div class="col-lg-3 first-xs"><img src="img/badge-tradeup.png" width="38" height="38" /></div>
  </article>
  <article class="badge col-lg-6 row">
   <div class="col-lg-9 row">
    <h3 class="col-lg-12">Wonderful locations</h3>
    <p class="col-lg-12">Don't settle for a nice home in a bad location. All our locations are carefully chosen</p>
   </div>
   <div class="col-lg-3 first-xs"><img src="img/badge-locations.png" width="38" height="38" /></div>
  </article>
  <article class="badge col-lg-6 row">
   <div class="col-lg-9 row">
    <h3 class="col-lg-12">Value-added service</h3>
    <p class="col-lg-12">We offer a range of packages that can add value to your home-buying experience, </p>
   </div>
   <div class="col-lg-3 first-xs"><img src="img/badge-valueadd.png" width="38" height="38" /></div>
  </article>
 </div>
</section>

Listing 9-7.Required HTML Alterations 

/* The badge benefits section */
#benefits {
 width:    960px;
 max-width:  960px;
 margin-top: 50px;
 height: 260px;
}
#benefits article.badge img {
 margin:  0.5em 0;
 margin-right: 10px;
}
#benefits article h1 {
 font-size:  2em;
 padding-right: 1em;
 font-weight:  normal;
 margin-bottom:  0.5em;
}
#benefits article h3 {
 font-size:  1.6em;
 font-weight:  normal;
 margin:  0;
 padding-left: 0;
 text-align:   left;
}
#benefits article p {
 text-align:   left;
 padding:  0;
 font-size:  1.2em;
 margin-bottom:  1em;
}

Listing 9-8.CSS to Size Elements on the Page

该实现的输出如图 9-11 所示。请注意,结果再次与第五章的原始版本几乎相同。这是意料之中的,因为从根本上说,这两种实现的代码是相同的;区别在于如何将属性分配给标记。您喜欢哪种方法由您自己决定,但是使用预构建的库来按照通用的设计模式创建布局,而不需要每次都创建自己的解决方案是非常有用的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-11。

The output in Safari Note

再次重申,需要一些额外的非 Flexbox CSS 代码来定义本例中显示的颜色、边框和印刷样式。我特意修剪了代码片段,只显示相关的 CSS 代码用于布局。

摘要

本章介绍了使用 CSS 库和框架加速页面开发的方法。虽然每次你开始一个页面布局的时候都很想重新发明轮子,但是基本上相同的核心元素支撑着你将要设计的几乎每一个页面。通过认识到这一事实,并使用库来加速布局,您可以专注于获得正确的设计细节。

当然,有时一个库或框架不适合你的项目,所以不要害怕承认你需要不时推出自己的解决方案。最好在开发过程的早期就认识到这一点,而不是在你投入大量时间将一个设计硬塞进一个框架中之后才恍然大悟。出于这个原因,预先花一点时间调查所有选项并选择最适合您特定项目的选项是值得的——即使这导致您不使用库!

十、CSS 布局的未来

恭喜你!关于作为 CSS3 的一部分提供的当前布局选项,您已经到达了这本书的末尾。但是不要以为这就是故事的结局!

在学习本章的过程中,您已经深入研究了 CSS Flexbox、CSS 多列布局、CSS 区域布局和 CSS 网格布局,您甚至快速回顾了过去提供的替代方案。我希望您也已经获得了一些想法,如何填充缺失的功能,并使用渐进增强的原则为越来越多使用最新浏览器的用户提供新的和改进的布局,同时不排除那些停留在旧浏览器上的用户。

这一切都还在开发中

正如你从本书中讨论的一些模块的短暂性所看到的,CSS3 正在积极开发中。不仅仅是我提到的模块还在开发中——更多的好东西正在开发中,可能会给你日常使用的布局带来全新的范例。

在写作和研究这本书的过程中,有很多关于 Adobe、微软、苹果和 Mozilla 等公司令人兴奋的新发展的传闻。2000 年代 CSS 发展停滞的时代已经结束;随着越来越多的消费者接受新技术并对他们的在线体验提出更多要求,负责提供支持这些体验的框架的公司正在倾听并做出反应!

Adobe 就是一个例子。以桌面出版和创意工具而闻名的 Adobe,决心拥抱数字化的未来——还有什么比开放网络更好的平台呢?除了共同发起许多你已经看到的模块,这个软件巨人的开发室里还在讨论许多其他的模块。

即将推出的模块和想法

我希望你已经意识到这样一个事实,即我们正处于 CSS 发展的一个非常激动人心的阶段。这种语言发展迅速,人们可以毫无畏惧地随意表达观点。这意味着有很多参与,设计师和技术人员正在接受进一步开发的想法。让我们快速看一下可能会成功的两个未来模块。

CSS 排除项

CSS 排除已经超越了闭门讨论的范畴,现在正在通过 W3C 进行开发。它目前处于工作草案形式,由 Adobe 和微软共同赞助;它基于 CSS2.1 中引入的浮动元素的思想。

在某些方面类似于 CSS 区域布局,CSS 排除描述了内容围绕元素流动的方式,有效地为设计者的军火库增加了另一个布局格式化工具(见图 10-1 )。值得注意的是,该规范仍处于最早期阶段,因此在不久的将来您将无法可靠地使用它,但您可以在 www.w3.org/TR/css3-exclusions/ 找到更多信息,那里有当前的规范。在撰写本文时,还没有太多的实现可用,但这可能是一个小而重要的改进,可以让您以更杂志式的方式控制内容。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 10-1。

The effect of CSS Exclusions on content, determining how wrapping should occur

CSS 形状

虽然不仅仅是关于布局,CSS Shapes 是另一个即将到来的规范的例子;您可以在 www.w3.org/TR/css-shapes/ 了解更多信息。同样,它建立在网页上实现更像杂志的布局的想法上;在这种情况下,它为内容确定非盒形的盒子。这是一件相当大的事情,因为到目前为止,你不得不使用烟雾和镜子来给人一种处理东西而不是盒子形状的内容区域的印象。

同样,这个模块是由 Adobe 和微软共同赞助的,并且仍在积极开发中。请关注网站,获取关于何时可以真正使用它的最新信息(没有当前基于脚本的填充工具!).图 10-2 让你知道这对于格式化网络上的图片(或其他内容)有多么重要。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 10-2。

A CSS shape acting based on the alpha channel of an image, wrapping content automatically around the image subject

还有更多…

正在探索的想法不仅限于这两个模块。查看 CSS 工作组网站了解更多信息,包括根据内容级别确定样式的演示级别模块(对于 PowerPoint 样式的演示非常有用)以及对网页上处理分页媒体的方式的升级。这里有很多内容超出了我的篇幅,所以很值得浏览一下,看看这本书的下一版会有什么内容!

Caution

事情会随着时间而改变!不要忘记定期查看权威的 CSS3——W3C——对本书中概述的规范的修订和增强。在编写这本书的这段时间里,已经有了许多发展,毫无疑问,在整套模块处于候选发布阶段之前,还会有更多的发展。但是,这也是在网络上工作的乐趣之一,不是吗?

摘要

这一章已经看了我们已经走了多远,以及 CSS3 布局的当前状态。我还偷偷瞥了一眼未来,以及未来几年可能会开发出哪些令人兴奋的新模块。这是一个参与网页设计的绝佳时机;随着推动网络发展的语言和技术的进步,以及允许用户浏览和享受网络的浏览器的进步,我们作为网页设计师的未来只会更加光明。前进,展开!

转载请注明出处或者链接地址:https://www.qianduange.cn//article/18304.html
标签
评论
发布的文章

HTML5 CSS3面试题整理

2024-05-05 22:05:21

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!