实现复杂但灵活且响应迅速的网格布局可能很困难。多年来,各种技术已经发展,但大多数技术,如人造柱,都是黑客而非强大的设计选项。
大多数这些 hack 都是建立在 CSS float属性之上的。当Flexbox 布局模块被引入显示属性选项列表时,一个新的选项世界成为可能。现在,您不仅可以定义容器堆叠项目的方向,还可以在容器中包装、对齐(项目和行)、排序、收缩等。
掌握了所有这些权力后,开发人员开始为各种布局创建自己的规则组合。灵活性占了上风。然而,Flexbox 设计用于处理一维布局:行或列。相比之下,CSS 网格布局允许二维行和列布局。
很难创建一个支持每个用户浏览器的网站。通常使用两个选项——“优雅降级”和“渐进式增强”。
优雅降级可确保网站即使在出现问题时也能继续运行。例如,float: right
如果一个元素对于屏幕来说太大,但它会换行到下一个空白空间,因此该块仍然可用,则可能会失败。
渐进增强采用相反的方法。该页面以最少的功能开始,并在支持时添加功能。上面的示例可以使用 CSS 媒体查询来验证屏幕是允许元素浮动之前的最小宽度。
当涉及到网格布局时,每个浏览器都会确定其组件的外观。在本文中,您将通过一些真实示例了解如何将一些 Web 内容从旧策略演变为新策略。更具体地说,如何将模型从基于浮动的布局逐步增强到 Flexbox,然后分别是 CSS Grid。
看看下面的 HTML 页面:
article content
这是您可以在网页中使用的一个小而常见的网格配置示例:两个 div 共享同一个容器(body)。
以下 CSS 可用于我们将创建的所有示例来设置正文样式:
body {
font-family: Segoe UI;
font-style: normal;
font-weight: 400;
font-size: 1rem;
}
另外,我们每个 div 的 CSS 片段,启用浮动效果:
main {
width: 100%;
}
main, article, aside {
border: 1px solid #fcddd1;
padding: 5px;
float: left;
}
article {
background-color: #fff4dd;
width: 74%;
}
aside {
width: 24%;
}
您可以在此处查看示例:
您可以根据需要浮动任意数量的元素,一个接一个,所有元素都适合整个可用宽度。但是,这种策略有一些缺点:
一种解决方案是display: table
布局:
main {
display: table;
}
main, article, aside {
display: table-cell;
}
但是,display: table
随着布局变得越来越复杂,使用变得不那么方便,并且在响应式布局中使用起来可能会变得混乱。display: table
最适用于页面的小部分,而不是主要的布局部分。
名为Flexbox的灵活盒子模块是一种较新的布局模型,能够以一维方式分配空间并强大地对齐容器(盒子)的项目。虽然它的一维性质并不妨碍您设计多维布局(行和列),但 Flexbox 可能不会导致可靠的行堆叠。
除了浮动方法非常流行并被流行的网格框架广泛采用之外,Flexbox 还提供了一系列优于浮动的优点:
要启动 Flexbox 格式化策略,您需要做的就是使用flex值设置 CSS display属性:
main {
width: 100%;
display: flex;
}
main, article, aside {
border: 1px solid #fcddd1;
padding: 5px;
float: left;
}
article {
background-color: #fff4dd;
width: 74%;
}
aside {
width: 24%;
}
下图显示了结果:
这是一个活生生的例子:
CSS Grid 布局紧跟 Flexbox 布局,最大的区别在于它在二维中工作。也就是说,如果您需要设计一个同时处理行和列的布局,网格布局很可能更适合。它具有与 Flexbox 相同的对齐和空间分布因子,但现在直接作用于容器(盒子)的两个维度。与 float 属性相比,它还有更多的优势:易于元素的配置、对齐、行/列/单元格控制等。
使用 CSS Grid 就像将容器元素的displaygrid
属性更改为. 例如,在容器内部,您还可以使用 div 创建列和行。让我们考虑一个具有四个内部容器 div 的 HTML 页面示例。
关于 CSS 定义,让我们从网格container
div 开始:
div.container {
display: grid;
grid-template-columns: 24% 75%;
grid-template-rows: 200px 300px;
grid-column-gap: 15px;
grid-row-gap: 15px;
}
该属性grid-template-columns
定义了与之前相同的配置:两个网格列分别占据整个容器宽度的 24% 和 75%。做同样的grid-template-rows
事情,分别应用 200px 和 300px 作为第一行和第二行的高度。
使用属性grid-column-gap
和grid-row-gap
在网格元素周围分配空间。
关于将网格对齐属性应用于特定单元格,让我们看一下:
.div1 {
background-color: #fff4dd;
align-self: end;
justify-self: end;
}
.div4 {
align-self: center;
}
对于 class 的 div div1
,您将在网格单元格的末尾对齐和对齐它。属性align-self
和justify-self
对布局中的所有弹性项目都有效,在这种情况下,包括网格单元格。div4
仅设置居中对齐,以便您检查两者之间的差异。
以下是元素现在的定位方式:
您可以在此处查看最终的网格布局示例:
大多数浏览器还提供对 Grid 布局检查的原生支持,这对于了解它如何在内部处理 Grid 机制非常有用。让我们在Firefox 上使用 Grid Inspector尝试我们的 Grid 示例,可通过 Firefox DevTools 获得。要打开它,请右键单击容器元素,然后在 CSS 窗格的规则视图中,找到并单击紧随其后的网格图标display: grid
:
这将切换网格荧光笔。您还可以在 CSS 窗格的布局视图中控制更多显示设置,例如行号或区域名称展示:
在下一个示例中,我们将使用博客页面作为参考,从完全基于浮动的页面升级到 CSS 网格布局,探索如何将旧布局完全转换为包含 Flexbox 和网格。
在接下来的更新中,我们将密切关注不支持 Flexbox 或 CSS Grid 的旧浏览器,以及博客在移动版本上的表现。这是我们博客页面的外观和感觉,完全基于 divs 和 CSS float 属性:
这是一个例子的笔:
请注意,对于已经熟悉语义标签的任何人来说,HTML 结构都很常见:一个 div(容器)包含所有内部元素,这些元素将根据谁浮动谁构成最终布局。
它基本上由一个简单header
的菜单组成,该菜单定义了其项目(链接)将如何显示和对齐:
nav.menu {
width: 98%;
}
ul {
list-style: none;
padding: 0px;
margin: 0px;
}
.left {
float: left;
}
.right {
float: right;
}
a {
padding: 4px 6px;
}
页面内容分为两部分,section
和aside
元素:
main {
float: left;
width: 74%;
}
aside {
float: left;
width: 24%;
margin-left: 15px;
margin-bottom: 15px;
}
aside h2 {
text-align: center;
}
没什么特别的,只是让 div 浮动并确定每个 div 在全宽之上的最大宽度。clear
还要注意,当我们需要在 div 之后禁用浮动效果时,需要清除 ( ) 的东西:
header:after {
content: "";
display: table;
clear: both;
}
CSS 的结尾带来了一条@media
规则,当页面在小屏幕设备中打开时,该规则将侧边栏断开到下一列。HTML 的末尾带有一个简单的页脚和一些简单的文本。
注意:HTML 的开头包含HTML5 Shiv 脚本,以便在旧版 Internet Explorer 中使用 HTML5 分段元素。
如前所述,Flexbox 更适用于水平菜单等一维布局。相同的菜单结构可以增强到这个:
nav.menu {
width: 98%;
}
nav.menu ul {
display: flex;
}
nav.menu ul > li:last-child {
margin-left: auto;
}
使用 Flexbox 属性会自动为较新的浏览器禁用浮动。然而,由于我们为属性保留了旧的 CSS 配置,float
当浏览器不支持 Flexbox 时,浮动仍然会应用。
同时,display: flex
为了使用 Flexbox 与margin-left: auto
最后一个菜单项一起布局菜单,添加了 。这将确保该项目将被推到布局的右侧,将它们分成不同的组。
当涉及到内部元素的放置时,CSS Grid 为我们提供了更大的灵活性。正如 Flexbox 是水平容器(菜单)的完美选择一样,网格对于基本上分为三个部分的二维博客布局来说也是完美的选择:
网格区域功能由两个属性的组合组成:grid-template-areas
和grid-area
。第一个定义如何将整个布局的高度和宽度划分为组,方法是明确地将每个组的名称放在最终布局中:
div.container {
width: 100%;
display: grid;
grid-gap: 20px;
grid-template-areas:
"header header header"
"content content sidebar"
"footer footer footer"
}
在这里,我们将整个容器空间划分为三行三列。与定义一起重复的区域名称表示每个区域将在垂直和水平方向占据多少空间。
然后,我们可以通过为每个网格区域设置相应的grid-area
值来使用第二个属性:
header {
grid-area: header;
}
main {
grid-area: content;
/* other properties */
}
aside {
grid-area: sidebar;
/* other properties */
}
footer {
grid-area: footer;
/* other properties */
}
与 Flexbox 一样,网格项会在支持 CSS Grid 的浏览器中自动禁用浮动声明。其余属性保持不变(当浏览器不支持网格时,浮动仍然适用)。
您可以在此处看到此示例完全运行:
当我们需要定义一个遵循网格定义模式的模板时,grid-template属性也非常有用。
让我们看一下下面的.container
CSS:
div.container {
width: 100%;
display: grid;
grid-gap: 20px;
grid-template-columns: auto auto auto;
}
在这里,我们基本上是说列的大小是由容器的大小和列中项目内容的大小决定的。
然后,我们的每个网格区域都必须适应:
header {
grid-column: 1/4;
}
section {
grid-column: 1/3;
/* other properties */
}
aside {
grid-column: 3/4;
/* other properties */
}
footer {
grid-column: 1/4;
/* other properties */
}
在这里,grid-column: 1/4
指示浏览器在第 1 轨开始列,在第 4 轨结束。轨道是每个网格单元之间的分隔符,因此该元素将占用单元格一到三个:
该示例可以在这里进行测试:
您现在可以在不同的浏览器版本以及您的手机上对其进行测试,以检查页面是如何逐步增强的。
有关 CSS Grid 的更多信息,请参阅 SitePoint 的CSS Grid Layout Introduction,也可以查看 SitePoint 的CSS Flexbox Introduction。
Mozilla 还提供了一篇关于CSS 网格布局和渐进增强的精彩文章,肯定会增加很多。好好学习!