惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
The Exploit Database - CXSecurity.com
V
Vulnerabilities – Threatpost
Google DeepMind News
Google DeepMind News
Attack and Defense Labs
Attack and Defense Labs
Webroot Blog
Webroot Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
TaoSecurity Blog
TaoSecurity Blog
I
Intezer
Application and Cybersecurity Blog
Application and Cybersecurity Blog
N
News | PayPal Newsroom
S
Security Affairs
T
Tor Project blog
P
Proofpoint News Feed
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Security @ Cisco Blogs
H
Heimdal Security Blog
Hacker News: Ask HN
Hacker News: Ask HN
Help Net Security
Help Net Security
U
Unit 42
云风的 BLOG
云风的 BLOG
The Hacker News
The Hacker News
Cisco Talos Blog
Cisco Talos Blog
量子位
F
Full Disclosure
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 叶小钗
有赞技术团队
有赞技术团队
T
Troy Hunt's Blog
P
Privacy & Cybersecurity Law Blog
Forbes - Security
Forbes - Security
人人都是产品经理
人人都是产品经理
L
Lohrmann on Cybersecurity
Apple Machine Learning Research
Apple Machine Learning Research
Microsoft Security Blog
Microsoft Security Blog
博客园 - Franky
腾讯CDC
AI
AI
Last Week in AI
Last Week in AI
Latest news
Latest news
Google Online Security Blog
Google Online Security Blog
N
Netflix TechBlog - Medium
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
IT之家
IT之家
Martin Fowler
Martin Fowler
Blog — PlanetScale
Blog — PlanetScale
V2EX - 技术
V2EX - 技术
酷 壳 – CoolShell
酷 壳 – CoolShell

张鑫旭-鑫空间-鑫生活

1分钟速度了解text-align match-parent声明 « 张鑫旭-鑫空间-鑫生活 光标的形状也能设置了,就是CSS caret-shape属性 « 张鑫旭-鑫空间-鑫生活 pretext与文字四面环绕效果的实现 « 张鑫旭-鑫空间-鑫生活 JSON.rawJSON方法的作用是什么? « 张鑫旭-鑫空间-鑫生活 如何使用CSS判断鼠标从哪个方向进入元素? « 张鑫旭-鑫空间-鑫生活 借助mediabunny纯JS实现视频水印、剪裁、合成等功能 « 张鑫旭-鑫空间-鑫生活 务必谨慎使用JS WeakRef弱引用 « 张鑫旭-鑫空间-鑫生活 CSS六边形头像的实现与蜂巢布局 « 张鑫旭-鑫空间-鑫生活 CSS corner-shape与背景底纹技术 « 张鑫旭-鑫空间-鑫生活 浅学WebTransport API:下一代Web双向通信技术 « 张鑫旭-鑫空间-鑫生活 HTML dialog元素新支持了closedBy属性 « 张鑫旭-鑫空间-鑫生活 HTML interestfor属性与悬停popover交互效果 « 张鑫旭-鑫空间-鑫生活 CSS3模拟window7炫酷界面效果展示 « 张鑫旭-鑫空间-鑫生活 图片旋转+剪裁js插件(兼容各浏览器) « 张鑫旭-鑫空间-鑫生活 纯js无图片无外链CSS图片幻灯片播放插件 « 张鑫旭-鑫空间-鑫生活 CSS border三角、圆角图形生成技术简介 « 张鑫旭-鑫空间-鑫生活 CSS “渐进增强”在web制作中常见应用举例 « 张鑫旭-鑫空间-鑫生活 让IE6/IE7/IE8浏览器支持CSS3属性 « 张鑫旭-鑫空间-鑫生活 jQuery – 高亮动态显示页面HTML代码插件 « 张鑫旭-鑫空间-鑫生活 翻译 – 逐渐消失的Flash网站 « 张鑫旭-鑫空间-鑫生活 CSS reset的重新审视 – 避免样式重置 « 张鑫旭-鑫空间-鑫生活 新浪微博插入话题后部分文字选中的js实现 « 张鑫旭-鑫空间-鑫生活 JavaScript实现http地址自动检测并添加URL链接 « 张鑫旭-鑫空间-鑫生活 CSS实现兼容性的渐变背景(gradient)效果 « 张鑫旭-鑫空间-鑫生活 CSS content内容生成技术以及应用 « 张鑫旭-鑫空间-鑫生活 CSS gradient渐变之webkit核心浏览器下的使用 « 张鑫旭-鑫空间-鑫生活 CSS渐变之CSS3 gradient在Firefox3.6下的使用 « 张鑫旭-鑫空间-鑫生活 区分IE8/IE7/IE6及其他浏览器-CSS “\9″hack « 张鑫旭-鑫空间-鑫生活 CSS实现跨浏览器兼容性的盒阴影效果 « 张鑫旭-鑫空间-鑫生活 CSS3&HTML5各浏览器支持情况一览表 « 张鑫旭-鑫空间-鑫生活 翻译 – CSS Sprites:实用技术还是生厌之物? « 张鑫旭-鑫空间-鑫生活 纯CSS实现易拉罐3D滚动效果 « 张鑫旭-鑫空间-鑫生活 纯CSS实现侧边栏/分栏高度自动相等 « 张鑫旭-鑫空间-鑫生活 CSS+JavaScript实现页面不同布局的切换 « 张鑫旭-鑫空间-鑫生活 JavaScript实现最简单的拖拽效果 « 张鑫旭-鑫空间-鑫生活 自己写的无图片版jQuery zxxbox弹出框插件 « 张鑫旭-鑫空间-鑫生活 中国古代道家思想与网页重构的思考 « 张鑫旭-鑫空间-鑫生活 让所有浏览器支持HTML5 video视频标签 « 张鑫旭-鑫空间-鑫生活 纯CSS实现各类气球泡泡对话框效果 « 张鑫旭-鑫空间-鑫生活 JS HEX十六进制与RGB, HSL颜色的相互转换 « 张鑫旭-鑫空间-鑫生活 CSS实现兼容性的渐变、高光等文字效果 « 张鑫旭-鑫空间-鑫生活 去除冗余 – 精简您的CSS样式代码 « 张鑫旭-鑫空间-鑫生活 对overflow与zoom”清除浮动”的一些认识 « 张鑫旭-鑫空间-鑫生活 jQuery Pagination Ajax分页插件中文详解 « 张鑫旭-鑫空间-鑫生活 absolute绝对定位的非绝对定位用法 « 张鑫旭-鑫空间-鑫生活 网页布局思想浅议-淘宝新版首页为实例 « 张鑫旭-鑫空间-鑫生活 回流与重绘:CSS性能让JavaScript变慢? « 张鑫旭-鑫空间-鑫生活 CSS float浮动的深入研究、详解及拓展(二) « 张鑫旭-鑫空间-鑫生活 CSS float浮动的深入研究、详解及拓展(一) « 张鑫旭-鑫空间-鑫生活 60个极富创造性的震撼的电影海报设计 « 张鑫旭-鑫空间-鑫生活 jQuery Lightbox(balupton版)图片展示插件讲解 « 张鑫旭-鑫空间-鑫生活 博客内嵌flash音乐播放器代码、下载与使用 « 张鑫旭-鑫空间-鑫生活 CSS3 animate实现图片墙3D翻转效果 « 张鑫旭-鑫空间-鑫生活 图片旋转效果的一些研究、jQuery插件及实例 « 张鑫旭-鑫空间-鑫生活 CSS3 border-image详解、应用及jQuery插件 « 张鑫旭-鑫空间-鑫生活 jQuery-两款不同原理的圆角插件讲解 « 张鑫旭-鑫空间-鑫生活 页面可用性之outline轮廓外框的一些研究 « 张鑫旭-鑫空间-鑫生活 CSS3 transition实现超酷图片墙动画效果 « 张鑫旭-鑫空间-鑫生活 HTML CSS列表元素ul,ol,dl的研究与应用 « 张鑫旭-鑫空间-鑫生活 jQuery图片文本滚动切换插件jCarousel中文翻译与详解 « 张鑫旭-鑫空间-鑫生活 酷酷的jQuery鼠标悬停图片放大切换显示效果 « 张鑫旭-鑫空间-鑫生活 IE6下z-index犯癫不起作用bug的初步研究 « 张鑫旭-鑫空间-鑫生活 checkbox复选框的一些深入研究与理解 « 张鑫旭-鑫空间-鑫生活 jQuery之使用slideToggle实现垂直下拉菜单 « 张鑫旭-鑫空间-鑫生活 jQuery-innerfade内部列表自动淡入淡出插件 « 张鑫旭-鑫空间-鑫生活 jQuery-火焰灯效果导航菜单 « 张鑫旭-鑫空间-鑫生活 IE下css bug集合-翻译自haslayout.net « 张鑫旭-鑫空间-鑫生活 翻译-IE7/8@font-face嵌入字体与文字平滑 « 张鑫旭-鑫空间-鑫生活 jQuery-马化腾产品设计与用户体验的一些技术实现 « 张鑫旭-鑫空间-鑫生活 像素的世界及其在web开发制作中的应用 « 张鑫旭-鑫空间-鑫生活 css行高line-height的一些深入理解及应用 « 张鑫旭-鑫空间-鑫生活 CSS实现圆角六色渐变自适应按钮详解 « 张鑫旭-鑫空间-鑫生活 我熟知的三种三栏网页宽度自适应布局方法 « 张鑫旭-鑫空间-鑫生活 jQuery照片图像剪裁插件Jcrop中文翻译详解 « 张鑫旭-鑫空间-鑫生活 Ajax Upload多文件上传插件翻译及中文演示 « 张鑫旭-鑫空间-鑫生活 告别图片—使用字符实现兼容性的圆角尖角效果beta版 « 张鑫旭-鑫空间-鑫生活 大小不固定的图片、多行文字的水平垂直居中 « 张鑫旭-鑫空间-鑫生活 jQuery boxy弹出层对话框插件中文演示及讲解 « 张鑫旭-鑫空间-鑫生活 JavaScript实现新浪微博文字放大显示动画效果 « 张鑫旭-鑫空间-鑫生活 翻译:让网络更快一些——最小化浏览器中的回流(reflow) « 张鑫旭-鑫空间-鑫生活 jQuery之addClasas与removeClass使用实例 « 张鑫旭-鑫空间-鑫生活 关于Google圆角高光高宽自适应按钮及其拓展 « 张鑫旭-鑫空间-鑫生活 JavaScript实现图片幻灯片滚动播放动画效果 « 张鑫旭-鑫空间-鑫生活 jQuery-鼠标经过显示大图并跟随鼠标效果插件 « 张鑫旭-鑫空间-鑫生活 关于gif图片(或png8)杂边锯齿的问题 « 张鑫旭-鑫空间-鑫生活 对html与body的一些研究与理解 « 张鑫旭-鑫空间-鑫生活 鲜为人知的一个解决兼容性问题的利器——小数 « 张鑫旭-鑫空间-鑫生活 搜狐白社会似iphone短信对话框效果的优化 « 张鑫旭-鑫空间-鑫生活 关于文字内容溢出用点点点(…)省略号表示 « 张鑫旭-鑫空间-鑫生活 jquery之append与insertBefore使用实例 « 张鑫旭-鑫空间-鑫生活 jQuery之图片关联伸缩效果 « 张鑫旭-鑫空间-鑫生活 jquery之图片左右切换动画效果 « 张鑫旭-鑫空间-鑫生活 jQuery之replace字符串替换实现不同尺寸图片切换 « 张鑫旭-鑫空间-鑫生活 jQuery-实现图片的放大镜显示效果 « 张鑫旭-鑫空间-鑫生活 jQuery-单击文字或图片内容放大显示效果插件 « 张鑫旭-鑫空间-鑫生活 reflection.js-实现图片投影倒影效果js插件 « 张鑫旭-鑫空间-鑫生活 jQuery-很酷的弹出层效果js插件 « 张鑫旭-鑫空间-鑫生活 复选框单选框与文字对齐问题的研究与解决 « 张鑫旭-鑫空间-鑫生活 css margin的相关属性,问题及应用 « 张鑫旭-鑫空间-鑫生活 IE6下png背景不透明问题的综合拓展 « 张鑫旭-鑫空间-鑫生活
写给自己看的display: grid布局教程 « 张鑫旭-鑫空间-鑫生活
张鑫旭,zhangxinxu · 2018-11-06 · via 张鑫旭-鑫空间-鑫生活

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=8144
本文可全文转载,个人网站无需授权,只要保留原作者、出处以及文中链接即可,任何网站均可摘要聚合,商用请联系授权。

一、前言&索引

<div>这类块状元素元素设置display:grid或者给<span>这类内联元素设置display:inline-grid,Grid布局即创建!例如:

div {
    display: grid;
}

此时该div就是“grid容器”,其子元素称为“grid子项”。

//zxx: grid和inline-grid区别在于,inline-grid容器为inline特性,因此可以和图片文字一行显示;grid容器保持块状特性,宽度默认100%,不和内联元素一行显示。

在Grid布局中,所有相关CSS属性正好分为两拨,一拨作用在grid容器上,还有一拨作用在grid子项上。具体参见下表,点击可快速索引。

作用在grid容器上 作用在grid子项上

Grid布局相关CSS属性虽然很多,但是实际上都不难理解,难的是这些属性不太容易记住,需要多多实战手写才能信手拈来。

Grid布局是一个二维的布局方法,纵横两个方向总是同时存在。其中的很多布局概念跟中国农田的布局是完全匹配的。

田地

因此,在我看来,Grid布局就像是“分田种地”。故事是这样的,张老板是个程序员,省吃俭用攒了点小钱,然后老家因为城镇化建设,农村都没什么人,土地都荒废在那里,于是就承包了一块地,打算养养鱼,种种果树。承包的地方很挺大,如何划分土地就成了问题,于是张老板打算借助Grid布局来划分。

二、作用在grid容器上的CSS属性

1. grid-template-columns和grid-template-rows

这两个CSS属性用来对田地进行基本的划分,columns是列的意思,表示竖直方向的划分;rows是行的意思,表示水平方向的划分。现实世界中,农田的布局构造一般下面两种:

  1. 田地A-田地B,下面是土地C-土地D,就是“田”这个字的构造,只不过4块地之间分隔就是个不能走路的小沟沟,宽度可以忽略不计。

    分隔不明显的田地

  2. 田地A-田垄-田地B,下面是土地C-田垄-土地D,也是“田”这个字的构造,只不过4块地之间分隔是个可以走路的田垄,有的地方也叫土埂。

    分隔明显的田地

这里的划分语法就和上面的农田划分一致,如下:

.container {
  grid-template-columns: <track-size> ... | <line-name> <track-size> ...;
  grid-template-rows: <track-size> ... | <line-name> <track-size> ...;
}

用中文表示就是:

.container {
  grid-template-columns: <田地> ... 或 <田垄> <田地> ...;
  grid-template-rows: <田地> ... 或 <田垄> <田地> ...;
}

也就是:

  • <track-size>:划分田地的尺寸。可以是长度值,百分比值,以及fr单位(网格剩余空间比例单位)。
  • <line-name>:中间用来走路的田垄的名字,可以任意命名。

看一个简单例子:

.container {
    grid-template-columns: 80px auto 100px;
    grid-template-rows: 25% 100px auto 60px;
}

grid-template-columns后面3个值,表示分为了3列,从左往右每列的尺寸分别是80px,auto(自动)和100px
grid-template-rows属性值含4个值,表示分为了4行,从上往下每行的高度分别是25%100px,auto(自动)和60px

基本尺寸划分示意图

实时效果如下所示:

宽80px
高25%

宽auto
高25%

宽100px
高25%

宽80px
高100px

宽auto
高100px

宽100px
高100px

宽80px
高auto

宽auto
高auto

宽100px
高auto

宽80px
高60px

宽auto
高60px

宽100px
高60px

我们还可以给“田垄”,也就是网格分隔线进行命名,语法是使用[]包裹我们自定义的命名,可以是中文,例如:

.container {
    grid-template-columns: [第一根纵线] 80px [纵线2] auto [纵线3] 100px [最后的结束线];
    grid-template-rows: [第一行开始] 25% [第一行结束] 100px [行3] auto [行4] 60px [行末];
}

实时效果如下,选中对应网格线的名称可以高亮其位置:

宽80px
高25%

宽auto
高25%

宽100px
高25%

宽80px
高100px

宽auto
高100px

宽100px
高100px

宽80px
高auto

宽auto
高auto

宽100px
高auto

宽80px
高60px

宽auto
高60px

宽100px
高60px

为何要给网格线命名呢?

Grid布局的好比街道划分,田地划分,这中间分隔的线通常就是道路或者田垄,如果我们不给这些道路起个名字,回头想要描述某片区域的时候就不好描述。比方说:

南京东路东起外滩即中山东一路,西至西藏中路。

因为我们给道路命了名称,因此,我们在描述某个区域的时候,就好描述,别人也好辨认。但如果没有命名,而是下面这样描述:

南京东路东起靠近黄浦江第1条路,靠近黄浦江第8条路。

得,这个区域描述就有问题,万一哪天封路,或者新建了条路,岂不就混乱了?

也就是说,给Grid布局中的分隔线命名,为的就是可以更好地对区域进行描述。如果我们没有描述某片区域的的需求,自然也不需要命名了。

双命名

由于网格中中间区域的网格线是两边格子公用的,就像道路有两边,因此,我们起名字的时候可以起两个名称(使用空格分隔),分别表示两侧。例如:

.container {
    grid-template-columns: [第一根纵线] 80px [第1根纵线结束 第2根纵线开始] 100px [最后的结束线];
}

repeat语法

有时候,我们网格的划分是很规律的,例如,基于40px创建栅格,要是我们布局宽度960px,岂不是要写24次40px,实在套啰嗦了,此时,就可以使用repeat()语法,如下示意:

.container {
    grid-template-columns: repeat(24, 40px [col-start]);
}

等同于:

.container {
    grid-template-columns: 40px [col-start], 40px [col-start], /* ...省略20个...*/, 40px [col-start], 40px [col-start];
}

fr单位是什么?

fr是单词fraction的缩写,表示分数。

  • 先从简单例子看起:

    .container {
        grid-template-columns: 1fr 1fr 1fr;
    }

    1:1:1,网格宽度三等分,实时效果如下:

    宽1fr
    占据1/3

    宽1fr
    占据1/3

    宽1fr
    占据1/3

  • 如果有固定尺寸值,则划分剩余空间大小,例如:

    .container {
        grid-template-columns: 200px 1fr 1fr 1fr;
    }

    4列,后面3列宽度是grid容器宽度减去200像素后的1/3大小,实时效果如下:

    宽200px

    宽1fr

    宽1fr

    宽1fr

  • 如果和auto混用会如何呢?

    .container {
        grid-template-columns: auto 1fr 1fr 1fr;
    }

    宽auto

    宽1fr

    宽1fr

    宽1fr

    从上面效果可以看出,当有设置fr尺寸的时候,auto的尺寸表现为“包裹”,为内容宽度。如果没有设置fr尺寸的网格,则表现为拉伸。

  • 如果fr数值之和小于1又当如何?

    .container {
        grid-template-columns: auto 0.25fr .25fr .25fr;
    }

    宽auto

    宽0.25fr

    宽0.25fr

    宽0.25fr

  • 这里计算就相对复杂些,首先,由于第一个网格尺寸设置为auto,因此fr计算需要的剩余空间尺寸是grid容器的宽度减去“宽auto”这几个字符的宽度。所以,后面3个0.25fr元素的宽度是:(容器宽度 - “宽auto”字符宽度) * 0.25。然后剩余尺寸就是第一个网格宽度。

2. grid-template-areas

area是区域的意思,grid-template-areas就是给我们的网格划分区域的,就好像张老板承包的土地划分不同区域养殖不同的农作物或者水产品。

语法如下:

.container {
  grid-template-areas: 
    "<grid-area-name> | . | none | ..."
    "...";
}

其中:

grid-area-name
对应网格区域的名称。
.
表示空的网格单元格。
none
没有定义网格区域。

我们还是通过案例了解这个CSS属性。张老板承包了一块地,然后划分成了3*4共12个小格子,然后张老板希望最上面3个格子种葡萄,最下面3个格子种西瓜,中间6个格子,左边2个养龙虾,右边4个养鱼。如下图示意:

养殖承包区域划分示意

则对应CSS代码如下:

.container {
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows: 1fr 1fr 1fr 1fr;
    grid-template-areas: 
        "葡萄 葡萄 葡萄"
        "龙虾 养鱼 养鱼"
        "龙虾 养鱼 养鱼"
        "西瓜 西瓜 西瓜";
}

12个格子,四片区域,因此,我们grid子项只需要4个元素即可,HTML示意如下:

<div class="container">
    <div class="putao"></div>
    <div class="longxia"></div>
    <div class="yangyu"></div>
    <div class="xigua"></div>
</div>

此时grid子项只要使用grid-area属性指定其隶属于那个区域就可以了(支持中文区域名称):

.putao { grid-area: 葡萄; }
.longxia { grid-area: 龙虾; }
.yangyu { grid-area: 养鱼; }
.xigua { grid-area: 西瓜; }

实时Grid布局效果如下:

葡萄种植区

龙虾养殖区

鱼类养殖区

西瓜种植区

注意:如果我们给网格区域命了名,但是没有给网格线命名,则会自动根据网格区域名称生成网格线名称,规则是区域名称后面加-start-end。例如,某网格区域名称是“葡萄”,则左侧column线名称就是“葡萄-start”,左侧column线名称就是“葡萄-end”。

以及,我们的网格区域一定要形成规整的矩形区域,什么L形,凹的或凸的形状都是不支持的,会认为是无效的属性值。

//zxx: 实际开发的时候,葡萄种植区就是头部区域,龙虾就是侧边栏区域,鱼类养殖区就是主区域,西瓜种植区就是底部区域。

3. grid-template

grid-templategrid-template-rowsgrid-template-columnsgrid-template-areas属性的缩写。

语法如下:

.container {
    grid-template: none;
}
.container {
    grid-template: <grid-template-rows> / <grid-template-columns>;
}

其中none表示将3个CSS属性都设置为初始值。

举个例子,前面张老板养殖区划分,用grid-template缩写表示就是:

.container {
    grid-template: 
        "葡萄 葡萄 葡萄" 1fr 
        "龙虾 养鱼 养鱼" 1fr 
        "龙虾 养鱼 养鱼" 1fr 
        "西瓜 西瓜 西瓜" 1fr
        /1fr 1fr 1fr;
}

实时效果如下:

葡萄种植区

龙虾养殖区

鱼类养殖区

西瓜种植区

由于grid-template不会重置一些隐式的grid属性(如grid-auto-columnsgrid-auto-rowsgrid-auto-flow),因此,大多数时候,还是推荐使用grid代替grid-template

4. grid-column-gap和grid-row-gap

grid-column-gapgrid-row-gap属性用来定义网格中网格间隙的尺寸。你可以理解成田地之间走路的田垄宽度。

语法如下:

.container {
  grid-column-gap: <line-size>;
  grid-row-gap: <line-size>;
}

更新于2021-05-26
推荐使用column-gaprow-gap属性,兼容性也不错。

.container {
  column-gap: <line-size>;
  row-gap: <line-size>;
}

//zxx: 更新end

其中:

<line-size>
网格间的间隙尺寸。

实例说话,给定一个简单的2×2网格,设置水平网格间隙10px,垂直方向15px,如下:

.container {
    grid-template-columns: 2fr 1fr;
    grid-template-rows: 1fr 2fr;
    grid-column-gap: 10px;
    grid-row-gap: 15px;
}

浏览器实时布局渲染如下:

5. grid-gap

更新于2021-05-26
推荐使用gap属性作为缩写,grid-gap已经很老了。Multi-column布局,以及Flex布局的间隙现在也都统一使用gap属性了。

//zxx: 更新end

CSS grid-gap属性是grid-column-gapgrid-row-gap属性的缩写。语法如下:

.container {
    grid-gap: <grid-row-gap> <grid-column-gap>;
}

先横row后竖column,这个比较好记忆,古语有云:“横竖都是死”,先横后竖,网格的间隙就像是汉字“田”中间的那个“十”,按照汉字书写,先横后竖,就记住了。

例如,上面的2×2网格间隙案例也可以写作:

.container {
    grid-template-columns: 2fr 1fr;
    grid-template-rows: 1fr 2fr;
    grid-gap: 15px 10px;
}

效果一样的,这里就不占据篇幅重复示意了。

6. justify-items

justify-items指定了网格元素的水平呈现方式,是水平拉伸显示,还是左中右对齐,语法如下:

.container {
    justify-items: stretch | start | end | center;
}

其中:

stretch
默认值,拉伸。表现为水平填充。更正:默认值是legacy
start
表现为网格水平尺寸收缩为内容大小,同时沿着网格线左侧对齐显示(假设文档流方向没有变)。
end
表现为网格水平尺寸收缩为内容大小,同时沿着网格线右侧对齐显示(假设文档流方向没有变)。
center
表现为网格水平尺寸收缩为内容大小,同时在当前网格区域内部水平居中对齐显示(假设文档流方向没有变)。

各个属性值实时效果如下(点击单选框体验不同属性值布局效果):

示意图片1

示意图片2

示意图片3

示意图片4

7. align-items

align-items指定了网格元素的垂直呈现方式,是垂直拉伸显示,还是上中下对齐,语法如下:

.container {
    align-items: stretch | start | end | center;
}

其中(假设文档流方向为网页默认):

stretch
默认值,拉伸。表现为垂直填充。
start
表现为网格垂直尺寸收缩为内容大小,同时沿着上网格线对齐显示。
end
表现为网格垂直尺寸收缩为内容大小,同时沿着下网格线对齐显示。
center
表现为网格垂直尺寸收缩为内容大小,同时在当前网格区域内部垂直居中对齐显示。

各个属性值实时效果如下(点击单选框体验不同属性值布局效果):

示意图片1

示意图片2

示意图片3

示意图片4

8. place-items

place-items可以让align-itemsjustify-items属性写在单个声明中。语法如下:

.container {
    place-items: <align-items> <justify-items>?;
}

这里顺序是align-items在前,justify-items在后。首字母a,j,a,j,a,j,口中不断重复,有没有发现跟angelababy发音很像,没错,记住angelababy我们也就记住这里的顺序了。又或者有句古话,叫做“合纵连横”,这种网格对齐,就有“合纵连横”的意味在里面,纵在前,横在后,也可以方便我们记忆。

据说Edge15之前版本不支持place-items属性(自己未实测),因此,如果有兼容性顾虑,建议还是分开书写。

9. justify-content

justify-content指定了网格元素的水平分布方式。此属性仅在网格总宽度小于grid容器宽度时候有效果。例如,我们网格设定的都是固定的宽度值,结果还有剩余空间。例如:

.container {
    display: grid;
    width: 300px;
    grid-template: 100px 100px/100px 100px;
}

此时,水平和垂直方向都有100px的剩余,justify-content属性此时就有用武之地了。

语法如下:

justify-content: stretch | start | end | center | space-between | space-around | space-evenly;

其中:

stretch
默认值。拉伸,宽度填满grid容器,拉伸效果需要网格目标尺寸设为auto时候才有效,如果定死了宽度,则无法拉伸。
start
默认值。逻辑CSS属性值,与文档流方向相关。默认表现为左对齐。
end
逻辑CSS属性值,与文档流方向相关。默认表现为右对齐。
center
表现为居中对齐。
space-between
表现为两端对齐。between是中间的意思,意思是多余的空白间距只在元素中间区域分配。使用抽象图形示意如下:

space-between分布效果示意

space-around
around是环绕的意思,意思是每个grid子项两侧都环绕互不干扰的等宽的空白间距,最终视觉上边缘两侧的空白只有中间空白宽度一半。使用抽象图形示意如下:

space-around分布效果示意

space-evenly
evenly是匀称、平等的意思。也就是视觉上,每个grid子项两侧空白间距完全相等。使用抽象图形示意如下:

space-evenly分布效果示意

眼见为实,点击下面对应单复选框,可以看到实时的布局效果:

示意图片1

示意图片2

示意图片3

示意图片4

上面案例和下面案例中的grid布局相关CSS都是:

.container {
    grid-template: auto auto/auto auto;
}

10. align-content

align-content可以看成和justify-content是相似且对立的属性,justify-content指明水平方向grid子项的分布方式,而align-content则是指明垂直方向每一行grid元素的分布方式。如果所有grid子项只有一行,则align-content属性是没有任何效果的。

语法如下:

align-content: stretch | start | end | center | space-between | space-around | space-evenly;

其中:

stretch
默认值。每一行grid子元素都等比例拉伸。例如,如果共两行grid子元素,则每一行拉伸高度是50%。
start
逻辑CSS属性值,与文档流方向相关。默认表现为顶部堆砌。
end
逻辑CSS属性值,与文档流方向相关。默认表现为底部堆放。
center
表现为整体垂直居中对齐。
space-between
表现为上下两行两端对齐。剩下每一行元素等分剩余空间。
space-around
每一行元素上下都享有独立不重叠的空白空间。
space-evenly
每一行元素都完全上下等分。

眼见为实,我们给grid容器设置高度500像素,然后点击下面对应单选框,可以看到实时的布局效果:

示意图片1

示意图片2

示意图片3

示意图片4

11. place-content

place-content可以让align-contentjustify-content属性写在一个CSS声明中,也就是俗称的缩写。语法如下:

.container {
    place-content: <align-content> <justify-content>?;
}

这里顺序是align-content在前,justify-content在后。首字母a,j,a,j,读个几遍,是不是和angelababy发音一致,记住angelababy就记住这里的顺序了。又或者有句古话,叫做“合纵连横”,这种网格分布,就有“合纵连横”的意味在里面,纵在前,横在后,也可以方便我们记忆。

据说Edge15及其之前版本尚不支持place-content属性(自己未实测),因此,如果有兼容性顾虑,建议还是分开书写。

12. grid-auto-columns和grid-auto-rows

指定任何自动生成的网格轨道(也称为隐式网格轨道)的大小。 当网格项目多于网格中的单元格或网格项目放置在显式网格之外时,将创建隐式轨道。

用张老板承包土地的案例解释就是:

  1. 土地划分,计划分成16块区域搞农业,材料都买好了,结果发现承包的土地只能放下12块区域,多的4块怎么办呢?就在承包土地外面种点东西,不要浪费。
  2. 土地划分,计划上面种葡萄,底部种西瓜。但是,种植的时候搞错了,西瓜种到了承包区域之外。

上面这两种情况都是因为各种原因在自己土地之外也种了东西。如果张老板想要对不在自己土地上的种植区域也进行尺寸规划,该怎么办?此时就需要用到grid-auto-columnsgrid-auto-rows属性,就是应付这种场景的。

//zxx: 在Grid布局中,这些非正常网格称为“隐式网格”,在规定容器内显示的称之为“显式网格”。

语法如下:

.container {
    grid-auto-columns: <track-size> ...;
    grid-auto-rows: <track-size> ...;
}

其中:

<track-size>
划分田地的尺寸。可以是长度值,百分比值,以及fr单位(网格剩余空间比例单位)。

我们通过一个实例来感受下grid-auto-columnsgrid-auto-rows属性的样式表现。CSS如下:

.container {
    display: grid;
    width: 150px;
    grid-template-columns: 60px 60px;
    grid-template-rows: 30px 90px;
    grid-auto-columns: 60px;
}
.item-a { 
    grid-column: 1 / 2;
    grid-row: 2 / 3;
}
.item-b { 
    /* 容器水平只有2个格子,但这里设定的是第3个,隐式网格创建 */
    grid-column: 3 / 4;
    grid-row: 2 / 3; 
    background-color: rgba(255,255,0, .5);
}

实时效果如下,.item-b宽度强制表现为了60px,否则,则表现为auto,在这里,则是可怜巴巴填满剩余的30px

.item-a

.item-b

13. grid-auto-flow

grid-auto-flow属性控制没有明确指定位置的grid子项的放置方式。比方说定义了一个5*2的10格子,共有5个元素,其中2个元素指定了放在哪个格子里,还有3个则自生自灭排列。此时,这3个元素如何排列就是由grid-auto-flow属性控制的。

语法如下:

.container {
  grid-auto-flow: row | column | row dense | column dense
}

其中:

row
默认值。没有指定位置的网格依次水平排列优先。
column
没有指定位置的网格依次垂直排列优先。
dense
dense这个英文是稠密的意思。如果有设置,则表示自动排列启用“密集”打包算法。如果稍后出现的网格比较小,则尝试看看前面有没有合适的地方放置,使网格尽可能稠密紧凑。此属性值仅仅改变视觉顺序,会导致DOM属性和实际呈现顺序不符合,这对于可访问性是不友好的,建议谨慎使用。

实例说话,已知CSS如下:

.container{grid-template: 1fr 1fr 1fr/1fr 2fr 2fr 1fr 2fr;}
.item-a { grid-column: 1; grid-row: 2 / 4; }
.item-b { grid-row: 1 / 3; }
.item-c {}
.item-d {}
.item-e {}

也就是.item-a.item-b水平位置固定,点击下面单选项,体验布局变化。

.item-a

.item-b

.item-c

.item-d

.item-e

  • 选中row,水平排列,此时.item-c高度足够放在左上角那个网格中,因此,视觉顺序是c, b, d, e。
  • 选中column,垂直排列,此时.item-c宽度不足够放在左上角那个网格中,因此,视觉顺序(先上下后左右)是b, c, d, e。
  • 选中row dense,水平排列,同时前面有空就钻。视觉顺序同row属性。
  • 选中column dense,垂直排列,此时.item-c放置在左上角那个网格中,因此,视觉顺序(先上下后左右)是c, b, d, e,b和d垂直排列。

14. grid

是下面所有这些CSS属性的缩写集合,grid-template-rowsgrid-template-columnsgrid-template-areasgrid-auto-rowsgrid-auto-columnsgrid-auto-flow

语法如下:

  • grid: none

    none表示设置所有的子属性为初始值。

  • grid: <grid-template>

    grid-template用法一致。例如这样:

    .container {
        grid: 100px 300px / 3fr 1fr;
    }

    等同于下面:

    .container {
        grid-template-rows: 100px 300px;
        grid-template-columns: 3fr 1fr;
    }
  • grid: <grid-template-rows> / [ auto-flow && dense? ] <grid-auto-columns>? 

    问号?表示0或1,可有可无的意思。也就是dense关键字和grid-auto-columns值都可以省略。

    具体说明:

    • auto-flow && dense?其实就是grid-auto-flow属性的值,等同于rowcolumnrow densecolumn dense

      但这里rowcolumn这两个关键字却使用了auto-flow这一个关键字代替了。那岂不有问题:什么时候解析成row,什么时候解析成column呢?

      原来,是根据auto-flow关键字是在斜杠的左侧还是右侧决定的。如果auto-flow关键字在斜杠左侧,则解析为row,如果是在右侧,则解析为column。这里的语法是在斜杠的右侧,因此,会将grid-auto-flow解析为column

    • <grid-auto-columns>后面有个问号?,因此是可以省略的,如果省略,则将grid-auto-columns解析为auto

    我们通过几个案例学习这里的语法:

    .container {
        grid: 100px 300px / auto-flow 200px;
    }

    上面CSS代码省略了dense关键字,启用了<grid-auto-columns>,因此,等同于下面CSS:

    .container {
        grid-template-rows: 100px 300px;
        grid-auto-flow: column;
        grid-auto-columns: 200px;
    }

    记住,在Grid布局中,斜杠前面都是rows相关属性,斜杠后面都是columns相关属性(下同)。

  • grid: [ auto-flow && dense? ] <grid-auto-rows>? / <grid-template-columns>

    此语法和上面一个语法类似,只是这个斜杠前面是隐式网格,后面是显示。在这里,由于auto-flow在斜杠左侧,因此解析为row。所以:

    .container {
        grid: auto-flow dense 100px / 1fr 2fr;
    }

    就等同于下面CSS:

    .container {
        grid-auto-flow: row dense;
        grid-auto-rows: 100px;
        grid-template-columns: 1fr 2fr;
    }

grid属性缩写语法第一次学习会有些懵逼,乍一看,头都大了,各种非字母以外的符号,天书一样。其实&[]?这些符号实际书写都不参与的,仅仅用来表示逻辑。

好吧,送佛送到西,我最后再给大家梳理下:

  • grid:none好简单好舒爽,没什么好说的。
  • 如果网格布局中规中矩,没有哪个格子跑到grid容器外面,就是grid-template属性。
  • 最后两个语法完全是出现了grid容器外面格子时候才使用的,要么grid-template/auto-flow,要么auto-flow/grid-template,就这么简单。

说穿了,其实也没啥,一开始使用不熟练是很正常的,你多实践几次,多手写几次,很快就能掌握,成为Grid布局小能手了。

三、作用在grid子项上的CSS属性

1. grid-column-start, grid-column-end, grid-row-start和grid-row-end

表示grid子项所占据的区域的起始和终止位置,包括水平方向和垂直方向。

就好比张老板养鱼,这鱼塘东边从什么地方开始,往西到什么地方,南边是哪里,北面又到何处,都要说清楚,这样,这鱼池的面积和位置也就出来了。

语法如下:

.item {
    grid-column-start: <number> | <name> | span <number> | span <name> | auto
    grid-column-end: <number> | <name> | span <number> | span <name> | auto
    grid-row-start: <number> | <name> | span <number> | span <name> | auto
    grid-row-end: <number> | <name> | span <number> | span <name> | auto
}

语法中的管道分隔符|表示“或者”的意思,所以别看上面好长,实际上就一个属性值,具体来讲:

<number>
起止与第几条网格线。
<name>
自定义的网格线的名称。
span <number>
表示当前网格会自动跨越指定的网格数量。
span <name>
表示当前网格会自动扩展,直到命中指定的网格线名称。
auto
全自动,包括定位,跨度等。

看例子说话,CSS和HTML如下:

.container {
    grid-template-columns: [第一根纵线] 80px [纵线2] auto [纵线3] 100px [最后的结束线];
    grid-template-rows: [第一行开始] 25% [第一行结束] 100px [行3] auto [行末];
}
.item-a {
    grid-column-start: 2;
    grid-column-end: 纵线3;
    grid-row-start: 第一行开始;
    grid-row-end: 3;
}
<div class="container">
    <div class="item-a"></div>
</div>

实时效果如下:

number: 2
name: 纵线2
number: 1 name: 第一行开始number: 3
name: 纵线3
number: 3 name: 行3

.item-a

每根网格线都有内置的<number>,从1开始计数,上面Grid布局为3×3的九宫格,因此,水平和垂直都是4条网格线(含边缘),从左往右4条线<number>值依次是1-4,垂直方向从上往下也是类似。

再本例中,所有网格线都命名了中文名称,例如“第一根纵线”,就是最左边竖直网格线。因此,最终效果也就不难理解了——

grid-column-start:2表示.item-a网格左侧起始于<number>2的线;
grid-column-end:纵线3表示.item-a网格右侧结束于<name>纵线3的线;
grid-row-start:第一行开始表示.item-a网格上方开始于<name>第一行开始的线;
grid-row-end:3表示.item-a网格下方结束于<number>3的线。

span作用表现

下面我们再来看下span关键字的作用。如下CSS和HTML:

.item-b {
    grid-column-start: 2;
    grid-column-end: span 纵线3;
    grid-row-start: 第一行开始;
    grid-row-end: span 3;
}
<div class="container">
    <div class="item-b"></div>
</div>

效果为:

number: 2
name: 纵线2
number: 1 name: 第一行开始number: 3
name: 纵线3
number: 3number: 4

.item-b

对于命名的网格线,有span和没有span没有区别(包括多个同名网格线)。

更新于2020-05-30

span是个摆设仅限于网格线命名只有1个,且匹配的场景。如果多个匹配的网格线命名,或者没有匹配的网格线命名,span关键字就会有明显的作用,篇幅原因这里就不继续展开了。

//zxx: 更新end

但是,对于数值网格线,则可以看出差异,有span则表示跨越的个数,而非网格线的序号。例如这里grid-row-end:span 3表示当前网格需要覆盖3个格子。于是,我们可以看到.item-b高度贯穿整个grid容器。

2. grid-column和grid-row

grid-columngrid-row都是缩写啦,前者是grid-column-start + grid-column-end的缩写,后者是grid-row-start + grid-row-end的缩写。

语法上是使用斜杠分隔,如下:

.item {
    grid-column: <start-line> / <end-line> | <start-line> / span <value>;
    grid-row: <start-line> / <end-line> | <start-line> / span <value>;
}

语法中的管道分隔符|表示“或者”的意思。然后<start-line>就是grid-*-start属性值,<end-line>就是grid-*-end属性值。例如:

.item-b {
    grid-column: 2 / span 纵线3;
    grid-row: 第一行开始 / span 3;
}

等同于:

.item-b {
    grid-column-start: 2;
    grid-column-end: span 纵线3;
    grid-row-start: 第一行开始;
    grid-row-end: span 3;
}

3. grid-area

grid-area表示当前网格所占用的区域。在介绍grid-template-areas属性的时候就演示过该属性,我们使用grid-template-areas属性自定义一些网格区域,然后使用grid-area属性让grid子项指定使用这些区域,就自动进行了区域分布。

grid-areagrid-column/grid-row作用都是grid子项的分布,但grid-area语义要更好,识别度更佳,非常适合具有功能属性的布局区域(如头部,底部),同时,还支持非规则区域。

更新于2020-05-31

grid-area其实是grid-row-start, grid-column-start, grid-row-end 以及 grid-column-end属性的缩写,以及额外支持grid-template-areas设置的网格名称而已。

//zxx:更新end

语法如下:

.item {
    grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;
}

其中:

<name>
区域名称。由grid-template-areas属性创建。
<row-start> / <column-start> / <row-end> / <column-end>
占据网格区域的纵横起始位置。

<name>属性值使用参见上面张老板划分鱼塘案例。我们这里演示下后面的基于位置的区域划分,如下代码:

.container {
    grid-template: 1fr 1fr 1fr/1fr 1fr 1fr 1fr;
}
.item-c { 
    grid-area: 1 / 2 / 3 / 4;
}

1/2/3/4划分区

表示水平网格线位置起止分别是1,3,垂直起止网格线位置是2,4。于是得到一个2×2大小的区域。

4. justify-self

justify-self表示单个网格元素的水平对齐方式。语法如下:

.item {
    justify-self: stretch | start | end | center;
}

其中(假设文档流方向没有变):

stretch
默认值,拉伸。表现为水平填充。//zxx: 纠正:默认值是auto
start
表现为网格水平尺寸收缩为内容大小,同时沿着网格线左侧对齐显示。
end
表现为网格水平尺寸收缩为内容大小,同时沿着网格线右侧对齐显示。
center
表现为网格水平尺寸收缩为内容大小,同时在当前网格区域内部水平居中对齐显示。

各个属性值实时效果如下(点击单选框体验不同属性值布局效果):

示意图片1

示意图片2

示意图片3

示意图片4

5. align-self

align-self指定了网格元素的垂直呈现方式,是垂直拉伸显示,还是上中下对齐,语法如下:

.container {
    align-self: stretch | start | end | center;
}

其中(假设文档流方向为网页默认):

stretch
默认值,拉伸。表现为垂直填充。//zxx: 纠正:默认值是auto
start
表现为网格垂直尺寸收缩为内容大小,同时沿着上网格线对齐显示。
end
表现为网格垂直尺寸收缩为内容大小,同时沿着下网格线对齐显示。
center
表现为网格垂直尺寸收缩为内容大小,同时在当前网格区域内部垂直居中对齐显示。

各个属性值实时效果如下(点击单选框体验不同属性值布局效果):

示意图片1

示意图片2

示意图片3

示意图片4

6. place-self

place-items可以让align-selfjustify-self属性写在单个声明中。语法如下:

.item {
    place-self: <align-self> <justify-self>?
}

这里顺序是align-self在前,justify-self在后。首字母a,j,a,j,a,j,口中不断重复,有没有发现跟angelababy发音很像,没错,记住angelababy我们也就记住这里的顺序了。

据说Edge15及之前版本尚不支持place-self属性(自己未实测),因此,如果有兼容性顾虑,建议还是分开书写。

四、其他Grid知识点

  • 在Grid布局中,floatdisplay:inline-blockdisplay:table-cellvertical-align以及column-*这些属性和声明对grid子项是没有任何作用的。这个可以说是Grid布局中的常识,面试经常会问的,一定要记得。
  • Grid布局则适用于更大规模的布局(二维布局),而Flexbox布局最适合应用程序的组件和小规模布局(一维布局),关Flex布局请参见“写给自己看的display: flex布局教程”一文
  • 命名虽然支持中文,但由于CSS文件中文存在乱码的风险,所以……创新还是保守就看大家自己的抉择了。
  • IE10-IE15虽然名义上支持Grid布局,但支持的是老版本语法(本文是介绍的全是2.0全新语法),还需要加-ms-私有前缀,精力原因,IE下的使用并未深究,以后有机会再补充。

另外:

本文所有水平和垂直,左侧与右侧这类方位的描述均是在网页的水平和垂直流都是默认方向前提下的表述。

本教程优点在于交互效果可以实时体验,更直观。如果是转载文章,必定没有效果,访问原文即可。

Grid布局自己之前并未在实际项目中使用过,本文内容也是边学边写,文中若有表述不准确的地方欢迎指正。

感谢阅读!

参考文章:A Complete Guide to Grid

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=8144

(本篇完)