图解CSS:Grid布局案例之构建杂志报刊类布局
一直以来,在 Web 布局中都是以方方正正的矩形向用户展示 UI 效果,而且众多 Web 开发者的意识中也是如此,Web 的布局是无法打破矩形排列的限制!但 Web 技术的发展速度是惊人的,每天都有新的东西出现在我们的眼前。就在这短短的几年时间内,用于 Web 布局的新特特别的多。换句话说,如果今天设计师跟你说:“亲,整一个类似杂志或报刊类的布局吧”!你会爽快的说 OK! 即,使用现在的新特性可以打破矩形框的限制,让你在 Web 上实现像杂志一样的排版布局。
杂志报刊类布局可能会用到的布局特性
虽然我们今天要聊的主题是使用 CSS Grid 来构建杂志报刊类布局,但这并不代表着,实现这类的布局仅用 CSS Grid 特性就可以。简单地说吧,如果我们要实现上图展示的布局效果,CSS Grid 只是给了我们一些独有的优势,那是因为像 Flexbox 、浮动之类的布局只是一维布局,而 CSS Grid 却不同,他是唯一一个支持两维布局的技术,可以同时在水平和垂直方向控制元素盒子的位置。
不过,要让 Web 布局效果更类似于杂志报刊的设计、排版效果,可能还会用到其他一些 CSS 特性,比如:
- 多列布局,可以将同一元素里内容自动分成多栏
- CSS Regions 和 Exclusions,可以很好的解决文本围绕图片的效果,只是目前支持的浏览器非常的少
- CSS Shapes,可以让内容在任何不规则的容器中流动,也可以围绕着任意不规则的图形排列
- CSS Clipping 和 Masking,可以裁剪出不规则的图形或形状,也可以让元素按不规则形状展示
- CSS 书写模式和逻辑属性,可以让文本竖排,也可以按不同的书写(阅读)方式排列
- 首字下沉,是杂志报刊类常见的一种效果,可以使用
initial-letters
轻易的实现首字下沉的效果 - Web Fonts 和可变字体,可以让文本更具艺术效果,视觉更具冲击性
有关于这方面更详细的介绍,可以阅读《构建杂志布局可能会用到的CSS特性》一文。
今天的目标
我们今天的目标很明确,使用 CSS Grid 构建杂志报刊类布局,先从简单的开始,比如说实现下图的布局效果:
然后在进入稍微复杂一点的布局,如下图所示:
注意,实现上面的布局效果,CSS Grid 只是用于布局,其他的一些效果还是需要用到 CSS 的其他特性,比如多列布局,书写模式,首字下沉,Flexbox等。
目标一
目标一是 @JENSIMMONS 的 "实验室布局" 首页顶部的布局效果,相对来说是很简单的。实现该效果所需的 HTML 结构也很简单:
<!-- HTML -->
<div class="grid__container">
<h1>The Experimental Layout Lab</h1>
<h2>of Jen Simmons</h2>
<div class="lists">
<h3>The Conference Talks</h3>
<ol>
<li>
<a href="#">Modern Layouts: Getting Out of Our Ruts</a>
</li>
</ol>
</div>
<ul class="workshop">
<li>
<a href="#">Layout Land Videos</a>
</li>
</ul>
<p class="follow">Follow <a href="#">@jensimmons</a> on Twitter for more as it happens.</p>
</div>
在没有任何 CSS 下,效果很粗矿:
使用浏览器开发者工具的网格审查器,可以很快的分析出该网格的构成要素:
暂且忽略其他的效果,仅聊 Grid。从上图中,我们可以知道这是一个 5 x 5
(五行五列)的网格,如果把网格轨道选项也开启的话,可以知道网格轨道(行和列)的尺寸:
即,使用 grid-tempate-columns
和 grid-template-rows
按上图所示轨道尺寸来定义每个网格轨道的尺寸:
.grid__container {
display: grid;
grid-template-columns: auto 1fr 1fr 1fr 0.5fr;
grid-template-rows: auto 1fr 1fr auto auto;
gap: 1rem;
}
正如上图所示,网格容器创建了,网格轨道尺寸和间距分配好了,接下来要做的是像 叠层布局、Full-Bleed布局 和 交叉布局 教程中介绍的类似,显式使用 grid-area
(或其子属性 grid-column
和 grid-row
)根据网格线数字索引号明确放置网格项目在网格容器中的位置:
CSS 代码如下:
h1 {
grid-column: 1 / 4;
}
h2 {
grid-area: 2 / 3 / 5 / 4;
}
.lists {
grid-area: 4 / 1 / span 2 / 3;
}
.workshop {
grid-area: 3 / 4 / 4 / 6;
}
.follow {
grid-area: 5 / 3 / 6 / 6;
}
网格项目根据网格线名称,把相应的网格项目放置到指定位置。现在缺的只是一些美化方面的样式,比如说字体、字号、颜色等。也就是说,上面的代码,有关于网格方面的布局已完成,后面可能还会添加一些对齐相关的样式,即用于网格轨道、网格项目的对齐属性,如 justify-*
、align-*
、*-content
、*-items
和 *-self
等:
justify-*
:- Flexbox 中主轴对齐(
flex-direction
的方向) - Flexbox 只支持
justify-content
,不支持justify-items
或justify-self
- Grid 中的内联轴(Inline Axis)对齐
- Flexbox 中主轴对齐(
align-*
:- Flexbox 中侧轴对齐
- Grid 中的块轴对齐
*-content
:- Flex项目或网格轨道之间的空间分布
- 没有多余的空间,这些属性什么也不做
*-items
,*-self
:- 网格区域内的对齐方式
- 侧轴上的其他 Flex项目对齐
CSS 网格项目中的对齐方式也是根据“盒模型对齐规范”来执行:
- 运用于“对齐项目到块方向列轴”的对齐属性有:
align-items
和align-self
,其中align-items
运用于网格容器上,align-self
运用于网格项目上 - 运用于“对齐项目到文本方向行轴”的对齐属性有:
justify-items
和justify-self
,其中justify-items
运用于网格容器上,justify-self
运用于网格项目上 - 运用于“对齐项目轨道到块方向的列轴”的对齐属性有:
align-content
,该属性运用于网格容器上 - 运用于“对齐项目轨道到文本方向的行轴”的对齐属性有:
justify-content
,该属性运用于网格容器上
也可以按下面这样的方式来划分:
- 对齐网格项目:
justify-items
和justify-self
沿着行轴对齐网格项目,而align-items
和align-self
沿着列轴对齐网格项目,其中justify-items
和align-items
被运用于网格容器,而justify-self
和align-self
被运用于网格项目 - 对齐网格轨道:
align-content
沿行轴对齐网格轨道,justify-content
沿着列轴对齐网格轨道,它们都被运用于网格容器
例如:
h2 {
justify-self: end
}
为了节约时间,我直接复制了@JENSIMMONS 写的样式。
对于竖排文本,将会使用 CSS 书写模式中的 writing-mode: vertical-lr;
,另外对于列表项,我们采用了一个新特性 @counter-style
(自定义列表项符号风格)。最终看到的效果如下:
如果你希望让文本更具艺术范,还可以使用一些可变字体(艺术字体):
@font-face {
font-family:'Decovar Regular24';
src:url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/209981/Decovar-VF.ttf');
}
h1 {
font-family: "Decovar Regular24", sans-serif;
font-weight: 800;
font-style: italic;
font-variation-settings: "SSTR" 183, "INLN" 648, "TSHR" 460, "TRSB" 312, "TWRM" 638, "SINL" 557, "TOIL" 333, "TINL" 526, "WORM" 523;
}
最终效果如下:
目标二
目标二和目标一相比,多了两个特性,即 首字下沉 和 多列布局。其他的和目标一用到的 CSS 特性是相同的。先上 HTML 结构吧:
<!-- HTML -->
<div class="grid__container">
<h1>Powers of <span>Attraction</span></h1>
<figure>
<img src="" alt="" >
</figure>
<div class="des">
<p>In the modern world...</p>
<p>By Amanda McCrae</p>
</div>
<div class="content">
<p>Lorem ipsum ...</p>
</div>
</div>
从示例效果上来看,该示例只需要构建一个 3 x 2
(两行三列)的网格。和前面示例一样,使用 grid-template-*
和 grid-area
明确放置网格项目,即可达到布局所需的效果:
.grid__container {
display: grid;
grid-template-columns: auto 1fr minmax(auto, 200px);
grid-template-rows: minmax(400px, max-content) auto;
grid-template-areas:
"figure des title"
"content content content";
gap: 1rem;
width: 100vw;
min-height: 100%;
}
figure {
grid-area: figure;
}
h1 {
grid-area: title;
}
.des {
grid-area: des;
}
.content {
grid-area: content;
}
和上一个示例有所差异是,显式在网格容器中使用了grid-template-areas
定义网格区域名称,接着使用 grid-area
指定网格区域名称来放置网格项目。
另外,该示例和目标一不同之处,使用了 initial-letter
做首字下沉的效果,另外使用 column-count
做多列布局:
.content {
column-count: 3;
}
@supports (not (initial-letter: 5)) and (not (-webkit-initial-letter: 5)) {
.content p:nth-of-type(1)::first-letter {
float: left;
font-size: calc(1.15rem * 6.25);
line-height: 0.7;
margin: 17px 12px 0 0;
}
}
@supports (initial-letter: 5) or (-webkit-initial-letter: 5) {
.content p:nth-of-type(1)::first-letter {
initial-letter: 3;
}
}
最终效果如下:
把上面两个示例使用到的相关特性结合在一起,就可以很容易构建出下面这个报纸布局的效果:
注意,该示例来自于 Codenpen 上的 @Olivia Ng 。
通过上面示例给我们带来的思路,可以借助这些 CSS 特性,比如,CSS Grid 和 Flexbox 来完在布局, CSS 书写模式 来改变文本的排列方向,特别是让文本竖排 和 CSS 可变字体 让文本有个性化的渲染 等可以构建出其他的一些 UI效果,比如音乐门标,电商中的优惠卷等:
@Adam Kuhn 在 Codepen 上就用这些特性写了一个这方面的案例: