Mozilla

火狐社区

登录    注册

QQ互联

CSS Grid 是 UI 布局的好帮手

yingliu Mozilla员工 发表于 2018-3-28 16:22:29 | 只看该作者  关闭 [复制链接] 打印 上一主题 下一主题
1 13868
跳转到指定楼层
本帖最后由 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)还很丑。嵌套的水平和垂直框变得极其复杂,而我这个例子还只有两层而已。倘若网页的互动性和功能性更复杂些,版面设计的难度还会更高。
  1. <div class='hbox'>
  2.   <div class='vbox'>
  3.     <div class='hbox'>header</div>
  4.     <div class='scroll'>
  5.       <div class='sidebar'>sidebar</div>
  6.     </div>
  7.     <div class='footer'>footer</div>
  8.   </div>

  9.   <div class=vbox>
  10.     <div class='hbox'>button button
  11.         spacer label spacer button button </div>
  12.     <div class='center'>main content</div>
  13.     <div class='hbox'>the footer</div>
  14.   </div>

  15.   <div class=vbox>
  16.     <div class=’hbox’>header</div>
  17.     <div class=’scroll’>
  18.       <div class=’sidebar’>sidebar</div>
  19.     </div>
  20.     <div class=’footer’>footer</div>
  21.   </div>
  22. </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 关键词作为最大参数值。
  1. #grid {
  2.   display: grid;
  3.   box-sizing: border-box;
  4.   width: 100vw;
  5.   height: 100vh;
  6.   grid-template-columns:
  7.       [start] minmax(auto, min-content)
  8.       [center]1fr
  9.       [end] minmax(auto,min-content);
  10.   grid-template-rows:
  11.       [header]2em
  12.       [content]1fr
  13.       [footer]2em;
  14.   grid-gap: 1px;
  15.   background-color: black;
  16. }
复制代码

这样一来,网格的行宽就会变得刚好能容纳任意一个使用了最小宽度的行。因此,只要行中有任何部分(如标头)比其他部分宽,该栏就会自动扩大来包含所有的内容。如果行中内容变窄或完全消失,行宽也会随着调整。基本上,这个做法等于是复制了 Flexbox 的展开/收缩行为,但差别在于它不只影响单一元素,而会使调整的部分与行中所有元素一同协调。这才是真正的 2D 布局。

下面是范例画面中其余的程序代码:
  1. .start {
  2.   grid-column: start;
  3. }
  4. .center {
  5.   grid-column: center;
  6. }
  7. .end {
  8.   grid-column: end;
  9. }
  10. header {
  11.   grid-row: header;
  12. }
  13. footer {
  14.   grid-row: footer;
  15. }
  16. .sidebar {
  17.   overflow: auto;
  18. }
复制代码
  1. <div id="grid">

  2. <header class="start">header</header>
  3. <header class="center">
  4.   <button id="toggle-left">toggle left</button>
  5. ...
  6. </header>

  7. <header class="end">header</header>


  8. <div class="start sidebar">sidebar</div>
  9. <div class="center content">the center content</div>
  10. <div class="end sidebar">
  11.   sidebar<br/>
  12. ...
  13. </div>

  14. <footer class="start">left footer</footer>
  15. <footer class="center">center footer</footer>
  16. <footer class="end">right footer</footer>

  17. </div>
复制代码

为了让上方标头处的开关键能遮住侧边栏,我又加上这个程序代码。如果运用现代的 DOM APIs 和箭头函数,我们只需要几行函数就可以复制好 JQuery。
  1. const $ = (selector) => document.querySelector(selector)
  2. const $ = (selector) => document.querySelectorAll(selector)
  3. const on = (elem, type, listener) => elem.addEventListener(type,listener)

  4. on($('#toggle-left'),'click',()=>{
  5.   $(".start").forEach((elem) => elem.classList.toggle('closed'))
  6. })
  7. on($('#toggle-right'),'click',()=>{
  8.   $(".end").forEach((elem) => elem.classList.toggle('closed'))
  9. })
复制代码

另外,请注意:CSS Grid 与 Flexbox 之间并无排斥。我们还是会视情况使用 Flexbox,也就是像工具栏等单一维度的内容。下面是我用标头来做工具栏的样式:
  1. <header class="center">
  2.   <button id="toggle-left">toggle left</button>
  3.   <button>open</button>
  4.   <button>save</button>
  5.   <span class="spacer"></span>
  6.   <span>filename.txt</span>
  7.   <span class="spacer"></span>
  8.   <button>delete</button>
  9.   <button id="toggle-right">toggle right</button>
  10. </header>

  11. header {
  12.   background-color: #ccc;
  13.   display: flex;
  14.   flex-direction: row;
  15. }

  16. .spacer {
  17.   flex: 1;
  18. }
复制代码

spacer 类别会使元素占掉所有的空间。但若在按钮中使用两个 spacer,工具栏便可随情况适时放大和缩小,而且名称还能一直在中间显示。这样就会很像原生工具栏。

你可到 Codepen 试试看,也可混合不同属性使用。

CSS Grid 支持二维的复杂度,非常适用于设计交互式应用。标记的语意可以保留,面板和工具栏也能整齐排列,grid-gap 会自动控制边框。它不需要用到任何一个 JavaScript 码,就能细致地调整布局,还能让我们控制平行和垂直的线。而且,这些全都不需要用到复杂的 CSS 框架。

Jen Simmons 的全新 YouTube 频道已经上线——Layout Land,欢迎关注。如果你是 Web 应用或交互式网站的开发人员,CSS Grid 能让你工作起来如虎添翼!



310971373 狐狸精
沙发
发表于 2018-3-31 09:44:59 | 只看该作者
沙发沙发,开发神器哦
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表