CSS进阶12-网格布局 Grid Layout

(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录。)

1. 导读

网格布局是由CSS3引入的一种新的布局方式,提供了强大的布局能力。我们先来看一下W3C对于它的描述。

This CSS module defines a two-dimensional grid-based layout system, optimized for user interface design. In the grid layout model, the children of a grid container can be positioned into arbitrary slots in a predefined flexible or fixed-size layout grid.

翻译过来就是,这个CSS模块定义了一个二维的基于网格的布局系统,为用户界面设计进行了优化。在网格布局模型中,网格容器的子节点可以定位到预定义的可伸缩的或者固定大小的布局网格中的任意插槽中。

2. 简介

(注:本节内容不是规范性的)。 网格布局是一种新的CSS布局模型,它具有强大的能力来控制箱子及其内容的大小和位置。与面向单轴的Flexible Box Layout不同,Grid Layout针对二维布局进行了优化:在两个维度中都需要对齐内容。

Figure 1示例性的Flex布局示例

Figure2 示例性的网格布局示例

此外,由于能够明确定位网格中的项目,网格布局允许在视觉布局结构中进行戏剧性的转换,而不需要相应的标记更改。通过将媒体查询与控制网格容器及其子节点布局的CSS属性相结合,作者可以使其布局适应设备形状因素,方向和可用空间的变化,同时保持演示文稿内容的理想语义结构。

虽然许多布局可以用Grid或Flexbox来表示,但它们都有其特色。网格强制执行二维对齐,使用自上而下的布局方式,允许项目的显式重叠,并具有更强大的跨越能力。Flexbox专注于轴内的空间分布,使用更简单的自下而上的布局方法,可以使用基于内容大小的换行系统content-size–based line-wrapping system来控制其次轴,并依靠底层标记层次来构建更复杂的布局。预计这两者都将成为CSS作者的宝贵和补充工具。

2.1 背景和动机

随着网站从简单的文档发展到复杂的交互式应用程序,文档布局技术(例如浮动)不一定非常适合应用程序布局。通过组合使用表格,JavaScript或对浮动元素进行仔细测量,作者发现了实现所需布局的解决方法。适应可用空间的布局通常很脆弱,并且在空间受到限制时导致反直觉行为。作为替代方案,许多Web应用程序的作者选择固定布局,无法利用屏幕上可用渲染空间的更改。

网格布局的能力解决了这些问题。它为作者提供了一种机制,使用一组可预测的大小调整行为将可用空间分配给列和行。然后,作者可以将其应用程序的构造块元素精确定位和设置到由这些列和行的交叉点定义的网格区域grid area中。以下示例说明了网格布局的自适应功能,以及它如何更清晰地分离内容和样式。

2.1.1 将布局调整为可用空间

网格布局可用于智能调整网页中的元素的大小。下列例子表示一个游戏,其布局中包含五个主要组件:游戏标题,统计区域,游戏板,评分区域和控制区域。作者的意图是划分游戏空间,使得:

  • 统计区域总是直接出现在游戏标题下。
  • 游戏板显示在统计和标题的右侧。
  • 游戏标题和游戏板的顶部应始终对齐。
  • 当游戏达到最小高度时,游戏板的底部和统计区域的底部对齐。在所有其他情况下,游戏板将会扩展以充分利用所有可用的空间。 *控件集中在游戏板下。
  • 得分区域的顶部与控制区域的顶部对齐。 *得分区域在统计区域下方。
  • 得分区域与统计区域下方的控件对齐。

Figuer 4 根据内容大小和可用空间排列五个网格项目

Figuer 5 由于可用空间增加导致网格增长 以下网格布局示例显示作者如何以声明方式实现所有尺寸,放置和对齐规则。

/* EXAMPLE 1 */
/**
* Define the space for each [grid item](https://www.w3.org/TR/css3-grid-layout/#grid-item) by declaring the grid
* on the [grid container](https://www.w3.org/TR/css3-grid-layout/#grid-container)
*/
#grid {
  /**
 * Two columns:
 *  1. the first sized to content,
 *  2. the second receives the remaining space
 *     (but is never smaller than the minimum size of the board
 *     or the game controls, which occupy this column [Figure 4])
 *
 * Three rows:
 *  3. the first sized to content,
 *  4. the middle row receives the remaining space
 *     (but is never smaller than the minimum height
 *      of the board or stats areas)
 *  5. the last sized to content.
 */
  display: grid;
  grid-template-columns:
    /* 1 */ auto
    /* 2 */ 1fr;
  grid-template-rows:
    /* 3 */ auto
    /* 4 */ 1fr
    /* 5 */ auto;
}

/* Specify the position of each [grid item](https://www.w3.org/TR/css3-grid-layout/#grid-item) using coordinates on
 * the 'grid-row' and 'grid-column' properties of each [grid item](https://www.w3.org/TR/css3-grid-layout/#grid-item).
 */
#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; }

<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>

注意:有多种方式可以指定网格的结构以及网格项目grid items的位置和大小,每个网格项每种场景都进行了优化。

2.1.2 源顺序独立性 Source-Order Independence

继续前面的例子,作者还希望游戏适应不同的设备。此外,当纵向或横向观看时,游戏应该优化组件的放置(Figuer6和7)。通过将网格布局与媒体查询相结合,作者能够使用相同的语义标记,但可以重新排列元素的布局,而不是独立于源顺序,从而在两个方向上实现所需的布局。

FIguer 6 适合“肖像”方向的布局

Figuer 7 适合“风景”定位的布局

以下示例使用网格布局的能力来命名将被网格项grid item占据的空间。这允许作者避免在网格的定义改变时为网格项目重写规则。

/* EXAMPLE 2 */

@media (orientation: portrait) {
  #grid {
    display: grid;

    /* The rows, columns and areas of the grid are defined visually
     * using the grid-template-areas property.  Each string is a row,
     * and each word an area.  The number of words in a string
     * determines the number of columns. Note the number of words
     * in each string must be identical. */
    grid-template-areas: "title stats"
                         "score stats"
                         "board board"
                         "ctrls ctrls";

    /* The way to size columns and rows can be assigned with the
     * grid-template-columns and grid-template-rows properties. */
    grid-template-columns: auto 1fr;
    grid-template-rows: auto auto 1fr auto;
  }
}

@media (orientation: landscape) {
  #grid {
    display: grid;

    /* Again the template property defines areas of the same name,
     * but this time positioned differently to better suit a
     * landscape orientation. */
    grid-template-areas: "title board"
                         "stats board"
                         "score ctrls";

    grid-template-columns: auto 1fr;
    grid-template-rows: auto 1fr auto;
  }
}

/* The grid-area property places a grid item into a named
 * area of the grid. */
#title    { grid-area: title }
#score    { grid-area: score }
#stats    { grid-area: stats }
#board    { grid-area: board }
#controls { grid-area: ctrls }



<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>

注:网格布局的重新排序功能特意仅针对视觉渲染,而不影响基于源顺序的语言顺序和导航。这使得作者可以操作视觉呈现,同时保持源顺讯的完整性并针对非CSS UA和线性模型(如语言和顺序导航)进行优化。 注:网格项目的放置和重新排序不能用于替代正确的源排序,因为这可能会破坏文档的可访问性。

3. 浏览器的兼容性

CSS网格布局从Safari 10.1, Firefox 52, Opera 44, Chrome 57开始受到支持,微软Edge在Edge 15会更新对网格布局的支持。

微软的浏览器(IE10–11和Edge 13-14)有一种比较旧的实现,所以有不少限制,我们会简单介绍新的实现方式和老的实现方式之间的区别,这样你能知道如何规避他们。

对于大多数布局,我们会使用下面的query特性来让老的浏览器对他们理解的特性也能工作:

@supports (display: grid) {
    .grid {
        display: grid;
    }
}

不支持浏览器@supports或网格的浏览器将不会生效。

为了能正确展示文中的示例,你需要使用支持网格布局的浏览器

4. 网格布局概念和术语

在网格布局中,一个网格容器的内容排列是依靠于他里面网格的位置与对齐方式。网格是由水平和垂直网格比交织组成,他将网格容器的空间分为网格区域,网格项目将放置在这些网格区域中。在网格中有两套网格线:一套是沿着水平方向的轴定义列的网格张,另一套是沿着垂直方向的轴定义行。

Figure 8 网格线:三个块轴和四个内嵌轴

4.1 网格线 Grid Lines

网格线是网格的水平和垂直的分界线。一个网格线存于行或列的两侧。他们可以参后数值指数,也可以由设计师指定名称。一个网格项目引用网格线来确定其网格中的位置属性。

下面两个例子创建了三个列网格线和四行网格线。第一个示例演示了设计师如何将一个使用网格行号的位置来确定网格项目的位置,第二个例子显式的设置了网格线。

/*具有三个列网格线和四个行网格线*/   
#grid {
  display: grid;
  grid-definition-columns: 150px 1fr; /*两列*/
  grid-definition-rows: 50px 1fr 50px;/*三行*/
}

#item1 { 
  grid-column: 2;
  grid-start: 1; 
  grid-end: 1; 
}   
/* 使用命名行,实现先前例子相等效果布局 */
#grid {
  display: grid;
  grid-definition-columns: 150px "item1-start" 1fr "item1-end";
  grid-definition-rows: "item1-start" 50px 1fr 50px "item1-end";
}

#item1 {
 grid-column: "item1-start" / "item1-end";
 grid-row: "item1-start" / "item1-end";
}   

4.2 网格轨道和单元格 Grid Tracks and Cells

网格轨道是“grid column”或者“grid row”的另一种术语,换句话说,他就是两条相邻网格线之间的空间。每个网格轨道可以设置一个大小,用来控制宽度或高度或者行可能会增长。 网格单元是网格行和网格列的交集。它是定位网格项时可以引用的网格的最小单元。 在接下来的例中定义了一个三行两列的网格。第一列设置一个固定宽度“150px”,第二列设置是一个弹性尺寸,它是一个未赋值的网格空间,从而根据网格容器的变化而进行宽度的改变。如果网格容器的宽度是“200px”,那么第二列的宽度是“50px”。

#grid {
  display: grid;
  grid-definition-columns: 150px 1fr; /* 两列*/
  grid-definition-rows: 50px 1fr 50px /* 三行  */
}   

4.3 网格区域 Grid Areas

网格区域是一个逻辑空间,主要用来放置一个或多个网格项目。他有四条网格线,网格区域每边一条,四边相交组织的网格轨道可以调整网格区域大小。可以使用“grid-template”属性为网格容器显式的设置网格区域,或者隐式的使用网格线创建网格区域。网格项目可以使用“grid-placement”属性将其分配给一个网格区域。

#grid  {
  display: grid;
  grid-template: ". a"
                 "b a"
                 ". a";
  grid-definition-columns: 150px 1fr;
  grid-definition-rows: 50px 1fr 50px
}

#item1 { grid-area: a }
#item2 { grid-area: b }
#item3 { grid-area: b }

#item2 { align-self: head }
#item3 { justify-self: end; align-self: foot }   

4.4 网格容器 Grid Containers

通过“display”属性给一个元素显式的设置了“grid”或者“inline-grid”属性值,这个元素将自动变成网格容器

一个网格容器将会创建一个新的网格格式化上下文内容(grid formatting context)。除是网格布局代替了块布局之外,网格格式化上下文和块格式化上下文是相同的。浮动对网格容器不会有影响,而且网格容器的margin不会和内容的margin相互层叠。

因为网格容器不是块容器,所以一些属性在网格布局中将会失效:

  • 多栏布局模块中的所有“column-*”属性运用在网格容器上将失效。
  • “float”和“clear”使用在网格项目上将失效
  • “vertical-align”使用在网格项目上将失效
  • “::first-line”和“::first-letter”这样的伪元素不能应用在网格容器上。 注意:如果一个元素指定了“display”值为“inline-grid”,并且此元素具有“float”或绝对定位时,这个元素将的“display”值将会以“grid”显示。

4.5 子网格容器 Subgrids

有时候我们需要给网格项目设置为网格容器。那么我们可以使用“display:grid”,在这种情况之下,他是独立于网格布局的。而在某些情况下,要为内容设置多个网格,让网格项目相互一致,在这种情况之下,我们需要通过“dsplay”属性显式的设置为“subgrid”,让其显示为次网格。

例如,我们一个标签和输入框组成的列表表单:

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

我们希望这个标签和输入文本框对齐,我们想给每个列表标签设置一个边框样式,这次就可以通过次网格布局实现。 ul { display: grid; grid-auto-flow: rows; grid-definition-columns: auto 1fr; } li { display: subgrid; margin: 0.5em; border: solid; padding: 0.5em; } label { grid-column: 1; } input { grid-column: 2; }

4.6 网格项目 Grid Items

在一个网格容器中包含了0个多个网格项目。网格容器的子元素称为网格项目以及运行在网格容器的文本将自动变成一个匿名的网格项目,然后如果只是一个空格,这个匿名项目就相当于“display:none”一相被隐藏在网格容器之中。

一个网格项目创建一个新的格式化上下文内容。这种格式化上下文内容类型取决于它的“display”值。

4.7 网格项目顺序order

网格项目顺序可以像flexobx模块一样,通过order属性来对网格项目进行顺序的重排。

5. 基本示例

以下示例显示了一个三列轨道网格,其中创建的行最小为100像素,最大为自动。条目使用线性定位放置在网格上。

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 10px;
  grid-auto-rows: minmax(100px, auto);
}
.one {
  grid-column: 1 / 3;
  grid-row: 1;
}
.two { 
  grid-column: 2 / 4;
  grid-row: 1 / 3;
}
.three {
  grid-row: 2 / 5;
  grid-column: 1;
}
.four {
  grid-column: 3;
  grid-row: 3;
}
.five {
  grid-column: 2;
  grid-row: 4;
}
.six {
  grid-column: 3;
  grid-row: 4;
}



<div class="wrapper">
  <div class="one">One</div>
  <div class="two">Two</div>
  <div class="three">Three</div>
  <div class="four">Four</div>
  <div class="five">Five</div>
  <div class="six">Six</div>
</div>

参考

https://www.w3.org/TR/css3-grid-layout/#grid-formatting-context 前端精选文摘:css之GFC 神奇背后的原理(整理) Getting to know CSS Grid Layout 翻译 | CSS网格(CSS Grid)布局入门 MDN-网格布局 MDN-CSS Grid Layout

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏编程

一行JS代码实现翻翻卡效果

本文章是由源码时代H5前端讲师分享:一行JS代码实现翻翻卡效果,希望对大家有一定帮助。 实现步骤 准备2张图片,一个在上一个在下 上方的图片不动,下方的图片先翻...

43780
来自专栏数据小魔方

帕累托图(Pareto Chart)

今天要跟大家分享的图表是帕累托图! ▽▼▽ 这种图表类似于之前曾分享过的直方图,但是又比直方图所能展现的数据信息更多,由一个降序排列的柱形图和一个升序排列的带数...

42850
来自专栏数据小魔方

sparklines迷你图系列7——Comparision(+/-Variance)。

今天跟大家分享sparklines迷你图系列的第七篇——Comparision(+/-Variance)。 该图表用于表现指标增长率波动情况,波动范围-100%...

27850
来自专栏钱塘大数据

看完这些美如画的数据信息图,你还会用饼图做图表?

14530
来自专栏MixLab科技+设计实验室

人工智能设计师之智能排版的另一种实现方式

Flipboard的自动排版系统Duplo 最近在整理算法驱动设计的案例,翻到Flipboard的自动排版系统,再次研究了下,把相关的技术思路整理了下: Fli...

42370
来自专栏深度学习之tensorflow实战篇

Python生成词云图,TIIDF方法文本挖掘: 词频统计,词云图

python中使用wordcloud包生成的词云图。 下面来介绍一下wordcloud包的基本用法。 class wordcloud.WordCloud(fon...

64260
来自专栏数据小魔方

蛇形图

今天要跟大家分享的图表是蛇形图! 该图表的制作原理很类似之前讲过的垂直折线图,不过这里要复杂一些,会用到很多错位排列的技巧。 下面就开始吧,还是首选让大家看一下...

42150
来自专栏邹成卓的专栏

Unity3D WebCamTexture 取帧渲染、像素读取的终端适配

由于Win/Mac/Adnroid/iOS等各系统平台和硬件环境下,WebCamTexture 用于渲染和图像计算时表现不完全一致,很容易造成图像渲染或者计算不...

57000
来自专栏jianhuicode

深入浅出之移动端屏幕适配(1)

说到移动端:可以根据开发技术分,也可以根据操作系统来分,今天重点不是这个,是讲下使用CSS与Android如何进行屏幕适配。 1.先来了解几个概念:CSS中的p...

247100
来自专栏HTML5学堂

一步步教你弹性框架-上篇

HTML5学堂:本系列主要在于跟大家分享弹性运动框架的制作方式。弹性运动框架的运动方式类似于弹簧,有一种回弹的效果,在网站中的一些特效当中还是有一些应用的。实现...

38080

扫码关注云+社区

领取腾讯云代金券