本帖最后由 yingliu 于 2018-3-28 16:29 编辑
CSS Grid 不但对于含长串文字内容的网站来说是好用的布局工具,也很适合拿来做许多传统 UI 的布局。本文将说明 CSS Grid 如何帮助需响应和适应用户互动及动态环境的应用程序改善其布局,同时还能让面板一直顺畅地滚动。
CSS Grid 能建立网站的布局。它让网页设计人员只用很小部分的程序代码,而不必像过去一样大量使用 float 工具,就能创造出绚丽的动态布局。Jen Simmons 多年来大力推广 CSS Grid,希望这个工具能登上浏览器。去年,她的努力终于有了结果:所有主流浏览器的最新桌面与移动版本都 开始支持 CSS Grid。
CSS Grid 的功能非常强大,可让你轻松建立动态内容的网站(如 这些实例)。不过,Grid 的好不仅限于一块块内容的布局。Grid 让你完全享有布局版面大小的主控权,比如滚动页面(scrolling),因此,以前在原生应用中习以为常的功能,如收合侧边面板和固定工具栏等,现在的操作都变得易如反掌。不用 hacks,也不必 debug,Grid就能办到。
我(作者 Josh Marinacci)在打造网页工具上有很多年的经验。下面是我帮复古角色扮演游戏所设计的工具的截图。 Flexbox 刚推出,我就开始采用。当时,我用嵌套(nested)的水平和垂直方框,以及一些公用程序类别(utility classes),如 scrolling 和 stretching,来建立复杂的布局。
Flexbox 虽然比绝对寻址的 divs 和 float 的做法方便许多,但它还是有一些问题。请看下图中两个面板相邻处的近图,看到左右两边下方底线高低不同吗?
这是另一张截图。工具栏下方是涂鸦板。按照我的设计框架,工具栏应该要一直固定在顶端,但只要往下滚动,工具栏就会消失:
虽然这些问题全都能通过更多定位和 float 技巧来解决,但做出来的结果会很脆弱。每次我想增加新面板,就必须重新帮布局排错,还要找出在重设大小时占用额外空间的 div,而且标记(markup)还很丑。嵌套的水平和垂直框变得极其复杂,而我这个例子还只有两层而已。倘若网页的互动性和功能性更复杂些,版面设计的难度还会更高。 - <div class='hbox'>
- <div class='vbox'>
- <div class='hbox'>header</div>
- <div class='scroll'>
- <div class='sidebar'>sidebar</div>
- </div>
- <div class='footer'>footer</div>
- </div>
- <div class=vbox>
- <div class='hbox'>button button
- spacer label spacer button button </div>
- <div class='center'>main content</div>
- <div class='hbox'>the footer</div>
- </div>
- <div class=vbox>
- <div class=’hbox’>header</div>
- <div class=’scroll’>
- <div class=’sidebar’>sidebar</div>
- </div>
- <div class=’footer’>footer</div>
- </div>
- </div>
复制代码
增加一个维度
Flexbox 最根本的问题是它只有一个维度,所以,Flexbox 很适合做包括工具栏和导航栏等单一维度的应用。但当我想同时对齐水平和垂直的内容时,它就会很麻烦。我需要做真正的二维布局,于是我开始使用 CSS Grid,因为 Grid 是2D 的。
下面是一个以 CSS Grid 建立的类似布局。
请仔细看看底线,对齐得非常工整。我不是在每块面板下增加边线,而是用 grid-gap 来处理框线,一点都不必担心网格线宽度是否一致,一切都水到渠成。
对我来说,CSS Grid 最大的好处是,它能适应环境的变化。我的应用常有侧边面板。我要确定当面板收起或展开时,布局中的东西都能保持正常运作,而且理想上,最好还能省下用 JavaScript 重新计算布局的麻烦。侧边栏包含标头和页脚等多种元素,在变大或变小时,每一个元素都须保持对齐。 靠一个叫 minmax() 的神奇功能,Grid 可以轻松办到这件事。
如果你研究过 CSS Grid,就应该知道可以用 范本来设置列和行的布局。通过 200px 1fr 200px 这个模板,你可以打造出 200px 宽的侧边栏,中间还会有一块内容区块占掉页面中的其他空间。但若收起面板时会如何?现在,就算内容缩小了,栏宽仍会保持在 200px。不过,我们可以用 minmax,以 min-content 关键词作为最大参数值。 - #grid {
- display: grid;
- box-sizing: border-box;
- width: 100vw;
- height: 100vh;
- grid-template-columns:
- [start] minmax(auto, min-content)
- [center]1fr
- [end] minmax(auto,min-content);
- grid-template-rows:
- [header]2em
- [content]1fr
- [footer]2em;
- grid-gap: 1px;
- background-color: black;
- }
复制代码
这样一来,网格的行宽就会变得刚好能容纳任意一个使用了最小宽度的行。因此,只要行中有任何部分(如标头)比其他部分宽,该栏就会自动扩大来包含所有的内容。如果行中内容变窄或完全消失,行宽也会随着调整。基本上,这个做法等于是复制了 Flexbox 的展开/收缩行为,但差别在于它不只影响单一元素,而会使调整的部分与行中所有元素一同协调。这才是真正的 2D 布局。
下面是范例画面中其余的程序代码: - .start {
- grid-column: start;
- }
- .center {
- grid-column: center;
- }
- .end {
- grid-column: end;
- }
- header {
- grid-row: header;
- }
- footer {
- grid-row: footer;
- }
- .sidebar {
- overflow: auto;
- }
复制代码- <div id="grid">
- <header class="start">header</header>
- <header class="center">
- <button id="toggle-left">toggle left</button>
- ...
- </header>
- <header class="end">header</header>
-
- <div class="start sidebar">sidebar</div>
- <div class="center content">the center content</div>
- <div class="end sidebar">
- sidebar<br/>
- ...
- </div>
-
- <footer class="start">left footer</footer>
- <footer class="center">center footer</footer>
- <footer class="end">right footer</footer>
- </div>
复制代码
为了让上方标头处的开关键能遮住侧边栏,我又加上这个程序代码。如果运用现代的 DOM APIs 和箭头函数,我们只需要几行函数就可以复制好 JQuery。 - const $ = (selector) => document.querySelector(selector)
- const $ = (selector) => document.querySelectorAll(selector)
- const on = (elem, type, listener) => elem.addEventListener(type,listener)
- on($('#toggle-left'),'click',()=>{
- $(".start").forEach((elem) => elem.classList.toggle('closed'))
- })
- on($('#toggle-right'),'click',()=>{
- $(".end").forEach((elem) => elem.classList.toggle('closed'))
- })
复制代码
另外,请注意:CSS Grid 与 Flexbox 之间并无排斥。我们还是会视情况使用 Flexbox,也就是像工具栏等单一维度的内容。下面是我用标头来做工具栏的样式: - <header class="center">
- <button id="toggle-left">toggle left</button>
- <button>open</button>
- <button>save</button>
- <span class="spacer"></span>
- <span>filename.txt</span>
- <span class="spacer"></span>
- <button>delete</button>
- <button id="toggle-right">toggle right</button>
- </header>
- header {
- background-color: #ccc;
- display: flex;
- flex-direction: row;
- }
- .spacer {
- flex: 1;
- }
复制代码
spacer 类别会使元素占掉所有的空间。但若在按钮中使用两个 spacer,工具栏便可随情况适时放大和缩小,而且名称还能一直在中间显示。这样就会很像原生工具栏。
CSS Grid 支持二维的复杂度,非常适用于设计交互式应用。标记的语意可以保留,面板和工具栏也能整齐排列,grid-gap 会自动控制边框。它不需要用到任何一个 JavaScript 码,就能细致地调整布局,还能让我们控制平行和垂直的线。而且,这些全都不需要用到复杂的 CSS 框架。
Jen Simmons 的全新 YouTube 频道已经上线—— Layout Land,欢迎关注。如果你是 Web 应用或交互式网站的开发人员,CSS Grid 能让你工作起来如虎添翼!
|