Flex 与 Grid 相比就像功能键盘和触摸屏。触摸屏的控制力相比功能键盘来讲就像是降维打击,由于功能键盘只能上下左右控制(x、y 轴),而触摸屏打破了布局障碍,直接从(z 轴)触达,这样 不管 UI 内部布局再复杂,均可以经过 touch 直接定位。css
Flex 是一维布局方式,咱们须要不断嵌套 Div 才能造成复杂结构,而一旦布局产生了变化,原有嵌套结构若是不能 “兼容变化” 到新结构,代码就须要重构。而 Grid 就像触摸屏同样,能够二维布局,即使布局方式作了翻天覆地的调整,也仅需少许修改就能适配。html
这就是此次精读 用 css grid 从新思考布局 的缘由,理解这个革命性布局技术给布局,甚至代码逻辑组织带来的变化。前端
做者首先抛出了 Flex 的问题,实际上是 block
float
flex
这三种布局模式的通病:css3
minmax
之类的 API,因此定制型不足。举个例子,上图的结构用 Flex 描述多是这样的:git
<div class="card"> <div class="profile-sidebar"> <img src="https://i.pravatar.cc/125?image=3" alt="" class="profile-img" /> <ul class="social-list"> <li> <a href="#" class="social-link" ><i class="fab fa-dribbble-square"></i ></a> </li> <li> <a href="#" class="social-link" ><i class="fab fa-facebook-square"></i ></a> </li> <li> <a href="#" class="social-link" ><i class="fab fa-twitter-square"></i ></a> </li> </ul> </div> <div class="profile-body"> <h2 class="profile-name">Ramsey Harper</h2> <p class="profile-position">Graphic Designer</p> <p class="profile-info"> Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere a tempore, dignissimos odit accusantium repellat quidem, sit molestias dolorum placeat quas debitis ipsum esse rerum? </p> </div> </div>
利用 HTML 嵌套结构,咱们将图形纵向分红两大块,而后在每块内部继续嵌套划分布局,这是最经典的布局行为了。github
样式文件里,咱们须要对每层布局进行描述,同时支持多分辨率弹性布局,包括顶层 card
容器在内的一些样式须要作必定调整:微信
.card { width: 80%; margin: 0 auto; display: flex; flex-direction: column; max-width: 600px; background: #005e9b; flex-basis: 250px; color: white; padding: 2em; text-align: center; } .profile-info { font-weight: 300; opacity: 0.7; } .profile-sidebar { margin-right: 2em; text-align: center; } .profile-name { letter-spacing: 1px; font-size: 2rem; margin: 0.75em 0 0; line-height: 1; } .profile-name::after { content: ""; display: block; width: 2em; height: 1px; background: #5bcbf0; margin: 0.5em auto 0.65em; opacity: 0.25; } .profile-position { text-transform: uppercase; font-size: 0.875rem; letter-spacing: 3px; margin: 0 0 2em; line-height: 1; color: #5bcbf0; } .profile-img { max-width: 100%; border-radius: 50%; border: 2px solid white; } .social-list { list-style: none; justify-content: space-evenly; display: flex; min-width: 125px; max-width: 175px; margin: 0 auto; padding: 0; } .social-link { color: #5bcbf0; opacity: 0.5; } .social-link:hover, .social-link:focus { opacity: 1; } .bio { padding: 2em; display: flex; flex-direction: column; justify-content: center; } @media (min-width: 450px) { .bio { text-align: left; max-width: 350px; } } .bio-title { color: #0090d1; font-size: 1.25rem; letter-spacing: 1px; text-transform: uppercase; line-height: 1; margin: 0; } .bio-body { color: #555; } .profile { display: flex; align-items: flex-start; } @media (min-width: 450px) { .card { flex-direction: row; text-align: left; } .profile-name::after { margin-left: 0; } }
让咱们看看 Grid 是怎么作的吧!Grid 有许多 API,咱们重点看 grid-template-areas
这个属性,利用它,咱们能够不关心模块的 HTML 结构,直接平铺方式描述:ide
<div class="card"> <img src="https://i.pravatar.cc/125?image=3" alt="" class="profile-img" /> <ul class="social-list"> <li> <a href="#" class="social-link"><i class="fab fa-dribbble-square"></i></a> </li> <li> <a href="#" class="social-link"><i class="fab fa-facebook-square"></i></a> </li> <li> <a href="#" class="social-link"><i class="fab fa-twitter-square"></i></a> </li> </ul> <h2 class="profile-name">Ramsey Harper</h2> <p class="profile-position">Graphic Designer</p> <p class="profile-info"> Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere a tempore, dignissimos odit accusantium repellat quidem, sit molestias dolorum placeat quas debitis ipsum esse rerum? </p> </div>
能够看到,使用 Grid 能够将 UI 结构与 HTML 结构分离,HTML 结构仅描述包含关系,咱们只需在样式文件中描述具体 UI 结构。模块化
样式文件只截取 Grid 相关部分:布局
.card { width: 80%; margin: 0 auto; display: flex; flex-direction: column; max-width: 600px; background: #005e9b; flex-basis: 250px; color: white; padding: 2em; text-align: left; display: grid; grid-template-columns: 1fr 3fr; grid-column-gap: 2em; grid-template-areas: "image name" "image position" "social description"; } .profile-name { grid-area: name; } .profile-position { grid-area: position; } .profile-info { grid-area: description; } .profile-img { grid-area: image; } .social-list { grid-area: social; }
能够看到,grid-template-areas
是进一步抽象的语法,将页面结构经过直观的文本描述,不管是理解仍是修改都更为轻松。
这种描述方式适配不一样分辨率下也具备优点,只要重组 grid-template-areas
便可:
@media (min-width: 600px) { .card { text-align: left; grid-template-columns: 1fr 3fr; grid-template-areas: "image name" "image position" "social description"; } }
归根结底,Grid 经过二维结构描述,将子元素布局控制收到了父级,使布局描述更加直观。
最后做者也提到,Flex 依然有使用场景,即简单的一维结构,或者 space-between
等 Flex 独有语法的状况。所以推荐总体、复杂的二维布局采用 Grid,一维的简单布局采用 Flex。
Grid 的布局思路给了我不少启发,HTML 结构与 UI 结构的分离有助于减小 DIV 的层级结构,使代码看上去更清晰。
也许有人会疑惑,Grid 无非将 HTML 布局部分功能挪到了 CSS,总体复杂度应该不变。其实,从 grid-template-areas
这个 API 能够看到,Grid 不只仅将布局功能抽到 CSS 中,更是将布局描述进行了一层抽象,使代码更易维护。
为何 Grid 能够对布局进行抽象?由于 Grid 将二维结构都掌握在手中,获得了更大的布局能力,才能进一步将结构化语法抽象为字符串的描述。
抽象的好处是不言而喻的,你以为一堆嵌套的 DIV 与下面的代码,哪一个更易读呢?
.card { grid-template-areas: "image name" "image position" "social description"; }
这就是抽象的好处,通常来讲,代码抽象程度越高就越易读,越易维护。
再看一个 Chrome Grid 插件,将 Grid 可视化显示出来,并能够以 UI 方式进行调整:
UI 是对文本的再抽象,同时能够规避一些不可能存在的语法,好比:
.card { grid-template-areas: "image name" "image position" "social image"; }
布局只能以凸多边形方式拓展,不可能分离,也不可能忽然插入一个其余模块而变成凹多边形。所以 UI 能够将这个错误规避,并简化为横竖多条线的方式对 UI 进行划分,显然这种描述方式效率更高。
不得不说,Grid 以及图形化插件的探索,是布局领域的一大进步,是不断抽象的尝试,要解决的问题只有一个:如何提供一种更直观的描述 UI 的方式。
Grid 将布局方式提升了一个维度,会直接影响到 JS 模块化方式。
尤为是以 JSX 组织代码的状况下,一个模块等于 UI + JS,经过嵌套方式的布局会让咱们更倾向于站在 UI 视角划分模块。
好比对于上图模块,若是用 Flex 方式布局,咱们可能会首先建立模块 X 做为左侧容器,子元素是 A 和 B,建立模块 Y 做为右侧容器,子元素是 C 以及新容器 Z,Z 容器的子元素是 D 和 E。
若是你的第一印象是这么组织代码,不得不认可模块化会受到布局方式的影响。虽然许多时候这样划分是正确的,但当这 5 个模块各自没有关联时,咱们建立的容器 X、Y、Z 就失去了复用性,在新的组合场景咱们又要从新组合一遍。
可是在 Grid 语法中,咱们不须要 X、Y、Z,只须要用 css grid generator 按照上图的方式拖拖拽拽便可自动生成以下布局代码:
.parent { display: grid; grid-template-columns: 3fr repeat(2, 1fr); grid-template-rows: repeat(5, 1fr); grid-column-gap: 0px; grid-row-gap: 0px; } .div1 { grid-area: 1 / 1 / 3 / 2; } .div2 { grid-area: 3 / 1 / 6 / 2; } .div3 { grid-area: 1 / 2 / 2 / 4; } .div4 { grid-area: 2 / 2 / 6 / 3; } .div5 { grid-area: 2 / 3 / 6 / 4; }
其实 grid-template-columns
grid-template-rows
组合起来使用比 grid-template-areas
更强大,可是纯代码方式描述没有 grid-template-areas
直观,但是配合一些可视化系统就很是直观了:
将 A ~ E 这 5 个模块布局抽出来后,它们之间的关系就打平了,咱们能够彻底从逻辑视角审视如何作模块化了。
CSS Grid 本质上是一种二维布局的语法,相比 Block、Flex 等一维布局方案,多了一个维度能够同时从行与列角度定义布局,所以派生出 grid-template-areas
等语法,总体上更内聚更直观,抽象度也更高了。
理解了这些也就理解了布局将来的发展方向,让布局与 Dom 分离 一直是前端的一个梦想,开发 UI 部分时,只需关心页面由哪些模块组成,去实现这些模块就好了,而不须要关心模块之间应该如何组合。在描述组合时,能够经过可视化或比较抽象的字符串描述布局的结构,并对应到写好的模块上,这样的代码维护性远高于用 DIV 描述结构的方案。
讨论地址是: 精读《用 css grid 从新思考布局》 · Issue #211 · dt-fe/weekly
若是你想参与讨论,请 点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。
关注 前端精读微信公众号
<img width=200 src="https://img.alicdn.com/tfs/TB...;>
版权声明:自由转载-非商用-非衍生-保持署名( 创意共享 3.0 许可证)