在本文中,我们将通过创建响应式多列网站布局来实现CSS Grid。
如今,CSS Grid是Web开发中一种新的热门趋势。忘记表格布局和浮动:设计网站的新方法已经在这里!该技术引入了二维网格,通过少量CSS规则定义了多个布局区域。
网格可以使第三方框架如960gs或Bootstrap网格冗余,因为您可以轻松地自己完成所有工作!尽管Internet Explorer实现了旧版本的规范,但所有主流浏览器都支持此功能。
我们要建立什么
因此,我们被要求创建一个典型的网站布局,其中包含标题,主要内容区域,右侧边栏,赞助商列表和页脚:
另一个开发人员已经尝试解决这个任务,并提出了一个涉及浮动的解决方案,以及一些clearfix hacks。我们将这个现有布局称为“初始”:display: table
直到最近,浮动被认为是创建这种布局的最佳选择。在此之前,我们必须使用HTML表,但它们有许多缺点。具体而言,这样的表的布局是非常刚性的,需要大量的标签(table
,tr
,td
,th
等等),和语义这些标记被用来呈现表数据,而不是设计布局。
但CSS继续发展,现在我们有了CSS Grid。从概念上讲,它类似于旧的表格布局,但可以使用具有更灵活布局的语义HTML元素。
规划网格
首先要做的是:我们需要为文档定义一个基本的HTML结构。在此之前,让我们简要地谈谈初始示例的工作原理。它有以下主要块:
.container
是全局包装器,左边和右边的边距很小。.main-header
是包含.logo
(占据20%的空间,向左浮动)和.main-menu
(占据空间的79%,向右浮动)的标题。标题也分配了一个hacky修复程序来清除浮动。.content-area-wrapper
包裹主要部分.content-area
(占空间的66.6%减去1rem
保留边缘,向左浮动)和.sidebar
(占据空间的33.3%,向右浮动)。包装器本身也分配了一个clearfix。.sponsors-wrapper
包含赞助商的徽标。在内部,有一个.sponsors
与部分display
属性设置为table
。反过来,每个赞助商都显示为表格单元格。.footer
是我们的页脚,跨越100%的空间。
我们的新布局与初始布局非常相似,但有一个例外:我们不会添加.main-header
和.content-area-wrapper
包装器,因为不再需要clearfixes。这是HTML的新版本:
<div class="container">
<header class="logo">
<h1><a href="#">DemoSite</a></h1>
</header>
<nav class="main-menu">
<ul>
<li class="main-menu__item"><a href="#">Our clients</a></li>
<li class="main-menu__item"><a href="#">Products</a></li>
<li class="main-menu__item"><a href="#">Contact</a></li>
</ul>
</nav>
<main class="content-area">
<h2>Welcome!</h2>
<p>
Content
</p>
</main>
<aside class="sidebar">
<h3>Additional stuff</h3>
<ul>
<li>Items</li>
<li>Are</li>
<li>Listed</li>
<li>Here</li>
<li>Wow!</li>
</ul>
</aside>
<section class="sponsors-wrapper">
<h2>Our sponsors</h2>
<section class="sponsors">
<figure class="sponsor">
<img src="https://via.placeholder.com/150x150">
</figure>
<figure class="sponsor">
<img src="https://via.placeholder.com/200x150">
</figure>
<figure class="sponsor">
<img src="https://via.placeholder.com/100x200">
</figure>
<figure class="sponsor">
<img src="https://via.placeholder.com/100x100">
</figure>
<figure class="sponsor">
<img src="https://via.placeholder.com/200x200">
</figure>
</section>
</section>
<footer class="footer">
<p>
© 2018 DemoSite. White&Sons LLC. All rights (perhaps) reserved.
</p>
</footer>
</div>
请注意,您可以将其body
用作全局.container
; 在这种情况下,这只是一个偏好问题。总而言之,我们有六个主要领域:
- 商标
- 菜单
- 主要内容
- 侧边栏
- 赞助商
- 页脚
通常建议您实施移动优先方法。也就是说,您从移动布局开始,然后为更大的屏幕添加样式。在这种情况下,这不是必需的,因为我们正在调整已经回退到小屏幕设备上的线性化视图的初始布局。因此,让我们首先关注网格的实现,然后讨论响应性和回退规则。所以,返回我们的方案,看看如何安排网格列:
所以,我建议有三列(以红色突出显示)和四行(以蓝色突出显示)。某些区域(如徽标)将仅占用一列,而其他区域(如主要内容)将跨越多列。稍后我们可以轻松修改布局,移动区域或添加新区域。
遵循该计划,为每个区域指定一个唯一的名称。这些将在下面定义的布局中使用:
.logo {
grid-area: logo;
}
.main-menu {
grid-area: menu;
}
.content-area {
grid-area: content;
}
.sidebar {
grid-area: sidebar;
}
.sponsors-wrapper {
grid-area: sponsors;
}
.footer {
grid-area: footer;
}
现在将display
属性设置为grid
,定义三列并在主容器的左侧和右侧添加小边距:
.container {
display: grid;
margin: 0 2rem;
grid-template-columns: 2fr 6fr 4fr;
}
display: grid
定义网格容器并为其子项设置特殊格式上下文。fr
是一个特殊的单位,意思是“网格容器的自由空间的一小部分”。给了我们,和。这意味着中间列占据了50%的可用空间。2 + 6 + 4
12
6 / 12 = 0.5
我还想在行和列之间添加一些间距:
.container {
// ...
grid-gap: 2rem 1rem;
}
完成此操作后,我们可以处理个别区域。但在结束本节之前,让我们快速添加一些常见的样式:
* {
box-sizing: border-box;
}
html {
font-size: 16px;
font-family: Georgia, serif;
}
body {
background-color: #fbfbfb;
}
h1, h2, h3 {
margin-top: 0;
}
header h1 {
margin: 0;
}
main p {
margin-bottom: 0;
}
好!现在我们可以进入第一个目标,它将成为标题。
设计标题
我们的标题占据了应该具有特定高度的第一行3rem
。在初始布局中,通过height
为头包装器分配属性来解决此问题:
.main-header {
height: 3rem;
}
另请注意,徽标和菜单垂直对齐中间,使用line-height
技巧:
.logo {
// ...
height: 100%;
line-height: 3rem;
}
然而,使用CSS Grid,事情会变得更简单:我们不需要任何CSS黑客攻击。
首先定义第一行:
.container {
// ...
grid-template-rows: 3rem;
}
我们的徽标应该只占一列,而菜单应该跨越两列。我们可以在grid-template-areas
属性的帮助下表达我们的意图,该属性引用grid-area
上面指定的名称:
.container {
// ...
grid-template-areas:
"logo menu menu";
}
这里发生了什么?好吧,logo
只说一次,我们确保它只占一个 – 最左边的列。menu menu
意味着菜单占据两列:中间和最右边的列。看看这条规则有多简单!
现在在Y轴上对齐徽标:
.logo {
grid-area: logo;
align-self: center;
}
菜单应垂直居中并向右拉:
.main-menu {
grid-area: menu;
align-self: center;
justify-self: end;
}
我们的菜单是使用ul
和li
标签构建的,所以让我们通过删除标记,使边距/填充无效以及将菜单设置为flex容器来设置它们的样式:
.main-menu ul {
margin: 0;
padding: 0;
display: flex;
}
.main-menu__item {
list-style-type: none;
padding: 0;
font-size: 1.1rem;
margin-right: 0.5rem;
}
.main-menu .main-menu__item:last-of-type {
margin-right: 0;
}
这就是它。为了观察结果,我将使用Firefox并启用一个方便的CSS Grid Highlighter工具。(有其他浏览器可用的类似工具:例如,Gridman for Chrome。)要访问此工具,请按,然后选择应具有标签的元素:F12
.container
grid
之后,进入CSS规则选项卡,找到该属性。通过按下值旁边的小图标,您可以启用或禁用荧光笔:display: grid
grid
结果如下:
荧光笔显示所有行和列,以及它们与区域名称之间的边距。您可以自定义“布局”部分中的输出,该部分还列出了页面上的所有网格:
所以,我们已经处理了标题,所以让我们进入主要内容区域和侧边栏。
主要内容和补充工具栏
我们的主要内容区域应该跨越两列,而侧边栏应该只占一列。至于行,我想要自动设置它的高度。我们可以相应地更.container
新网格:
.container {
// ...
grid-template-rows: 3rem auto;
grid-template-areas:
"logo menu menu"
"content content sidebar";
}
我想为侧边栏添加一些填充,以提供更多的可视空间:
.sidebar {
grid-area: sidebar;
padding: 1rem;
}
这是结果,如Firefox的网格工具中所示:
赞助商
赞助商部分应包含五个宽度和高度相等的项目。反过来,每个项目将有一个图像。
在初始布局中,此块采用了样式,但我们不会依赖它。实际上,赞助商部分也可能是应用CSS网格的一个很好的候选者!display: table
首先,调整grid-template-areas
包含sponsors
区域:
.container {
// ...
grid-template-areas:
"logo menu menu"
"content content sidebar"
"sponsors sponsors sponsors"
}
现在将该.sponsors
部分转换为网格:
.sponsors {
display: grid;
}
只要我们需要五个宽度相等的项目,repeat
就可以使用一个函数来定义列:
.sponsors {
display: grid;
grid-template-columns: repeat(5, 1fr);
}
至于行,应自动设置其高度。列之间的差距应该等于1rem
:
.sponsors {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-template-rows: auto;
grid-column-gap: 1rem;
}
每个项目的样式:
.sponsor {
margin-left: 0;
margin-right: 0;
background-color: #fff;
border-radius: 0.625rem;
}
这是中间结果:
此示例说明您可以毫无问题地嵌套网格。另一个解决方案可能是使用Flexbox,但在这种情况下,如果没有足够的宽度,赞助商可能会换行。
现在我想垂直和水平居中图像。我们可能会尝试执行以下操作:
.sponsor {
place-self: center;
}
place-self
对齐X轴和Y轴上的元素。这是一个速记属性align-self
和justify-self
。
图像确实会对齐,但不幸的是白色背景消失了。这是因为.sponsor
现在每个都有宽度和高度等于图像的尺寸:
这意味着我们需要一种不同的方法,其中一种可能的解决方案是采用Flexbox:
.sponsor {
// ...
display: inline-flex;
align-items: center;
justify-content: center;
}
现在一切都正常显示,现在我们知道Grid与Flexbox很好地配合:
页脚
我们的最后一部分是页脚,它实际上是最简单的部分。我们所要做的就是将其扩展到所有三列:
.container {
// ...
grid-template-areas:
"logo menu menu"
"content content sidebar"
"sponsors sponsors sponsors"
"footer footer footer";
}
基本上,布局完成了!但是,我们还没有完成:该网站也必须做出回应。所以,让我们在下一节中处理这个任务。
使布局响应
有了CSS Grid,实际上很容易引入响应,因为我们可以快速重新定位区域。
大屏幕
让我们从大屏幕开始(在本文中,我将坚持使用Bootstrap 4中定义的相同断点)。我想减少主要容器的水平边距以及各个赞助商之间的差距:
@media all and (max-width: 992px) {
.container {
margin: 0 1rem;
}
.sponsors {
grid-column-gap: 0.5rem;
}
}
中型屏幕
在中型屏幕上,我希望主要内容区域和侧边栏占据所有三列:
@media all and (max-width: 768px) {
.container {
grid-template-areas:
"logo menu menu"
"content content content"
"sidebar sidebar sidebar"
"sponsors sponsors sponsors"
"footer footer footer";
}
}
让我们减少字体大小并叠加赞助商,使它们在另一个下面显示。列之间的间隙应为零(因为实际上只有一列)。相反,我会在行之间设置间隙:
@media all and (max-width: 768px) {
// ...
html {
font-size: 14px;
}
.sponsors {
grid-template-columns: 1fr;
grid-column-gap: 0;
grid-row-gap: 1rem;
}
}
这就是现在布局在中画面上的样子:
小屏幕
在小屏幕上,我们将在一个单独的行上显示每个区域,这意味着现在只有一列:
@media all and (max-width: 540px) {
.container {
grid-template-columns: 1fr;
grid-template-rows: auto;
grid-template-areas:
"logo"
"menu"
"content"
"sidebar"
"sponsors"
"footer";
}
}
在这种情况下,菜单不应该向右拉,我们也不需要列之间的间隙:
@media all and (max-width: 540px) {
.container {
// ...
grid-gap: 2rem 0;
}
.main-menu {
justify-self: start;
}
}
工作完成了:
请注意,您甚至可以轻松地为各种屏幕重新排列网格项。假设我们想将菜单放在小屏幕的底部(这样访问者在完成阅读页面上的资料后就不必向上滚动)。要做到这一点,只需调整grid-template-areas
:
@media all and (max-width: 540px) {
.container {
// ...
grid-template-areas:
"logo"
"content"
"sidebar"
"sponsors"
"footer"
"menu";
}
}
没有媒体查询
值得一提的是,我们可以让赞助商在没有任何媒体查询的情况下阻止响应。在auto-fit
财产和minmax
功能的帮助下,这是可能的。要查看它们的运行情况,请调整以下样式.sponsors
:
.sponsors {
// ...
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
repeat
正如您所知,该函数会根据需要多次重复列。
auto-fill
表示“用尽可能多的列填充行”。如果列没有足够的空间,它将被放置到下一行。
minmax
允许我们指定列宽度的最小值和最大值。在这种情况下,每列应跨越1个可用空间,但不得少于200个像素。
所有这些意味着在较小的屏幕上,列可以缩小到最多200px
每个。如果仍然没有足够的空间,则会将一列或多列移动到单独的行。以下是应用上述CSS规则的结果:
回退
遗憾的是,CSS Grid尚未得到所有浏览器的完全支持,您可能猜测哪一个仍在实现规范的旧版本。是的,它是Internet Explorer 10和11.如果您在这些浏览器中打开演示,您将看到网格根本不起作用,并且区域只是堆叠:
当然,这不是世界末日,因为该网站仍然可用,但让我们至少添加一些后备规则。好消息是,如果元素浮动并且还分配了网格,则网格优先。此外,display
,vertical-align
,和其他一些特性也对电网的项目没有任何影响,所以让我们利用这一事实。
堆叠菜单看起来不错,但侧边栏应该放在主要内容旁边,而不是放在它下面。我们可以通过使用:display: inline-block
.content-area {
display: inline-block;
vertical-align: top;
}
.sidebar {
display: inline-block;
vertical-align: top;
}
在所有支持网格的浏览器中,这些属性都没有效果,但在IE中它们将按预期应用。我们需要调整的另一个属性是width
:
.content-area {
width: 69%;
display: inline-block;
vertical-align: top;
}
.sidebar {
width: 30%;
display: inline-block;
vertical-align: top;
}
但是添加了这些样式后,我们的网格布局现在看起来会更糟糕,因为网格项不会忽略该width
属性。这可以在CSS查询的帮助下修复。IE不了解这些查询,但它不需要:我们将使用它来修复网格!@supports
@supports (display: grid) {
.content-area, .sidebar {
width: auto;
}
}
现在让我们来处理赞助商项目并为每个区块添加一些上边距:
.sponsor {
vertical-align: middle;
}
.main-menu, .content-area, .sidebar, .sponsors-wrapper, .footer {
margin-top: 2rem;
}
支持网格时,我们不需要任何上边距,因此在@supports
查询中使其无效:
@supports (display: grid) {
// ...
.main-menu, .content-area, .sidebar, .sponsors-wrapper, .footer, .sponsor {
margin-top: 0;
}
}
最后,让我们为IE添加一些响应。我们只需在较小的屏幕上将主要内容,侧边栏和每个赞助商扩展到全宽:
@media all and (max-width: 760px) {
.content-area, .sidebar {
display: block;
width: 100%;
}
.sponsor {
width: 100%;
margin-top: 1rem;
}
}
不要忘记为支持网格的浏览器修复赞助商的宽度:
@supports (display: grid) {
// ..
.sponsor {
width: auto;
}
}
以下是现在Internet Explorer中布局的外观:
您可以在CodePen上查看最终结果:
结论
在本文中,我们已经看到CSS Grid正在运行并利用它来重新设计现有的基于浮动的布局。比较这两个解决方案,我们可以看到“网格”解决方案的HTML和CSS代码更小(当然不包括回退),更简单,更具表现力。在酒店的帮助下grid-template-areas
,很容易理解各个区域的布局,我们可以快速重新定位或调整尺寸。最重要的是,我们不需要依赖像clearfix这样的各种hacky技巧。
所以,正如你所看到的,CSS Grid是浮动的一个很好的替代品,并且它非常适合生产。您可能需要为Internet Explorer(实现规范的旧版本)提供一些回退规则,但正如您所见,它们并不是非常复杂,并且通常该站点仍然可用,即使没有任何向后兼容性所有。
您是否已尝试使用CSS Grid创建网站?你的印象是什么?在评论区分享你的观点!
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/261318.html