网格布局:flexbox 彻底改变了网页布局方式,但这只是开始。它还有一个大哥:另一个称作网格布局模块的新规范。这两个规范提供了一种前所未有的全功能布局引擎。跟 flexbox 类似,网格布局也是作用于两级的 dom 结构。设置为 display:grid 的元素成为一个网格容器(grid container)。它的子元素则变成网格元素。

<!DOCTYPE html>
<html lang="cn" class="has-bottombar">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
name="viewport"
/>
<style>
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-gap: 0.5em;
} .grid > * {
background-color: darkgray;
color: white;
padding: 2em;
border-radius: 0.5em;
}
</style>
</head> <body>
<div class="grid">
<div class="a">a</div>
<div class="b">b</div>
<div class="c">c</div>
<div class="d">d</div>
<div class="e">e</div>
<div class="f">f</div>
</div>
</body>
</html>

  在支持网格布局的浏览器中,这段代码会渲染三列,共六个大小相等的盒子。首先,使用 display:grid 定义一个网格容器。容器会表现得像一个块级元素。100%填充可用宽度。也可以使用 inline-grid,这样元素就会在行内流动,且宽度只能够包含子元素,不过 inline-grid 的使用频率不高。接下来是新属性:grid-template-columns 和 grid-template-rows。这两个属性定义了网格每行每列的大小。本例使用了一种新单位 fr,代表每一行或每一列的分数单位(fraction unit)。这个单位跟 flexbox 中的 flex-grow 因子的表现一样。grid-template-columns:1fr 1fr 1fr 表示三列等宽。不一定非得用分数单位,可以使用其他的单位,比如 px,em 或者百分数。也可以混搭这几种单位,例如 grid-template-columns:300px 1fr 定义了一个固定宽为 300px 的列,后面跟着一个会填满剩余可用空间的列。2fr 的列宽是 1fr 的两倍。最后,grid-gap 属性定义了每个网格单元之间的间距。也可以用两个值分别指定垂直和水平方向的间距。比如(grid-gap:0.5em 1em;)

  理解网格各个部分很重要。前面已经提及网格容器和网格元素,这些事网格布局的基本元素。grid line 网格线:网格线构成了网格的框架。一条网格线可以水平或垂直,也可以位于一行或一列的任意一侧。如果指定了 grid-gap 的话,它就位于网格线上。grid track 网格轨道:一个网络轨道上两条相邻网格线之间的空间。网格有水平轨道和垂直轨道。网格单元 grid cell:网格上的单个空间,水平和垂直的网格轨道交叉重叠的部分。grid area 网格区域:网格上的矩形区域,由一个到多个网格单元组成。该区域位于两条垂直网格线和两条水平网格线之间。

  构建网格布局时会涉及这些组成部分。比如声明 grid-template-columns:1fr 1fr 1fr 就会定义三个等宽且垂直的网格轨道,同时还定义了四条垂直的网格线:一条在网格最左边,两条在每个网格轨道之间,还有一条在最右边。讲 flexbox 的时候构建了一个网页,假如用网格来实现。有一点值得注意的事,使用网格并不会让 flexbox 失去用武之地。用网格实现同样的布局需要改一下 html 结构:将嵌套的 html 拉平。放在网格里的每个元素都必须是主要网格容器的子元素。

<!DOCTYPE html>
<html lang="cn" class="has-bottombar">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
name="viewport"
/>
<style>
:root {
box-sizing: border-box;
} *,
:before,
:after {
box-sizing: inherit;
} body {
background-color: #709b90;
font-family: Arial, Helvetica, sans-serif;
} .container {
display: grid;
grid-template-columns: 2fr 1fr;
grid-template-rows: repeat(4, auto);
grid-gap: 1.5em;
max-width: 1080px;
margin: 0 auto;
} header,
nav {
grid-column: 1/3;
grid-row: span 1;
} .main {
grid-column: 1/2;
grid-row: 3/5;
} .sidebar-top {
grid-column: 2/3;
grid-row: 3/4;
} .sidebar-bottom {
grid-column: 2/3;
grid-row: 4/5;
} .tile {
padding: 1.5em;
background-color: #fff;
} .tile > :first-child {
margin-top: 0;
} .tile * + * {
margin-top: 1.5em;
}
</style>
</head> <body>
<div class="container">
<header>
<h1 class="page-heading">Ink</h1>
</header> <nav>
<ul class="site-nav">
<li><a id="button1">Home</a></li>
<li><a id="button2">Features</a></li>
<li><a id="button3">Pricing</a></li>
<li class="nav-right">
<a href="/about">About</a>
</li>
</ul>
</nav> <main class="main tile">
<h1>Team collaboration done right</h1>
<p>
Thousands of teams from all over the world turn to <b>Ink</b> to
communicate and get things done.
</p>
<h1>Team collaboration done right</h1>
<p>
Thousands of teams from all over the world turn to <b>Ink</b> to
communicate and get things done.
</p>
<h1>Team collaboration done right</h1>
<p>
Thousands of teams from all over the world turn to <b>Ink</b> to
communicate and get things done.
</p>
<h1>Team collaboration done right</h1>
<p>
Thousands of teams from all over the world turn to <b>Ink</b> to
communicate and get things done.
</p>
<h1>Team collaboration done right</h1>
<p>
Thousands of teams from all over the world turn to <b>Ink</b> to
communicate and get things done.
</p>
<h1>Team collaboration done right</h1>
<p>
Thousands of teams from all over the world turn to <b>Ink</b> to
communicate and get things done.
</p>
<h1>Team collaboration done right</h1>
<p>
Thousands of teams from all over the world turn to <b>Ink</b> to
communicate and get things done.
</p>
<h1>Team collaboration done right</h1>
<p>
Thousands of teams from all over the world turn to <b>Ink</b> to
communicate and get things done.
</p>
</main> <div class="sidebar-top tile">
<form class="login-form">
<h3>Login</h3>
<p>
<label for="username">Username</label>
<input id="username" type="text" name="username" />
</p>
<p>
<label for="password">Password</label>
<input id="password" type="password" name="password" />
</p>
<button>Login</button>
</form>
</div> <div class="sidebar-bottom tile centered">
<small>Starting at</small>
<div class="cost">
<span class="cost-currency">$</span>
<span class="cost-dollars">20</span>
<span class="cost-cents">.00</span>
</div>
<a class="cta-button" href="/pricing"> Sign up </a>
</div>
</div>
</body>
</html>

  这段代码引入了很多新概念。代码首先设置了网格容器,并用 grid-template-columns 和 grid-template-rows 定义了网格轨道。因为列的分数单位分别是 2fr 和 1fr,所以第一列的宽度是第二列的两倍。定义行的时候用到了一个 repeat()函数。它再说声明多个网格轨道的时候提供了简写方式。grid-template-rows:repeat(4,auto);定义了四个水平网格轨道,高度为 auto,这等价于 grid-template-rows:auto auto auto auto。轨道大小设置为 auto,轨道会根据自身内容扩展。用 repeat()符号还可以定义不同的重复模式,比如 repeat(3,2fr 1fr)会重复三遍这个模式,从而定义 6 个网格轨道,重复的结果是 2fr 1fr 2fr 1fr 2fr 1fr。grid-template-columns:1fr repeat(3,3fr) 1fr;还可以将 repeat()作为一个更长的模式的一部分。比如 grid-template-columns:1fr repeat(3,3fr) 1fr 定义了一个 1fr 的列,接着是三个 3fr 的列,最后还有一个 1fr 的列。可以看出来因为展开的写法无法一目了然,所以才产生了 repeat()这种简写方式。

  网格轨道定义好之后,要将每个网格元素放到特定的位置上。可以在 grid-column 和 grid-row 属性中用网格线的编号指定网格元素的位置。如果想要一个网格元素在垂直方向上跨越 1 号网格线到 3 号网格线,就需要给元素设置 grid-column:1/3。或者设置 grid-row:3/5 让让元素在水平方向上跨越 3 号网格线到 5 号网格线。这两个属性一起就能指定一个元素应该放置的网格区域。

<style>
header,
nav {
grid-column: 1/3;
grid-row: span 1;
}
.main {
grid-column: 1/2;
grid-row: 3/5;
} .sidebar-top {
grid-column: 2/3;
grid-row: 3/4;
} .sidebar-bottom {
grid-column: 2/3;
grid-row: 4/5;
}
</style>

  这段代码将 main 元素放在第一列,(1 号到 2 号网格线之间)跨越第三行到第四行(3 号到 5 号网格线)的位置。侧边栏的两个板块放在右列(2 号到 3 号网格线之间),并且在第三行到第四行上下排列。这些属性实际上是简写属性:grid-column 是 grid-column-start 和 grid-column-end 的简写;grid-row 是 grid-row-start 和 grid-row-end 的简写。中间的斜线只在简写属性用于区分两个值,斜线前后的空格不作要求。定位 header 和 nav 的规则集稍有变化。代码里使用之前介绍的 grid-column 写法,让网格元素占满网格的宽度。其实还可以用一个特别的关键字 span 来指定 grid-row 和 grid-column 的值(这里用在了 grid-row 上)。这个关键字告诉浏览器元素需要占据一个网格轨道。因为这里没有指出具体是哪一行,所以会根据网格元素的布局算法自动将其放到合适的位置。布局算法会将元素放在网格上可以容纳该元素的第一处可用空间。

  与 flexbox,grid 几乎是一起开发出来的,虽然它们的功能有一些重叠的地方,但是它们各自擅长的场景不一样。在一个设计设计场景里,要根据特定的需求来做出选择。这两种布局方式有以下两个重要区别。flexbox 本质是一维的,而网格是二维的。flexbox 是以内容为切入点由内向外工作的,而网格是以布局为切入点从外向内工作的。因为 flexbox 是一维的,所以它很适合用在相似的元素组成的列(或行)上。它支持用 flex-wrap 换行,但是没法让上一行元素跟下一行元素对齐。相反,网格是二维的,指在解决一个轨道的元素跟另一个轨道的元素对齐的问题。

  用网格给网页的主区域定位是因为我们希望内容能限制在它所在的网格内,但是对于网页上的其他元素,比如导航菜单,则允许内容对布局有更大的影响。也就是说,文字多的元素可以宽一些,文字烧的元素则可以窄一些。同时这还是一个水平(一维)布局。因此,用 flexbox 来处理这些元素更合适。当设计要求元素在两个维度上都对齐时,使用网格。当只关心一维的元素排列时,使用 flexbox.在实践中,这通常意味着网格更适合用于整体的网页布局,而 flexbox 更适合对网格区域内的特定元素布局。继续用网格和 flexbox,你就会对不同情况下该用哪种布局方式得心应手。

  布局网格元素还有另外两个替代语法:命名的网格线和命名的网格区域。至于选择哪个纯属个人偏好。有时候记录所有网格线的编号实在太麻烦了,尤其是在处理很多网格轨道时。为了能简单点,可以给网格线命名,并在布局时使用网格线的名称而不是编号。声明网格轨道时,可以在中括号内写上网格线的名称:grid-template-columns:[start] 2fr [center] 1fr [end];这条声明定义了两列的网格,三条垂直的网格线分别叫做 start,center,end.之后定义网格元素在网格中的位置时,可以不用编号而是这些名称来声明,grid-column:start/center;接下来还有命名网格区域。不过暂时感觉不会用。

  在某些场景下,可能不清楚该把元素放在网格的哪个位置上。当处理大量的网格元素时,挨个指定元素的位置未免太不方便。当元素是从数据库获取时,元素的个数可能是未知的。在这些情况下,以一种宽松的方式定义网格可能更合理,剩下的交给布局算法来放置网格元素。这时需要用到隐式网格。使用 grid-template-*属性定义网格轨道时,创建的是显式网格,但是有些网格元素仍然可以放在显式轨道外面,此时会自动创建隐式轨道以扩展网格,从而包含这些元素。

  隐式网格轨道默认大小为 auto,也就是它们会扩展到能容纳网格元素的内容。可以给网格容器设置 grid-auto-columns 和 grid-auto-rows,为隐式网格轨道指定一个大小。在指定网格线的时候,隐式网格轨道不会改变负数的含义。接下来实现一个照片墙。这个布局很有意思,因为它用 flexbox 或者浮动很难实现。

<!DOCTYPE html>
<html lang="cn" class="has-bottombar">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
name="viewport"
/>
<style>
:root {
box-sizing: border-box;
} *,
::before,
::after {
box-sizing: inherit;
} body {
background-color: #709b90;
font-family: Helvetica, Arial, sans-serif;
} .portfolio {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-auto-rows: 1fr;
grid-gap: 1em;
} .portfolio > figure {
margin: 0;
} .portfolio img {
max-width: 100%;
} .portfolio figcaption {
padding: 0.3em 0.8em;
background-color: rgba(0, 0, 0, 0.5);
color: #fff;
text-align: right;
}
</style>
</head> <body>
<div class="portfolio">
<figure class="featured">
<img src="data:images/monkey.jpg" />
<figcaption>Monkey</figcaption>
</figure>
<figure>
<img src="data:images/eagle.jpg" />
<figcaption>Eagle</figcaption>
</figure>
<figure class="featured">
<img src="data:images/bird.jpg" />
<figcaption>Bird</figcaption>
</figure>
<figure>
<img src="data:images/bear.jpg" />
<figcaption>Bear</figcaption>
</figure> <figure class="featured">
<img src="data:images/swan.jpg" />
<figcaption>Swan</figcaption>
</figure>
<figure>
<img src="data:images/elephants.jpg" />
<figcaption>Elephants</figcaption>
</figure>
<figure>
<img src="data:images/owl.jpg" />
<figcaption>Owl</figcaption>
</figure>
</div>
</body>
</html>

  有时候我们不想给一个网格轨道设置固定尺寸,但是又希望限制它的最小值和最大值。这时候需要用到 minmax()函数。它指定两个值:最小尺寸和最大尺寸。浏览器会确保网格轨道的大小介于这两者之间。(如果最大尺寸小于最小尺寸,最大尺寸就会被忽略。)通过指定 minmax(200px,1fr),浏览器确保了所有的轨道至少宽 200px。repeat()函数里的 auto-fill 关键字是一个特殊值。auto-fill 和 minmax(200px,1fr)加在一起,就会让网格在可用的空间内尽可能多地产生网格列,并且每个列的宽度不会小于 200px。

  接下来,我们让特定图片变大,增加一些视觉上的趣味性。现在每个网格元素都占据了 1x1 的区域,将特定图片的尺寸增加到 2x2 的网格区域。由于元素按顺序排列,增加某些网格元素的大小会导致网格中出现空白区域。网格布局模块规范提供了另一个属性 grid-auto-flow,它可以控制布局算法的行为。它的初始值是 row,上一段描述的就是这个值的行为。如果值为 column,它就会将元素优先放在网格列中,只有当一列填满了,才会移动到下一行。还可以额外加一个关键字 dense(grid-auto-flow:column dense)。它让算法紧凑的填满网格里的空白,尽管这会改变某些网格元素的顺序。加上这个关键字,小元素就会回填大元素造成的空白区域。

<style>
:root {
box-sizing: border-box;
} *,
::before,
::after {
box-sizing: inherit;
} body {
background-color: #709b90;
font-family: Helvetica, Arial, sans-serif;
} .portfolio {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-auto-flow: dense;
grid-auto-rows: 1fr;
grid-gap: 1em;
width: 1080px;
margin: 0 auto;
} .portfolio > figure {
display: flex;
flex-direction: column;
margin: 0;
} .portfolio img {
flex: 1;
object-fit: cover;
max-width: 100%;
} .portfolio .featured {
grid-row: span 2;
grid-column: span 2;
} .portfolio figcaption {
padding: 0.3em 0.8em;
background-color: rgba(0, 0, 0, 0.5);
color: #fff;
text-align: right;
}
</style>

深入理解css 笔记(6)的更多相关文章

  1. 理解CSS

    写在前面的话:对于web开发,html完成网页的structure,css完成网页的presentation,js完成网页的behavior,今天就来说一说css,通过理解一些css的基础概念,能够更 ...

  2. 深入理解css BFC 模型

    如果要深入理解css布局的各种原理,要在重构页面做得心应手的话,那么你就必须先理解这玩意 "BFC" , BlockFormatting Context(块级格式化上下文): 这里 ...

  3. 深入理解CSS中的层叠上下文和层叠顺序(转)

    by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/wordpress/?p=5115 零.世间的道 ...

  4. 深入理解CSS溢出overflow & overflow:hidden真的失效了吗[转载]

    深入理解CSS溢出overflow http://www.cnblogs.com/xiaohuochai/p/5289653.html overflow:hidden真的失效了吗 http://www ...

  5. 深入理解css中的margin属性

    深入理解css中的margin属性 之前我一直认为margin属性是一个非常简单的属性,但是最近做项目时遇到了一些问题,才发现margin属性还是有一些“坑”的,下面我会介绍margin的基本知识以及 ...

  6. 深入理解css中position属性及z-index属性

    深入理解css中position属性及z-index属性 在网页设计中,position属性的使用是非常重要的.有时如果不能认识清楚这个属性,将会给我们带来很多意想不到的困难. position属性共 ...

  7. 深入理解CSS中的层叠上下文和层叠顺序

    零.世间的道理都是想通的 在这个世界上,凡事都有个先后顺序,凡物都有个论资排辈.比方说食堂排队打饭,对吧,讲求先到先得,总不可能一拥而上.再比如说话语权,老婆的话永远是对的,领导的话永远是对的. 在C ...

  8. 理解CSS居中

    我想很多在前端学习或者开发过程中,肯定会遇到如何让你的元素居中的问题,网上google肯定会有很多的解决方法.今天我就个人的项目与学习经验谈谈个人理解css如何让元素居中. 要理解css的居中,首先必 ...

  9. <转>HTML+CSS总结/深入理解CSS盒子模型

    原文地址:http://www.chinaz.com/design/2010/1229/151993.shtml 前言:前阵子在做一个项目时,在页面布局方面遇到了一点小问题,于是上stackoverf ...

  10. 认识和理解css布局中的BFC

    认识和理解css布局中的BFC BFC的定义 是 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用. Block Formatting Con ...

随机推荐

  1. 接口设置ip跨域

    // 允许跨域请求的地址'allowUrls' => [ 'http://localhost:8080', 'http://192.168.2.224', 'http://192.168.2.2 ...

  2. C# Linq查本集合中不包含于另一个集合的元素

    public void Linq() { List<Product> products = GetProductList(); List<Customer> customers ...

  3. Python3 学习基础知识

    python是动态语言(对象属性可以动态改变,删除添加..),不是强类型语言,所以和java,c/c++等强类型静态语言有不一样地方需要注意. 一:基本数据类型 变量 counter = 1   # ...

  4. centos-7实现批量ping

    批量ping 脚本 新接手了一个项目,10多个网段,500多机器,看自己机器可以连上多少服务器,一个个ping不符合我们的作风,因此百度了下大神的脚本,按自己的风格修改了,于是有了如下的脚本. 脚本如 ...

  5. go 死锁示例

    以下代码不会有任何打印.原因是:channel ch 在make 时是无缓冲区的channel.无缓冲区的channel 发送一个数据进入后需要等待这个数据被消耗才能继续发送下一个数据.然而getFr ...

  6. 小批量excel数据导入oracle

    前提是小批量数据,大批量的还是建议用sqlloader 使用PLSQL Developer工具,这个可是大名鼎鼎的Oracle DBA最常使用的工具.在单个文件不大的情况下(少于100000行),并且 ...

  7. mac中Mysql各种版本下载

    https://downloads.mysql.com/archives/community/ 安装后,5.8以下修改密码,参考 https://www.cnblogs.com/xuyin/p/121 ...

  8. 微信小程序:微信web开发阶段性学习总结

    小程序运行机制 前台/后台状态 小程序启动后,界面被展示给用户,此时小程序处于前台状态. 当用户点击右上角胶囊按钮关闭小程序,或者按了设备 Home 键离开微信时,小程序并没有完全终止运行,而是进入了 ...

  9. bzoj 3561

    题意:求$\sum_{i=1}^{n}\sum_{j=1}^{n}lcm(i,j)^{gcd(i,j)}$ 神仙题... 首先可能会想到一个转化,就是$lcm(i,j)=\frac{ij}{gcd(i ...

  10. JAVA第六七八次大作业

         21201411-李英涵            前言:这几次的作业较为简单,主要思路就是利用正则表达式来过滤掉不需要的信息.  题量设置较为合理,比之前的多边形好做一些,应该是老师为了捞起来 ...