在线文档教程
CSS
网格布局 | Grid Layout

网格布局和渐进增强 | CSS Grid Layout: CSS Grid and Progressive Enhancement

CSS Grid Layout: CSS Grid and Progressive Enhancement

在2017的春天,我们第一次看到像Grid这样的主要规范几乎同时发布到浏览器中,我们很快就会在火狐、Chrome、Opera和Safari的公共版本中提供CSSGrid布局支持。然而,虽然常绿浏览器意味着我们中的许多人会很快看到大多数用户支持网格布局,但也有一些旧的或不支持的浏览器需要应对。在本指南中,我们将介绍各种支持策略。

支持浏览器

除了InternetExplorer/Edge之外,在Safari、Chrome、Opera和Firefox中,CSS网格布局都没有前缀。对这些指南中详细说明的所有属性和值的支持在浏览器之间是可互操作的。这意味着,如果您在Firefox中编写一些网格布局代码,它在Chrome中的工作方式应该是相同的。这不再是一个实验规范,您在生产中使用它是安全的。

Internet资源管理器与边缘状态

应该记住,CSS网格布局的最初实现发生在InternetExplorer 10中。这个早期规范没有包含最新规范所具有的所有属性和值。IE 10中提供的内容与当前规范也有很大的差异,即使在属性和值看起来相同的情况下也是如此。此早期实现也是在当前版本的Edge中实现的网格布局的版本。

规范的IE/Edge版本以-ms前缀和在IE/Edge中实现的属性如下:

  • grid-template-columns-ms-grid-columns

  • grid-template-rows-ms-grid-rows

  • grid-row-start-ms-grid-row

  • grid-column-start-ms-grid-column

  • align-self-ms-grid-column-align

  • justify-self-ms-grid-row-align

的新规范中不需要IE版本的附加属性。-ms-grid-column-span-ms-grid-row-span此版本不包括自动放置功能或网格模板区域.。可以为IE10实现一些简单的网格布局,直到当前边缘,使用-ms财产。由于这些属性是供应商前缀的,因此不会影响任何支持最新和无前缀规范的浏览器。

自动重固定器网格布局支持

流行工具自动复位器已更新以支持-ms-使用新网格属性时的网格版本。除非你的布局是非常简单的线基础的布局,这很可能会导致你更多的问题,它解决了。我不建议让自动复位器在网格属性上运行,如果对您有意义的话,可以使用网格布局的IE版本编写一个版本。

我的布局使用CSS网格安全吗?

与任何前端技术选择一样,使用css Grid布局的决定将取决于站点访问者通常使用的浏览器。如果他们倾向于使用最新版本的火狐、Chrome、Opera和Safari,那么一旦这些浏览器更新,就应该开始使用css网格。但是,如果您的站点服务于与旧浏览器相关联的市场部门,那么它可能还没有意义。但是,我的建议是,不要根据过去浏览器中推出的新规范来进行假设。CSS网格布局是非常不同的,在它开发的时间上,以及各个浏览器供应商的工作,以确保什么船舶以相同的方式为每个人工作。

实际使用中使用网格

值得注意的是,您不必在全部或无是的。您可以通过使用网格简单地增强设计中的元素,否则就可以使用旧的方法显示元素。由于网格与这些其他方法的交互方式,用网格布局覆盖遗留方法的效果令人惊讶。

浮动布局

我们通常用浮动布局创建多列布局,请执行以下操作。如果您已经浮动了一个项(它也是支持浏览器中的网格项),则浮点数将不再适用于该项。事实是网格项优先。在下面的示例中,我有一个简单的媒体对象。在不支持的浏览器中,我使用float但是,为了使用CSS网格中实现的对齐属性,我也将容器定义为网格容器。

float不再适用,若要将内容与容器的末尾对齐,我可以使用CSSBox对齐属性align-self

* {box-sizing: border-box;} img { max-width: 100%; display: block; } .media { border: 2px solid #f76707; border-radius: 5px; background-color: #fff4e6; max-width: 400px; display: grid; grid-template-columns: 1fr 2fr; grid-template-areas: "img content"; margin-bottom: 1em; } .media::after { content: ""; display: block; clear: both; } .media .image { float: left; width: 150px; margin-right: 20px; } .media .text { padding: 10px; align-self: end; }

<div class="media"> <div class="image"><img src="http://placehold.it/150x150" alt="placeholder"></div> <div class="text">This is a media object example. I am using floats for older browsers and grid for new ones.</div> </div>

下图显示左侧不支持的浏览器中的媒体对象,右侧的支持对象:

使用功能查询

上面的例子非常简单,我们可以不需要编写代码就可以解决这些问题,对于不支持网格的浏览器来说,这将是一个问题,而遗留代码对于我们支持浏览器的网格来说并不是一个问题。然而,事情并不总是那么简单。

在下一个例子中,我有一组浮动卡。我给了卡片width,为了float他们。要在卡片之间创建空白,我使用margin在项目上,然后在容器上出现负值:

.wrapper ul { overflow: hidden; margin: 0 -10px; padding: 0; list-style: none; } .wrapper li { float: left; width: calc(33.333333% - 20px margin: 0 10px 20px 10px; }

<div class="wrapper"> <ul> <li class="card"><h2>One</h2> <p>We can use CSS Grid to overwrite older methods.</p> </li> <li class="card"><h2>Two</h2> <p>We can use CSS Grid to overwrite older methods.</p> </li> <li class="card"><h2>Three</h2> <p>We can use CSS Grid to overwrite older methods.</p> </li> <li class="card"><h2>Four</h2> <p>We can use CSS Grid to overwrite older methods.</p> </li> <li class="card"><h2>Five</h2> <p>We can use CSS Grid to overwrite older methods.</p> </li> <li class="card"><h2>Six</h2> <p>We can use CSS Grid to overwrite older methods.</p> </li> </ul> </div>

该示例演示了浮动布局的典型问题:如果向任何一张卡添加了其他内容,布局就会中断。

作为旧版浏览器的妥协,我已经设置了一个min-height项目,并希望我的内容编辑不会添加太多的内容,使布局混乱!

然后,我使用网格增强布局。我可以把我的<ul>一个有三条列轨的网格容器。但是,我分配给列表项本身的宽度仍然适用,现在它使这些项成为宽度的三分之一:

如果我将宽度重置为auto,这样就可以停止旧浏览器的浮点行为。我需要能够定义旧浏览器的宽度,并删除网格支持浏览器的宽度。感谢CSS功能查询我能做到,就在我的CSS里。

特征查询如果您曾经使用过媒体查询若要创建响应性布局,请执行以下操作。而不是检查视口宽度,或者浏览器或设备的某些特性,我们使用@supports规则。在特性查询中,我们可以编写任何我们需要的CSS来应用现代布局,并删除旧布局所需的任何内容。

@supports (display: grid) { .wrapper { /* do anything for grid supporting browsers here. */ } }

功能查询被多种浏览器支持,并且所有支持更新的网格规范支持的浏览器也都具有查询功能。您可以使用它们来处理我们使用增强的浮动布局时遇到的问题。

我用的是@supports规则以检查是否支持display: grid.然后在<ul>,设置我的宽度min-height在<li>到auto.我还删除了边距和负边距,并将空格替换为grid-gap财产。这意味着我在最后一行框上没有最后的空白。即使其中一张卡片中的内容比其他卡片的内容更多,布局现在仍然有效:

.wrapper ul { overflow: hidden; margin: 0 -10px; padding: 0; list-style: none; } .wrapper li { float: left; width: calc(33.333333% - 20px margin: 0 10px 20px 10px; } @supports (display: grid) { .wrapper ul { display: grid; grid-template-columns: repeat(3, 1fr grid-gap: 20px; margin: 0; } .wrapper li { width: auto; min-height: auto; margin: 0; } }

<div class="wrapper"> <ul> <li class="card"><h2>One</h2> <p>We can use CSS Grid to overwrite older methods.</p> </li> <li class="card"><h2>Two</h2> <p>We can use CSS Grid to overwrite older methods.</p> <p>We can use CSS Grid to overwrite older methods.</p> </li> <li class="card"><h2>Three</h2> <p>We can use CSS Grid to overwrite older methods.</p> </li> <li class="card"><h2>Four</h2> <p>We can use CSS Grid to overwrite older methods.</p> </li> <li class="card"><h2>Five</h2> <p>We can use CSS Grid to overwrite older methods.</p> </li> <li class="card"><h2>Six</h2> <p>We can use CSS Grid to overwrite older methods.</p> </li> </ul> </div>

覆盖其他值display

由于使用浮点数创建项目网格的问题,我们中的许多人会使用与上面显示的浮动方法不同的方法来布局一组卡片。使用display: inline-block是另一种方法。

再次,我可以使用功能查询覆盖一个布局,该布局使用display: inline-blockinline-block成为网格项,因此inline-block不再适用。我用过vertical-align属性中的inline-block显示模式,但此属性不适用于网格项,因此,一旦该项成为网格项,将被忽略:

.wrapper ul { margin: 0 -10px; padding: 0; list-style: none; } .wrapper li { display: inline-block; vertical-align: top; width: calc(33.333333% - 20px margin: 0 10px 20px 10px; } @supports (display: grid) { .wrapper ul { display: grid; grid-template-columns: repeat(3, 1fr grid-gap: 20px; margin: 0; } .wrapper li { width: auto; margin: 0; } }

<div class="wrapper"> <ul> <li class="card"><h2>One</h2> <p>We can use CSS Grid to overwrite older methods.</p></li><li class="card"><h2>Two</h2> <p>We can use CSS Grid to overwrite older methods.</p> <p>We can use CSS Grid to overwrite older methods.</p></li><li class="card"><h2>Three</h2> <p>We can use CSS Grid to overwrite older methods.</p></li><li class="card"><h2>Four</h2> <p>We can use CSS Grid to overwrite older methods.</p></li><li class="card"><h2>Five</h2> <p>We can use CSS Grid to overwrite older methods.</p></li><li class="card"><h2>Six</h2> <p>We can use CSS Grid to overwrite older methods.</p></li> </ul> </div>

再一次,我们需要处理的是项目的宽度,然后是我们想要增强的任何其他属性。在这个例子中,我再次使用了grid-gap,而不是利润率和负边距来装饰。

规范如何定义这些重写?

CSSGrid布局规范详细说明了为什么当某物成为网格项时,我们可以覆盖某些属性的行为。规范的关键部分是:

由于规范中详细介绍了这种行为,所以在支持旧浏览器时可以安全地使用这些重写。我在这里描述的任何东西都不应该被视为“黑客”,我们利用了网格规范详细描述了不同布局方法之间的交互这一事实。

其他显示值

当元素的父元素设置为display: grid它是闭塞中定义的CSS显示规范.如果我们的项目设置为inline-block,这就是为什么display: inline-block不再适用。

如果你用display: table对于遗留布局,设置为display: table-cell生成匿名框。因此,如果您使用display: table-cell而没有将任何父元素设置为display-table,匿名表包装器将围绕任何相邻的单元格创建,就好像您已经将它们包装在div或其他设置为display: table.如果您的项目设置为display: table-cell,然后在特性查询中将父项更改为display: grid,此匿名框的创建将不会发生。这意味着您可以覆盖display: table基于布局,没有额外的匿名框。

浮动元素

我们已经看到,float同时clear对网格项没有任何影响。因此,不需要显式地将项设置为float: none...

垂直对准

对齐性vertical-align对网格项没有任何影响。在布局中使用display: inline-blockdisplay: table,您可以使用垂直对齐属性来执行基本对齐。在您的网格布局中,您将拥有更强大的框对齐属性。

多列布局

还可以使用多列布局作为遗留浏览器计划,作为column-*属性在应用于网格容器时不应用。

进一步阅读

  • 对IE/Edge网格实现与现代实现的区别进行了总结,并对其进行了讨论。自动复位器支持,看一看:我是否应该尝试使用CSS网格布局的IE实现?