前端开发者学堂 - fedev.cn

CSS Grid布局:独立源与网格的层叠顺序

发布于 大漠

最近一直在学习CSS Grid布局相关的知识与使用,虽然目前浏览器对其支持度还并不十分的友好,但我始终相信有一天,浏览器会支持,Web人员也迟早有一天能在自己的布局中使用上CSS Grid。前几天花了几节内容,介绍了CSS Grid布局中的概念测试环境创建单元格合并单元网格线创建网格区域相关的内容。可以说这些内容都是CSS Grid布局最基础和最常用的相关知识,当然,除了这些之外,还会有其他相关的知识,今天要与大家一起探讨的就是有关于CSS Grid Layout中的独立源与网格层叠顺序。

##浏览器渲染原理

Web在浏览器中的渲染是非常复杂的,如果需要整明白浏览器是如何渲染Web页面,那需要对浏览器的渲染原理有足够的了解。如果你不了解浏览器是如何渲染Web页面,个人建议您先阅读Tali GarsielPaul Irish共同为大家写的一篇教程《浏览器的工作原理:新式网络浏览器幕后揭秘》。如果觉得这篇文章实在太长了,看得有点晕呼,你也可以阅读itwriter博客园中发表的一篇读后感《浏览器的渲染原理简介》,帮助你更好的理解。

当然,有关于浏览器渲染原理并不是本文的重点,我们回到要讲的内容上来。先说说CSS Grid布局中的独立源。

##网格布局中的独立源

这里说的独立源,指的并不是源码。而是Web页面中的内容源。大家都知道,在Web中所说的源基本上指的是内容源,但对于我们来说并不关注他的内容是什么,而更关注的是他的HTML结构是什么?说得简单点,源指就是HTML结构。

在Web页面中,HTML结构是按照一种类似于树形结构的方向,根据从上到下,从前到后的顺序,依次出现。那么把这些HTML的标签元素称为源,而这些源的出现的顺序被称为内容流。

或许理论上说,有点晕呼,我们来看一个简单的示例,然后配合一些图片来说明这个问题,或许大家更易理解与接受。一图胜千言万语。

假设我们有一个简单的Web页面,其结构与内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CSS Grid Layout</title>
    <style>
        .wrapper {
            width: 600px;
            margin: 0 auto;
        }
        .box {
            background-color: #444;
            color: #fff;
            padding: 10px;
            margin-bottom: 10px;
        }
        .ad1 {
            background-color: orange;
        }
        .ad2 {
            background-color: #f36;
        }
    </style>
</head>
<body>
    <div class="wrapper">
        <div class="box section1">Section content one</div>
        <div class="box section2">Section content two</div>
        <div class="box section3">Section content three</div>
        <div class="box ad1">Advert!</div>
        <div class="box ad2">Another lovely advert!</div>
    </div>
</body>
</html>

这是一个非常简单的HTML页面的结构。针对上面的HTML结构,画出其对应的DOM树,从而更好的理解其内容流(也就是源)在Web页面中出现的先后顺序:

HTML DOM树

上图清晰的表述了HTML结构出现的顺序。在不对文档流做特殊处理情况下,其出现的顺序是从上到下,从前到后,如下图所示:

HTML默认文档流

如果你需要实现下图的效果:

改变HTML默认文档流

对比两者的效果,如果不修改HTML结构的情况之下,仅通过以前的CSS技术来实现上图的效果,对于Web前端人员来说是件痛苦的事情(Flexbox个性order值,或许能达到)。但在CSS Grid Layout中,这并不是问题。这也是今天要说的一个点:CSS Grid Layout中的独立源

通过前面几篇文章大家应该了解到,在CSS Grid Layout中,HTML文档流(<body>中的元素)出现的顺序并不重要,因为它一点不关注HTML中的结构顺序是什么?只要元素标签的父元素被声明了是网格容器:

.wrapper {
  display: grid;
  grid-template-columns: 600px;
  grid-template-rows: auto ;
}

那么就可以根据设计的需要,通过grid-columngrid-row来决定.wrapper内的子元素(也就是网格单元格,或网格区域)放在哪?就好比这个示例中所示一样,在.wrapper容器内有五个div元素,其中前三个div放置的是页面关键内容(页面中更重要的信息),后面两个div是用来放置广告内容(用户并不太关注)。而实际设计中,在一些平台中,希望广告内容穿插在其他内容中,这个时候Grid的魅力就展示出来了:

.wrapper {
  width: 600px;
  margin: 20px auto;
  display: grid;
  grid-template-columns: 600px;
  grid-template-rows: auto ;
}
.section1 {
  grid-row: 1 / 2;
}
.section2 {
  grid-row: 3 / 4;
}
.section3 {
  grid-row: 5 / 6;
}
.ad1 {
  grid-row: 2 / 3;
}
.ad2 {
  grid-row: 4 / 5;
}

效果如下:

改变HTML默认文档流

在线案例

试想一下,在移动终端,希望展先展示主内容,然后再展示广告内容,这个时候借助媒体查询就可以完美实现你需要的布局。

其实啰嗦这么多,唯一想说的就是:在CSS Grid Layout中具有独立的源(文档流),实现任何布局效果,完全不需要考虑文档流结构的先后顺序,只需要根据设计需求,调整网格单元格位置

##网格分层

先来看一张滑块制作的示意图:

制作滑块示意图

整个控件有六个部分:

  • 下标(lower-label)
  • 上标(upper-label)
  • 下填充(lower-fill)
  • 上填充(upper-fill)
  • 滑块(thumb)
  • 滑块轨道(track)

Web前端人员拿到这样的一个效果基本上会考虑绝对 定位来布局,通过控制每个元素的宽度和高度来控制每个元素的大小,然后通过确定每个元素的顶端和工边的坐标来实现。那么在CSS Grid Layout中,Web前端人员可以通过Grid中相关的属性来实现。在这里只是想借助此图来说明,在CSS Grid Layout中任何元素都是其中的一个层。

##网格的层叠顺序

上面说过,在CSS Grid Layout中任何元素(单元格或网格区域)都是网格中的一个层,既然在一个网格中有很多个层存在,就会发现层与层之间的层叠。

网格层叠

在CSS Grid Layout中,网格单元格在交叉网格区域会发生重叠,或者在非交叉区域,使用margin负值、position定位也会发生重叠。而当网格单元格发生重叠时,可以通过z-index属性来控制网格单元在Z轴的顺序。

如下面的示例所示,在容器.wrapper中有A~F六个.box。其中.f.d发现重叠,而且.e通过margin-top负值,致使.c~.f都产生了重叠:

#####HTML

<div class="wrapper">
  <div class="box a">A</div>
  <div class="box b">B</div>
  <div class="box c">C</div>
  <div class="box d">D</div>
  <div class="box e">E</div>
  <div class="box f">F</div>
</div>

#####CSS

.wrapper {
  display: grid;
  grid-template-columns: repeat(5, (col) 100px (gutter) 10px) ;
  grid-template-rows: repeat(3, (row) auto (gutter) 10px );
}
.a { 
  grid-column: col / span gutter 2; 
  grid-row: row ;
}
.b { 
  grid-column: col 3 / span gutter 3 ; 
  grid-row: row ;
}
.c { 
  grid-column: col ; 
  grid-row: row 2 ;
}
.d { 
  grid-column: col 2 / span gutter 3 ; 
  grid-row: row 2 ;
}
.e {
  grid-column: col / span gutter 5;
  grid-row: row 3;
  background: rgb(136,36,136);
  margin-top: -30px;
}
.f {
  grid-column: col 3 / span gutter 3;
  grid-row: row 2  ;
  background-color: rgba(49,121,207, 0.5);
}

效果如下:

网格层叠

在线案例

从效果图中可以看出,在CSS Grid Layout中Z轴的顺序(隐式的z-index值)还是会根据文档流中结构出现的先后顺序来决定,越往后出现的元素,其z-index的值越大。从这一点看,其并没有做太多的改变。

在CSS Grid Layout中同样可以通过显式的设置元素的z-index值来改变元素在Z轴的顺序。在上例基础上做一定的修改:

.wrapper {
  display: grid;
  grid-template-columns: repeat(5, (col) 100px (gutter) 10px) ;
  grid-template-rows: repeat(3, (row) auto (gutter) 10px );
}
.a { 
  grid-column: col / span gutter 2; 
  grid-row: row ;
}
.b { 
  grid-column: col 3 / span gutter 3 ; 
  grid-row: row ;
}
.c { 
  grid-column: col ; 
  grid-row: row 2 ;
  z-index: 10;
}
.d { 
  grid-column: col 2 / span gutter 3 ; 
  grid-row: row 2 ;
}
.e {
  grid-column: col / span gutter 5;
  grid-row: row 3;
  background: rgb(136,36,136);
  margin-top: -30px;
  z-index: 5;
}
.f {
  grid-column: col 3 / span gutter 3;
  grid-row: row 2  ;
  background-color: rgba(49,121,207, 0.5);
  z-index:4;
}

效果如下:

网格层叠

在线案例

##总结

在这篇文章中主要介绍了CSS Grid Layout的文档流与元素在Z轴顺序相关的内容。从文章中简单的示例,可以得知,在CSS Grid Layout中,网格内的元素不受文档流渲染顺序所制,可以根据自己需求,独立控制元素在任何位置显示。当网格中单元格或者网格区域发生重叠时,同样可以根据z-index值为控制其在Z轴的层级。