使用CSS网格布局实现常见布局 | CSS Grid Layout: Realising common layouts using CSS Grid
CSS网格布局:使用CSS网格实现公共布局
为了整理CSS Grid Layout的这套指南,我将介绍几种不同的布局,这些布局演示了在使用网格布局进行设计时可以使用的一些不同的技术。我们将使用网格模板区域(典型的12列柔性网格系统)以及使用自动布局的产品列表来看一个例子。从这组示例中可以看出,通常有多种方法可以通过网格布局来实现所需的结果。选择最适合您正在解决的问题以及需要实施的设计的方法。
使用1到3流体柱的响应布局grid-template-areas
许多网站都是这种布局的变体,包括内容、侧边栏、页眉和页脚。在响应性设计中,您可能希望将布局显示为单个列,在某个断点添加一个侧栏,然后为更宽的屏幕引入三列布局。
我将使用我们在指南网格模板区域
了解到的命名模板区域
创建此布局。
我的标记是一个容器,里面有一个标题、页脚、主要内容、导航、侧边栏和一个我打算放置广告的块。
<div class="wrapper">
<header class="main-head">The header</header>
<nav class="main-nav">
<ul>
<li><a href="">Nav 1</a></li>
<li><a href="">Nav 2</a></li>
<li><a href="">Nav 3</a></li>
</ul>
</nav>
<article class="content"><h1>Main article area</h1>
<p>In this layout, we display the areas in source order for any screen less that 500 pixels wide. We go to a two column layout, and then to a three column layout by redefining the grid, and the placement of items on the grid.</p></article>
<aside class="side">Sidebar</aside>
<div class="ad">Advertising</div>
<footer class="main-footer">The footer</footer>
</div>
正如我们grid-template-areas
用来创建布局。在任何媒体查询之外,我需要命名这些区域。我们使用该grid-area
属性命名区域。
.main-head {
grid-area: header;
}
.content {
grid-area: content;
}
.main-nav {
grid-area: nav;
}
.side {
grid-area: sidebar;
}
.ad {
grid-area: ad;
}
.main-footer {
grid-area: footer;
}
这将不会创建任何布局,但我们的项目现在有名称,我们可以使用这样做。在任何媒体查询之外,我现在要设置移动宽度的布局。在这里,我把所有的东西都按源文件顺序排列,尽量避免在源和显示之间出现任何脱节,如指南所述。网格布局和可访问性
我没有定义任何列或行轨迹,但是这个布局指定了一个列,并将根据需要为隐式网格中的每个项创建行。
.wrapper {
display: grid;
grid-gap: 20px;
grid-template-areas:
"header"
"nav"
"content"
"sidebar"
"ad"
"footer";
}
在设置移动布局之后,我们将得到这个所有屏幕大小的单列,现在我们可以添加一个媒体查询并重新定义我们的布局,在有足够的屏幕房地产显示两列的情况下。
@media (min-width: 500px) {
.wrapper {
grid-template-columns: 1fr 3fr;
grid-template-areas:
"header header"
"nav nav"
"sidebar content"
"ad footer";
}
nav ul {
display: flex;
justify-content: space-between;
}
}
您可以看到布局正在形成,其值为grid-template-areas
...header
跨两列轨道,以及nav
.在第三行轨道中,我们有sidebar
旁边content
.在第四行轨道上,我选择将ad
内容-所以它出现在边栏下面,然后是footer
旁边的内容。我在导航上使用一个挠曲盒来将它显示在一排分隔开的位置上。
现在我可以添加一个最后的断点,以移动到三列布局。
@media (min-width: 700px) {
.wrapper {
grid-template-columns: 1fr 4fr 1fr;
grid-template-areas:
"header header header"
"nav content sidebar"
"nav content ad"
"footer footer footer"
}
nav ul {
flex-direction: column;
}
}
三列布局有两个1fr
单元侧列和中间列4fr
作为轨道大小。这意味着容器中的可用空间被分割成6,并按照我们的三条轨道的比例分配--每条轨道一条到侧列,4部分分配到中心。
在这个布局中,我将显示nav
在左边的列旁边content
。在右边的列中,我们有sidebar
广告(ad
)的下方。在footer
现在已经扩展到对面的布局的底部。然后,我使用Flexbox将导航显示为列。
这是一个简单的例子,但演示了如何使用网格布局来重新排列不同断点的布局。特别是我要改变那个地方ad
块,在我的不同列设置中适当。我发现这个命名区域方法非常有用,在原型阶段,它很容易玩周围的位置的元素。您可以开始以这种方式使用网格进行原型开发,即使您无法在生产中完全依赖网格,因为浏览器访问您的站点。
灵活的12列布局
如果您一直在使用可能习惯于在12或16列柔性网格上布局网站的众多框架或网格系统之一。我们可以使用CSS Grid Layout创建这种类型的系统。作为一个简单的例子,我创建了一个12列的柔性网格,它有12 1fr
列的曲目,它们都有一个起始行col-start
。这意味着我们将有十二个网格线命名col-start
。
.wrapper {
display: grid;
grid-template-columns: repeat(12, [col-start] 1fr
grid-gap: 20px;
}
为了演示这个网格系统是如何工作的,我在包装器中有四个子元素。
<div class="wrapper">
<div class="item1">Start column line 1, span 3 column tracks.</div>
<div class="item2">Start column line 6, span 4 column tracks. 2 row tracks.</div>
<div class="item3">Start row 2 column line 2, span 2 column tracks.</div>
<div class="item4">Start at column line 3, span to the end of the grid (-1).</div>
</div>
然后,我可以使用命名行和span关键字将这些内容放在网格中。
.item1 {
grid-column: col-start / span 3;
}
.item2 {
grid-column: col-start 6 / span 4 ;
grid-row: 1 / 3;
}
.item3 {
grid-column: col-start 2 / span 2;
grid-row: 2;
}
.item4 {
grid-column: col-start 3 / -1;
grid-row: 3;
}
如命名行指南,我们正在使用命名行放置我们的项目。因为我们有12行,所有的名称都是相同的,所以我们使用名称,然后使用行的索引。如果您喜欢并避免使用命名行,也可以使用行索引本身。
没有设置结束行号,而是选择使用span
关键词。我喜欢这种方法,因为当使用多列布局系统时,我们通常会根据网格的轨迹数来考虑块,并针对不同的断点进行调整。若要查看块如何与轨道对齐,请使用Firefox网格检查器它清楚地说明了我们的物品是如何放置的。
网格布局在您以前使用过的网格系统上的工作方式有一些关键的区别。正如您所看到的,我们不需要添加任何标记来创建行,网格系统需要这样做来阻止元素弹出到上面的行中。使用CSSGrid布局,我们可以将事物放置到行中,如果行是空的,则不会有上升到上面的行的危险。因为这个严苛
列和行的放置,我们也可以很容易地在我们的布局中留出空白。我们也不需要特殊的类来拉动或推动事物,将它们缩进网格中。我们所需要做的就是指定项目的开始和结束行。
使用12列系统构建布局
要查看此布局方法的实际工作方式,我们可以创建与我们创建的布局相同的布局。grid-template-areas
,这一次使用12列网格系统。我开始使用与网格模板区域示例相同的标记。
<div class="wrapper">
<header class="main-head">The header</header>
<nav class="main-nav">
<ul>
<li><a href="">Nav 1</a></li>
<li><a href="">Nav 2</a></li>
<li><a href="">Nav 3</a></li>
</ul>
</nav>
<article class="content"><h1>Main article area</h1>
<p>In this layout, we display the areas in source order for any screen less that 500 pixels wide. We go to a two column layout, and then to a three column layout by redefining the grid, and the placement of items on the grid.</p></article>
<aside class="side">Sidebar</aside>
<div class="ad">Advertising</div>
<footer class="main-footer">The footer</footer>
</div>
然后,我可以设置我们的网格,如上面的例子12列布局。
.wrapper {
display: grid;
grid-template-columns: repeat(12, [col-start] 1fr
grid-gap: 20px;
}
我们将再次使这是一个响应性的布局,但这一次,但使用命名行。每个断点都将使用12列网格,但是,项目跨越的轨道数量将根据屏幕大小而变化。
我们首先开始移动,我们想要的是最窄的屏幕,所有的项目保持源顺序,所有跨越整个网格。
.wrapper > * {
grid-column: col-start / span 12;
}
在下一个断点,我们要移动到两列布局。我们的标题和导航仍然跨越整个网格,因此我们不需要为它们指定任何位置。侧边栏是从第一列行开始的,名为col-start,跨越3行。它位于第3行之后,因为标题和导航位于三行轨道上。
广告面板在侧栏下面,因此从网格行4开始。然后,我们有内容和页脚,从col-start 4开始,跨越9条轨道,将它们带到网格的末尾。
@media (min-width: 500px) {
.side {
grid-column: col-start / span 3;
grid-row: 3;
}
.ad {
grid-column: col-start / span 3;
grid-row: 4;
}
.content, .main-footer {
grid-column: col-start 4 / span 9;
}
nav ul {
display: flex;
justify-content: space-between;
}
}
最后,我们将讨论这个布局的三列版本。标题继续跨越网格,但现在导航向下移动,成为第一个侧栏,内容和旁边的侧边栏。页脚现在也跨越整个布局。
@media (min-width: 700px) {
.main-nav {
grid-column: col-start / span 2;
grid-row: 2 / 4;
}
.content {
grid-column: col-start 3 / span 8;
grid-row: 2 / 4;
}
.side {
grid-column: col-start 11 / span 2;
grid-row: 2;
}
.ad {
grid-column: col-start 11 / span 2;
grid-row: 3;
}
.main-footer {
grid-column: col-start / span 12;
}
nav ul {
flex-direction: column;
}
}
再一次网格检查器帮助我们了解我们的布局是如何形成的。
在创建这个布局时要注意的是,我们不需要显式地将网格上的每个元素定位在每个断点上。我们能够继承为早期断点设置的位置--这是“移动第一”工作的优势。我们还可以利用网格自动布局。通过保持元素的逻辑顺序,自动布局在将项目放置到网格中做了大量的工作。在本指南的最后一个例子中,我们将创建一个完全依赖于自动布局的布局。
自动配售的产品列表
许多布局本质上是“卡片”的集合--产品列表、图像画廊等等。网格可以使创建这些清单变得非常容易,而无需添加响应。媒体查询才能做到这一点。在下一个例子中,我将CSSGrid和Flexbox布局组合在一起,生成一个简单的产品列表布局。
清单的标记是一个无序的项目列表。每个项目包含一个标题、一些不同高度的文本,以及一个调用操作链接。
<ul class="listing">
<li>
<h2>Item One</h2>
<div class="body"><p>The content of this listing item goes here.</p></div>
<div class="cta"><a href="">Call to action!</a></div>
</li>
<li>
<h2>Item Two</h2>
<div class="body"><p>The content of this listing item goes here.</p></div>
<div class="cta"><a href="">Call to action!</a></div>
</li>
<li class="wide">
<h2>Item Three</h2>
<div class="body"><p>The content of this listing item goes here.</p>
<p>This one has more text than the other items.</p>
<p>Quite a lot more</p>
<p>Perhaps we could do something different with it?</p></div>
<div class="cta"><a href="">Call to action!</a></div>
</li>
<li>
<h2>Item Four</h2>
<div class="body"><p>The content of this listing item goes here.</p></div>
<div class="cta"><a href="">Call to action!</a></div>
</li>
<li>
<h2>Item Five</h2>
<div class="body"><p>The content of this listing item goes here.</p></div>
<div class="cta"><a href="">Call to action!</a></div>
</li>
</ul>
我们将创建一个具有灵活数量的灵活列的网格。我希望它们永远不会小于200像素,然后平等地共享任何可用的剩余空间--所以我们总是得到等宽的列轨。我们通过minmax()
函数在重复表示法中进行跟踪调整。
.listing {
list-style: none;
margin: 2em;
display: grid;
grid-gap: 20px;
grid-template-columns: repeat(auto-fill,minmax(200px, 1fr)
}
一旦我添加了这个CSS,项目就开始布局为一个网格。如果我使窗口变小或变宽,那么列轨迹的数目就会发生变化--而不需要我使用媒体查询添加断点并重新定义网格。
然后,我可以用一点柔性盒来整理盒子的内部。我将列表项设置为display: flex
而flex-direction
到column
然后,我可以在.cta
把这个棒推到盒子的底部。
.listing li {
border: 1px solid #ffe066;
border-radius: 5px;
display: flex;
flex-direction: column;
}
.listing .cta {
margin-top: auto;
border-top: 1px solid #ffe066;
padding: 10px;
text-align: center;
}
.listing .body {
padding: 10px;
}
这确实是我使用柔性盒而不是网格的关键原因之一,如果我只是在一个维度中对齐或分发某个东西,那就是一个柔箱用例。
这一切看起来都相当完整,但我们有时有这些卡片,其中包含的内容远远超过其他。如果能让它们跨越两条轨道,那么它们就不会那么高了。我有一节课wide
在我更大的项目上,我添加了一个规则grid-column-end
价值为span 2
现在,当网格遇到这个项目时,它会给它分配两个轨道。在一些断点上,这意味着我们将在网格中得到一个空白--在那里没有空间来布局一个双轨项目。
我可以通过设置grid-auto-flow
: dense
在网格容器上。但是,在执行此操作时要小心,因为它确实会将项目从其逻辑源顺序中删除。只有在项目没有设置顺序的情况下才应该这样做-并且要注意问题的选项卡顺序,而不是重新排序的显示。
.listing {
list-style: none;
margin: 2em;
display: grid;
grid-gap: 20px;
grid-auto-flow: dense;
grid-template-columns: repeat(auto-fill,minmax(200px, 1fr)
}
.listing .wide {
grid-column-end: span 2;
}
这种使用自动放置和某些规则应用于特定项目的技术非常有用,并且可以帮助您处理CMS输出的内容。在这里,您有重复的项,并且可能会在将类呈现到HTML中时将类添加到特定的类中。
进一步探索
学习使用网格布局的最佳方法是继续构建示例,如我们在这里介绍的示例。选择通常使用您选择的框架构建的东西,或者使用浮点数,看看是否可以使用网格构建它。别忘了找到用当前方法构建的例子。这可能意味着从杂志或其他非网络来源获得灵感。网格布局打开了我们以前没有过的可能性,我们不需要绑定到相同的旧布局来使用它。
- 如需灵感,请参阅
布局实验室
珍·西蒙斯,她一直在根据一系列来源创建布局。
- 有关其他常见布局模式,请参阅“按
网格示例”
,其中有许多较小的网格布局示例,以及一些较大的UI模式和整页布局。