原文 https://mp.weixin.qq.com/s/aHyWCzUYwcnkwt5MWhGfFw
相信很多前端同志对弹性盒(Flex)布局很熟悉,但是对于网格(Grid)布局很陌生,甚至在项目中从来没有用到过。今天就带大家学习一下网格布局是如何玩的。
> 如果你懒的动手写代码,或者本地创建项目,博主贴心的为你准备了代码预览地址,你可以一边调试一边预览效果。
## 1\. 什么是网格布局
网格是由一系列水平及垂直的线构成的一种布局模式。根据网格,我们能够将设计元素进行排列,帮助我们设计一系列具有固定位置以及宽度的元素的页面,使我们的网站页面更加统一。
一个网格通常具有许多的**列(column)与行(row)**,以及行与行、列与列之间的间隙,这个间隙一般被称为**沟槽(gutter)**。
也就是下面这张图:
![图片](https://mmbiz.qpic.cn/sz_mmbiz_png/Kgb3xohibzibIuz1Cbna4jpmGGCibntFBuoqmaVb4vE10n9bYYwHKSTKEc4R945X29bsNBLHSETOLibicGojgRiaX9Lg/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1)
我们一般会根据我们的设计图来决定网格的布局长什么样子。
接下来我们从一个基础的网格系统开始学起来。
## 2\. 自定义网格布局
布局如下:
~~~
<h1>Simple grid example</h1>
<div class="container">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
<div>Six</div>
<div>Seven</div>
</div>
~~~
### 2.1. Gird
首先,你要设置网格布局,必须把display设置为`grid`。
~~~
.container {
display: grid;
}
~~~
### 2.2. grid-template-columns
此时的布局并没有任何变化,我们需要通过`grid-template-columns`设置列的宽度,给个三列,每列200px吧。
~~~
.container {
display: grid;
grid-template-columns: 200px 200px 200px;
}
~~~
此时,页面效果如下:
![图片](https://mmbiz.qpic.cn/sz_mmbiz_png/Kgb3xohibzibIuz1Cbna4jpmGGCibntFBuoyZL5iajp0JJJtOU4mkTq7Nia0OK52s5XuAPMoUXkvjT8kDibMztq5ZUNQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1)
### 2.3. gap
使用 grid-column-gap(en-US) 属性来定义列间隙;使用 grid-row-gap(en-US) 来定义行间隙;使用 grid-gap(en-US) 可以同时设定两者。
修改代码:
~~~
.container {
display: grid;
grid-template-columns: 200px 200px 200px;
grid-gap: 20px;
gap: 20px;
}
~~~
**备注:**gap属性曾经有一个grid-前缀,不过后来的标准进行了修改,目的是让他们能够在不同的布局方法中都能起作用。尽管现在这个前缀不会影响语义,但为了代码的健壮性,你可以把两个属性都写上。
此时,页面效果如下:
![图片](https://mmbiz.qpic.cn/sz_mmbiz_png/Kgb3xohibzibIuz1Cbna4jpmGGCibntFBuo5QC1oSgbyLKXibVErRiaMnVHxWicRe99XpuJodEBfqrypGAc7qQSEOLIQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1)
### 2.4. fr
这里除了使用px意外,我们也可以用 fr 这个单位来灵活地定义网格的行与列的大小。这个单位代表网格容器中可用空间的一份。也就是把列等分以后,每列占据的份数是多少,fr值越法,占据的空间就越大。
修改代码:
~~~
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
~~~
这个意思是,把列三等分,每列占据1份空间。
此时,页面效果如下:
![图片](https://mmbiz.qpic.cn/sz_mmbiz_gif/Kgb3xohibzibIuz1Cbna4jpmGGCibntFBuoeeBqTJhNwXxHVbyWg9EibicbkX3k4Czv4FWbPqEmibt4Zx5maw2W5DYXA/640?wx_fmt=gif&wxfrom=5&wx_lazy=1&wx_co=1)
### 2.5. repeat
你可以使用repeat来重复构建具有某些宽度配置的某些列。举个例子,如果要创建多个等宽轨道,可以用下面的方法。
~~~
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 20px;
}
~~~
这个效果跟上面的代码是一致的。第一个传入 repeat 函数的值(3)表明了后续列宽的配置要重复多少次,而第二个值(1fr)表示需要重复的构建配置,这个配置可以具有多个长度设定。例如repeat(2, 2fr 1fr),如果你仍然不明白,可以实际测试一下效果,这相当于填入了 2fr 1fr 2fr 1fr。
### 2.6. grid-template-rows
通过`grid-template-rows`可以设置行的高度,我们给每行设置个100px吧。
~~~
.container {
display: grid;
grid-gap: 20px;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 100px 100px 100px;
}
~~~
此时,页面效果如下:
![图片](https://mmbiz.qpic.cn/sz_mmbiz_png/Kgb3xohibzibIuz1Cbna4jpmGGCibntFBuoU7YjSpJrmdIjL6aDvIicFlDXW4OOl7yH1971YnP052zic25vDQPqvBGA/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1)
### 2.7. minmax() 函数
100 像素高的轨道有时可能会不够用,因为时常会有比 100 像素高的内容加进去。所以,我们可以将其设定为至少 100 像素,并且能够跟随内容来自动拓展尺寸,从而保证能容纳所有内容。显而易见,你很难知道网页上某个元素的尺寸在不同情况下会变成多少,一些额外的内容或者更大的字号就会导致许多能做到像素级精准的设计出现问题。所以有了minmax()函数。
minmax()函数为一个行/列的尺寸设置了取值范围。比如设定为 minmax(100px, auto),那么尺寸就至少为 100 像素,并且如果内容尺寸大于 100 像素则会根据内容自动调整。在这里试一下把 grid-auto-rows 属性设置为minmax函数。
~~~
.container {
display: grid;
grid-gap: 20px;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: minmax(100px, auto) 100px 100px;
}
~~~
此时,页面效果如下:
![图片](https://mmbiz.qpic.cn/sz_mmbiz_png/Kgb3xohibzibIuz1Cbna4jpmGGCibntFBuomyicWQtZJ0ibX5b5Zia87qcV0Yrue1VMGzLVCrfSEn9waSjxyk1JvTTGA/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1)
可以看到,我们设置了minmax(100px, auto)以后,此时内容高度会自动撑高。
### 2.8. auto-fill
在上面的布局中,每次都是把行和列的属性重复写三次才能都生效。有没有更简便的方法呢?有,那就是repeat中的一个参数:auto-fill。
~~~
.container {
display: grid;
grid-gap: 20px;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-auto-rows: minmax(100px, auto);
}
~~~
此时,页面效果如下:
![图片](https://mmbiz.qpic.cn/sz_mmbiz_png/Kgb3xohibzibIuz1Cbna4jpmGGCibntFBuoxONlwicRLzMqFW8J2BCFp6oD9xK5b1omOmiawsmv3Fibq1JiaUvxINOtkw/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1)
以上代码参考地址:https://stackblitz.com/edit/web-platform-vabj4w?file=styles.css
## 3\. 基于线的元素放置
既然是一个网格,那么它就有线,我们可以根据这些线所处的位置来放置我们的元素。如下图所示:
![图片](https://mmbiz.qpic.cn/sz_mmbiz_png/Kgb3xohibzibIuz1Cbna4jpmGGCibntFBuoE2AxX2icfkxWRNeDPx38AwaJVBmrtHjJmMXPdjiauYQUaQw5Kl5raGibA/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1)
在英文中,第一条列分隔线(即网格边缘线)在网格的最左边而第一条行分隔线在网格的最上面。而对于阿拉伯语,第一条列分隔线在网格的最右边,因为阿拉伯文是从右往左书写的。
### 3.1. grid-column和grid-row
我们根据这些分隔线来放置元素,通过以下属性来指定从那条线开始到哪条线结束。
* grid-column-start
* grid-column-end
* grid-row-start
* grid-row-end
这些属性的值均为分隔线序号,你也可以用以下缩写形式来同时指定开始与结束的线。
* grid-column
* grid-row
注意开始与结束的线的序号要使用/符号分开。
上面的概念听起来是不是没听懂?没关系,我们接下来做个博客系统的布局,你就懂了:
![图片](https://mmbiz.qpic.cn/sz_mmbiz_png/Kgb3xohibzibIuz1Cbna4jpmGGCibntFBuoFlsdqjNJnyLtibBMEOnW56DLMRosuy7t8EFbRdoQwdb6cic1mBVmNjqA/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1)
页面布局如下:
~~~
<div class="container">
<header>This is my lovely blog</header>
<aside>
<h2>Other things</h2>
<p>
Nam vulputate diam nec tempor bibendum. Donec luctus augue eget
malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut,
facilisis sed est.
</p>
</aside>
<article>
<h1>My article</h1>
<p>
Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras
porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed
auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet
orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac
ornare ex malesuada et. In vitae convallis lacus. Aliquam erat
volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin
eros pharetra congue. Duis ornare egestas augue ut luctus. Proin
blandit quam nec lacus varius commodo et a urna. Ut id ornare felis,
eget fermentum sapien.
</p>
<p>
Nam vulputate diam nec tempor bibendum. Donec luctus augue eget
malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut,
facilisis sed est. Nam id risus quis ante semper consectetur eget
aliquam lorem. Vivamus tristique elit dolor, sed pretium metus
suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu
urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt
eget purus in interdum. Cum sociis natoque penatibus et magnis dis
parturient montes, nascetur ridiculus mus.
</p>
</article>
<footer>Contact me@mysite.com</footer>
</div>
~~~
添加css样式
~~~
body {
width: 90%;
max-width: 900px;
margin: 2em auto;
font: 0.9em/1.2 Arial, Helvetica, sans-serif;
}
header,
footer {
border-radius: 5px;
padding: 10px;
background-color: rgb(207, 232, 220);
border: 2px solid rgb(79, 185, 227);
}
aside {
border-right: 1px solid #999;
}
.container {
display: grid;
grid-template-columns: 1fr 3fr;
gap: 20px;
}
header {
grid-column: 1 / 3;
grid-row: 1;
}
article {
grid-column: 2;
grid-row: 2;
}
aside {
grid-column: 1;
grid-row: 2;
}
footer {
grid-column: 1 / 3;
grid-row: 3;
}
~~~
我们再来看看这个页面布局的网格线:
![图片](https://mmbiz.qpic.cn/sz_mmbiz_png/Kgb3xohibzibIuz1Cbna4jpmGGCibntFBuofSQQN1TeuaeFdMafXCe9Yz6NMEA1X8YzVhXJVyHNsmVQia2fppRStNw/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1)
拿header来说,grid-column: 1 / 3,意思就是说从列的位置从分隔线序号1开始,从分隔线序号3结束,是不是跟上面图中的网格线一致?其他元素的布局也是类似的,你可以一一的对照去看。
以上代码参考地址:https://stackblitz.com/edit/web-platform-tmtmba?file=styles.css
### 3.2. grid-template-areas
当然,上面的布局实现方式可以用另一种往网格放元素的方式:grid-template-areas,并且你要命名一些元素并在属性中使用这些名字作为一个区域。
将之前基于线的元素放置代码删除(或者重新下载一份新的文件),然后加入以下 CSS 规则:
~~~
.container {
display: grid;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
grid-template-columns: 1fr 3fr;
gap: 20px;
}
header {
grid-area: header;
}
article {
grid-area: content;
}
aside {
grid-area: sidebar;
}
footer {
grid-area: footer;
}
~~~
同样的也能实现上面博客的布局效果。
## 4\. 网格排版框架
网格排版框架一般由 12 到 16 列的网格构成,下面我们实现一个12列网格的排版框架。页面布局还是以上面博客的为例,参考代码:https://stackblitz.com/edit/web-platform-pfi7ju?file=styles.css
我们可以用基于线的元素放置模式来将我们的内容放到这个 12 列的网格中。
~~~
.container {
display: grid;
grid-template-columns: repeat(12, minmax(0, 1fr)); /** 关键代码 **/
gap: 20px;
}
header {
grid-column: 1 / 13;
grid-row: 1;
}
article {
grid-column: 4 / 13;
grid-row: 2;
}
aside {
grid-column: 1 / 4;
grid-row: 2;
}
footer {
grid-column: 1 / 13;
grid-row: 3;
}
~~~
在Google浏览器中使用开发者工具查看它的网格线,你应该能看到这 12 列的网格是如何工作的了。
![图片](https://mmbiz.qpic.cn/sz_mmbiz_png/Kgb3xohibzibIuz1Cbna4jpmGGCibntFBuoqUsmxJtZp82N9fbNN97eeseFe5ibwyxDF823EJsfjVPKeeqz1tKMfiaA/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1)
> 总结:我们在这篇文章中接触了 CSS 网格版面的主要特性,你现在应该可以在你自己的设计中使用了。
最后,看完了别忘了给博主三连。请转发给你的朋友,让他们也学会网格布局的使用技巧吧,非常感谢!
- 后端
- composer
- composer配置国内镜像
- composer安装及设置2
- PHP
- 贝塔SG11加密
- 申请KEY
- 开始加密
- php 中连接tcp服务的三种方式
- php websocket 教程
- editor内容转换数组
- 使用正则判断中文维吾尔文
- PHP常用函数总结
- 常用助手函数
- 通过Imagick把pdf转换图片
- 维吾尔语基本区转换扩展区
- php GD库生成一个由文字和图片生成新的图片
- aes加密
- php数组函数 -- array_column,array_multisort 实现二维数组排序
- PHP操作Excel
- php更新内容
- 辅助查询(*)
- 【时间】操作
- 时间函数例子
- Date/Time 函数(不包含别名函数)
- php网络相关
- HTTP请求的返回值含义说明
- 使用php语言开发一个类似数据库操作的文件表类
- pinyin
- 维吾尔语基本区转换扩展区(2)
- php获取当前环境的信息
- laravel
- laravel 队列的使用
- laravel 自定义助手函数
- laravel seeder的使用
- laravel项目从git下载命令
- laravel 多个数据库配置
- laravel 填充假数据
- laravel 动态路由
- laravel 自定义 validate 响应
- laravel 创建追加字段的模拟访问器
- laravel 线上环境的数据库更改或添加字段
- laravel 模型查询按照whereIn排序
- laravel 使用 workerman 通过TCP 文件传输功能
- laravel api Header添加Accept头
- Laraval IDE 自动补全插件 laravel-ide-helper
- laravel 网站后台
- laravel 设置路由
- laravel-第三方composer包
- laravel 开发技巧
- laravel 昨天,今天时间
- 使用宝塔计划任务启动laravel调度器
- laravel结合workerman第二节
- Laravel - 上传多个文件
- 查询聊天好友列表
- 事件系统 event, listener
- laravel 安装 laravel-modules
- 自定义求看守器-toekn
- laravel限流
- 使用 Laravel api Resource 类时自定义分页信息
- Laravel php artisan命令大全
- 验证器
- workerman 创建wss服务
- 架构师必须知道的26项PHP安全实践
- python
- Python读取文件代码块已经备好,用的时候光拿(建议收藏)
- Python常用库大全
- api 签名验证
- git
- git命令
- 十分钟学会git基础
- Git代码同时上传到GitHub和Gitee(码云)
- Git - 多人协同开发利器,团队协作流程规范与注意事项
- 删除远程仓库的文件
- github查询方法
- 错误
- 解除项目git版本控制
- linux
- sentos安装supervisor
- PHP怎么守护进程运行php脚本
- 600条最强Linux命令总结
- centos开启防火墙、开放指定端口
- 前端
- vue
- vue2发布之前的config简单配置
- vue2安装scss命令
- vue2父子组件之间双向数据绑定
- 国际化双语--安装VueI18n
- vue3-setup 组件传参(defineProps、defineEmits、defineExpose
- Vue3 新写法速览:十分钟内轻松get
- 关于vue的外连接
- watch讲解
- computed
- webpack 打包后生成很多小文件怎么优化?
- vue2 vue.config.js常见配置和打包部署测试
- 小程序
- 小程序长期订阅消息
- 小程序自定义TabBar后如何实现keep-alive
- 收藏的html和css和js
- CSS 省略号(单行省略号、多行省略号)
- UyghurInput_a.js
- font.css
- 漂亮按钮样式
- clock.html
- css
- scroll css样式
- CSS流动布局-页面自适应
- css grid布局
- 禁止wap页面调整字体大小
- CSS @media 和 min-width/max-width
- 网站变灰是怎么实现的
- 瀑布流实现方式
- javascript
- SortableJS拖动排序
- wondow scroll滚动到上边
- 原生js插入HTML元素
- Konva.js —— 像操作DOM一样操作canvas
- 通过canvas合并俩个图片
- js scroll更多加载
- js 实现复制功能
- js判断安卓和苹果或者微信
- 浏览器打开控制台禁止
- 原生js一些dom操作
- js http客户端集合
- fetch
- axios
- canvas 点钟
- layer dialog
- jquery 和 laravel ajax全局配置
- layui 获取select的自定义参数
- konva.js中文开发文档
- js 大文件分片上传
- js监听网络状态实现断网重连后自动刷新页面
- js生成video缩略图
- JS获取当前系统电量情况
- uniapp
- uni-app swiper数量过多时卡顿优化方案
- uniapp 帖子集合
- 微信wap
- wap分享朋友和朋友圈
- wap 手机页面微信支付
- JsSdk微信公众号支付
- 通用各种小知识
- 正则表达式
- JS正则匹配过滤字符串中的html标签及html标签内的内容
- 判断维吾尔文输入
- 正则表达式符号
- 正则表达式练习
- 百度网盘不限速下载助手
- 解决VSCode下载慢或下载失败的问题
- 性能测试 使用Apache的ab测试工具
- nginx从入门到精通
- nginx
- Nginx 是怎么禁止访问php的 ?
- 宝塔面板
- supervisor
- 卸载宝塔
- redis
- redis实用笔记
- redis入门到精通
- phpredis
- redis数据库基础
- PHP对Redis的基本操作
- ffmpeg
- 合并多个音视
- 获取音视时长
- FFmpeg视频处理入门教程(新手必看)
- 外连接
- 安装
- PHP基于ffmpeg实现转换视频,截图及生成缩略图的方法
- Linux安装ffmpeg
- docker
- 服务实现
- docker基本命令
- rewrite笔记
- 别人笔记链接
- 计算机常用知识
- 二进制1-10
- 斐波那契数列
- mysql
- 高性能高可用的MySQL,得从各种规范开始
- 读写分离配置
- 重要外连接,前端/ 后端/数据库等等
- 关于程序必须收藏的文章链接集合
- markdown
- 一篇文章讲清楚markdown