网站建设之用CSS网格解决棘手的布局问题

网站建设时布局设计需要创新,然后就往往会遇到排版很不好做的一些设计,实现起来难度很大。

这篇文章是对具有独特布局和一组约束的特定组件的案例研究。构建适用于大量需求以及未知内容的布局,需要应用横向思维和大量问题解决方案来找到正确的解决方案。

一个这样的组件看起来像这样:

网站建设之用CSS网格解决棘手的布局问题

它由一个图像或视频,一个水平和垂直居中的大标题和一个文本块组成。在这种情况下,文本块与图像的顶部对齐,但如果由内容作者选择,则可以同等地对齐到图像的底部。

你可能会想,并不是太繁重,而且应该用现代布局方法很简单。但是这个组件带有一组限制:

  • 标题必须在组件内水平居中,并在图像上垂直居中。
  • 文本块必须与图像的顶部或底部对齐,除非文本长于可用空间,在这种情况下,文本块应向上(或如果与底部对齐)向下延伸。
  • 图像尺寸未知,并且不受宽高比的限制 – 换句话说,内容作者可以上传任何尺寸的图像,而不会导致它们被裁剪。
  • 标题和文本块的长度也是未知的。

设计本身由一个24列网格和组件的多个变体组成 – 图像和文本块可以对齐各种不同的网格列。出于本文的目的,我们暂时不会关注列轴,因为这里的主要焦点是行轴上网格项的对齐。

我创建了相同组件的简化视图,这使我们可以更轻松地查看每个元素的边界框。(想象一下,粉红色轮廓是组件的边界框。)

网站建设之用CSS网格解决棘手的布局问题

让我们假设网格容器和直接子项(我们的网格项)的以下标记 – 为了本文的目的,我们将忽略这些元素中的每一个,这样我们就可以专注于布局:

<article class="grid">
	<div class="grid__heading">Heading</div>
	<figure class="grid__image"></figure>
	<div class="grid__text"></div>
</article>

我们有以下CSS来定义我们的网格并在列轴上放置项目:

.grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) repeat(24, minmax(0, 60px)) minmax(0, 1fr);
	column-gap: 20px;
}

.grid__heading {
	/* Using a negative line for the grid-column-end value allows us to easily center the position of the heading when we have a large grid */
	grid-column: 5 / -5;
}

.grid__image {
	grid-column: 2 / 16;
}

.grid__text {
	grid-column: span 5 / -1;
}

如果您对我们用于grid-template-columns物业的价值感到好奇。

现在我们需要定义网格行。我最初的想法是我们可以grid-template-rows如下定义属性:

.grid {
	grid-template-rows: 1fr auto 1fr;
}

这给了我们一个中心行,其中auto包含我们标题的值(因为我们不知道这将是多长时间,我们希望轨道增长以适应内容),以及两个周围的行1fr。这两个外行将占用可用空间的相等比例。如果我们设置row-gap: 40px(使用速记gap这里grid-row-gapgrid-column-gap),那么我们将得到上方和标题下方一个40像素排水沟,保持它与文本块之间的空间。

网站建设之用CSS网格解决棘手的布局问题

我们也可以在Grid中使用flex对齐属性,这在这里非常有用。我正在使用align-items: center水平居中我们的网格项目。我们需要这样做的原因尚不清楚,但如果我们的文本内容比可用空间长,我们很快就会发现它变得更有用。

.grid {
	/* ...Other grid code */
	grid-template-rows: 1fr auto 1fr;
	gap: 40px 20px;
	align-items: center;
}

现在我们可以将网格项放在行轴上:

.grid__heading {
	grid-row: 2;
}

.grid__image {
	/* From the start of the grid to the end */
	grid-row: 1 / -1;
}

.grid__text {
	grid-row: 1;
}

我们所有的项目当前都在它们的网格框中居中对齐,但是如果我align-self: flex-start在文本块上使用那么该项目将对齐到组件的顶部,而标题和图像是集中对齐的(由于align-items: center我们在网格本身)。

.grid__text {
	grid-row: 1;
	align-self: flex-start;
}

到现在为止还挺好。看起来我们已经固定了这种布局。只有一个问题:当文本块比标题和图像顶部之间的空间长时,组件会扩展以容纳它,推动图像并向下(这是我们想要的) – 但遗憾的是底部的网格也在扩展,为我们提供了额外的空间:

网站建设之用CSS网格解决棘手的布局问题

如果我们将多个组件堆叠在一起,那么它们之间的垂直空间将是不均匀的。这不太理想。我们想要的是组件在顶部(文本块的一侧)垂直生长,而不是底部。

网站建设之用CSS网格解决棘手的布局问题
想法解决方案:顶行轨道尺寸增加,但底部没有增加

要解决这个问题,我必须创造性地思考!让我们一步一步地完成解决方案。

首先,我们要将三排轨道尺寸更改为auto

.grid {
	grid-template-rows: auto auto auto;
	gap: 40px 20px;
	align-items: center;
}

然后我们可以在现有行的上方添加一个额外的行,其高度为1fr。使用fr行轴上的单位会发生什么情况可能并不那么明显。在列轴上,我们知道网格的宽度(默认情况下为100%),因此很容易想象1fr填充该空间比例的列轨道。当涉及行轴时,在这种情况下,我们网格的高度将由最高网格项目的高度确定 – 图像 – 当前从第一个网格线到最后一个网格线放置。

.grid {
	grid-template-rows: 1fr auto auto auto;
	gap: 40px 20px;
	align-items: center;
}

我们添加的行实际上是一个隐藏的行 – 0除非我们在其中放置内容,否则它将崩溃。

网站建设之用CSS网格解决棘手的布局问题

在我们查看项目放置之前,我们需要对网格容器做更多的事情。我们将设置row-gap为0并在标题行和其相邻行之间添加40px的轨道。我们也可以删除align-items: center,因为我们不再需要它了。

.grid {
	grid-template-rows: 1fr auto 40px auto 40px auto;
	gap: 0 20px;
}

既然我们的网格有六行,那么可视化将网格项放在行轴上的位置并不容易。有更多的网格线可以跟踪!在这里命名我们的网格线将非常有用。然后我们可以引用这些行名来放置我们的网格项。

.grid {
	grid-template-rows:
		[text-start] 1fr [image-start] auto [text-end]
		40px [heading-start] auto [heading-end] 40px
		auto [image-end];
	gap: 0 20px;
}

.grid__heading {
	grid-row: heading;
}

.grid__image {
	grid-row: image;
}

.grid__text {
	grid-row: text;
	align-self: flex-start;
}

老鹰眼的读者可能会注意到我们的文本块现在跨越两个轨道(从网格线1开始),我们的图像不再从网格线1开始,而是从第2行开始。但是,视觉上没有任何改变。

当我们在文本块中添加更长的文本段落时,我们可以看到这些更改的好处。重要的是, -我们添加膨胀,同时图像和标题仍然是集中相互对准隐藏的行,而不在网格的底部添加额外的空间!

网站建设之用CSS网格解决棘手的布局问题
随着文本内容变长,网格的顶行会扩展

希望现在更明显的是为什么我们需要设置row-gap为0而不是使用额外的轨道作为我们的排水沟:如果我们有40px row-gap,即使文本内容较短,因此在网格的顶部也可以看到它,因此第一个轨道有完全崩溃了。遗憾的是,我们不能gap在单个轴上为属性设置不同的值,否则我们不需要那些额外的行。

对于不同的组件变体 – 文本块低于标题而不是上面 – 我们只需更改grid-template-rows属性以包含隐藏行和结尾而不是开头。

.grid--text-bottom {
	grid-template-rows:
		[media-start] auto 40px
		[heading-start] auto [heading-end]
		40px [text-start] auto [media-end]
		1fr [text-end];
	gap: 0 20px;
}

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/259357.html

(0)
上一篇 2022年5月21日
下一篇 2022年5月21日

相关推荐

发表回复

登录后才能评论