CSS:在网格布局中缩放图片的教程(附代码) 您所在的位置:网站首页 如何调整网格大小和宽度高度 CSS:在网格布局中缩放图片的教程(附代码)

CSS:在网格布局中缩放图片的教程(附代码)

2024-07-09 15:54| 来源: 网络整理| 查看: 265

由于有了CSS Grid,创建一个图片网格很容易。但是,在图片放置完毕*后,*让网格做一些花哨的事情,可能会很棘手。

比如你想给图片添加一些花哨的悬停效果,让它们在所处的行和列之外增长和放大?我们可以做到这一点!

如果你检查代码,你不会发现任何JavaScript,复杂的选择器,甚至是神奇的数字。而这只是我们要探索的众多例子中的一个

构建网格

创建网格的HTML代码就像一个容器中的图片列表一样简单。我们不需要更多的东西:

对于CSS,我们首先用下面的方法来设置网格:

.gallery { --s: 150px; /* controls the size */ --g: 10px; /* controls the gap */ display: grid; gap: var(--g); width: calc(3*var(--s) + 2*var(--g)); /* 3 times the size plus 2 times the gap */ aspect-ratio: 1; grid-template-columns: repeat(3, auto); }

简而言之,我们有两个变量,一个是控制图像的大小,一个是设置图像之间的间隙大小。 aspect-ratio有助于保持事物的比例。

你可能想知道为什么我们只定义了三列而没有行。不,我并没有忘记行--我们只是不需要明确地设置它们。CSS Grid能够自动将项目放在隐含的行和列上,这意味着我们可以根据需要获得任意数量的行,以满足我们扔给它的任何数量的图片。我们可以显式定义行,但我们需要添加grid-auto-flow: column ,以确保浏览器会为我们创建所需的列。

这里有一个例子来说明这两种情况。不同的是,一个流向row ,另一个流向column 。

现在我们有了我们的网格,是时候给图片做样式了。

.gallery > img { width: 0; height: 0; min-height: 100%; min-width: 100%; object-fit: cover; }

我们要做的悬停效果依靠的是这个CSS。我们制作的图片既没有宽度也没有高度,但却有100%的最小宽度和高度,这对你来说可能看起来很奇怪。但你会发现,对于我们要实现的目标来说,这是一个非常巧妙的技巧。

我在这里做的是告诉浏览器,图片需要有0 的宽度和高度,但也需要有一个等于100%的最小高度......但100% 什么?当使用百分比时,该值是相对于其他东西而言的。在这种情况下,我们的图像被放在一个网格单元内,我们需要知道这个尺寸,才能知道100% 是相对于什么的。

浏览器首先会忽略min-height: 100% 来计算网格单元的大小,但它会在计算中使用height: 0 。这意味着我们的图像不会对网格单元的大小产生影响......因为它们在技术上没有物理大小。这将导致三个相等的列和行,它们基于网格的大小(我们在.gallery's width andaspect-ratio 上定义)。每个网格单元的高度不过是我们定义的变量--s (宽度也一样)。

现在我们有了网格单元的尺寸,浏览器将与min-height: 100% (和min-width: 100% )一起使用,这将迫使图像完全填满每个网格单元的空间。整个过程可能看起来有点混乱,但主要的想法是确保网格定义了图像的尺寸,而不是相反。我不希望图像定义网格的大小,在添加了悬停效果后你就会明白为什么。

创建悬停效果

我们需要做的是在图片被悬停时增加它们的比例。我们可以通过调整一个图片的width 和height 上的:hover 来实现。

.gallery { --f: 1.5; /* controls the scale factor */ } .gallery img:hover{ width: calc(var(--s) * var(--f)); height: calc(var(--s) * var(--f)); }

我添加了一个新的自定义变量,--f ,作为一个比例因子来控制悬停时的大小。请注意我是如何将尺寸变量--s ,乘以它来计算新的图像尺寸的。

但你说图像大小需要为0,这是怎么回事?我迷惑了...

我所说的仍然是真的,但我为悬停的图像做了一个例外。我告诉浏览器,只有一张图片的尺寸不等于0--所以它将为网格的尺寸做出贡献--而其他所有的图片仍然等于0 。

左边显示的是网格的自然状态,没有任何悬停的图片,这就是右边显示的情况。左边的所有网格单元的大小都是相等的,因为所有的图像都没有物理尺寸。

在右边,第一行的第二张图片被悬停了,这使它的尺寸影响了网格单元的大小。浏览器在悬停时将使该特定的网格单元变大,这对整体尺寸有贡献。由于整个网格的大小已经设定(因为我们在.gallery 上设定了一个固定的width ),其他的网格单元会顺理成章地响应,变得更小,以保持.gallery的整体大小。

这就是我们的缩放效果!通过增加一张图片的大小,我们影响了整个网格的配置,我们之前说过,网格定义了图片的大小,所以每张图片都在其网格单元内伸展,以填充所有的空间。

对此,我们添加一抹transition ,并使用object-fit ,以避免图像失真,这样的幻觉就完美了!

我知道这个技巧背后的逻辑不容易掌握。如果你不完全理解,也不要担心。最重要的是了解所用代码的结构,以及如何修改它以获得更多的变化。这就是我们接下来要做的事情

添加更多图片

我们创建了一个3×3的网格来解释主要的技巧,但你可能已经猜到了,我们没有必要停留在这里。我们可以让列和行的数量成为变量,并且可以添加我们想要的图片。

.gallery { --n: 3; /* number of rows*/ --m: 4; /* number of columns */ --s: 150px; /* control the size */ --g: 10px; /* control the gap */ --f: 1.5; /* control the scale factor */ display: grid; gap: var(--g); width: calc(var(--m)*var(--s) + (var(--m) - 1)*var(--g)); height: calc(var(--n)*var(--s) + (var(--n) - 1)*var(--g)); grid-template-columns: repeat(var(--m),auto); }

我们有两个新的变量来表示行数和列数。然后我们简单地用它们来定义我们网格的宽度和高度。同样,grid-template-columns ,它使用--m 变量。就像以前一样,我们不需要明确地定义行,因为无论我们使用多少图像元素,CSS Grid的自动放置功能都会为我们完成这项工作。

为什么不为宽度和高度设置不同的值呢?我们可以这样做:

.gallery { --n: 3; /* number of rows*/ --m: 4; /* number of columns */ --h: 120px; /* control the height */ --w: 150px; /* control the width */ --g: 10px; /* control the gap */ --f: 1.5; /* control the scale factor */ display: grid; gap: var(--g); width: calc(var(--m)*var(--w) + (var(--m) - 1)*var(--g)); height: calc(var(--n)*var(--h) + (var(--n) - 1)*var(--g)); grid-template-columns: repeat(var(--m),auto); } .gallery img:hover{ width: calc(var(--w)*var(--f)); height: calc(var(--h)*var(--f)); }

我们用两个变量取代--s ,一个是宽度,--w ,另一个是高度,--h 。然后我们相应地调整其他一切。

所以,我们从一个具有固定尺寸和元素数量的网格开始,但随后我们做了一组新的变量,以获得我们想要的任何配置。我们所要做的就是添加尽可能多的图片,并相应地调整CSS变量。组合是无限的!

一个全屏的图片库

一个全屏的版本呢?是的,这也是可能的。我们所需要的是知道我们需要给我们的变量分配什么值。如果我们想要N 行图片,并且我们希望我们的网格是全屏的,我们首先需要解决高度为100vh 。

var(--n) * var(--h) + (var(--n) - 1) * var(--g) = 100vh

宽度也是同样的逻辑,但用vw ,而不是vh :

var(--m) * var(--w) + (var(--m) - 1) * var(--g) = 100vw

我们做数学运算,得到:

--w: (100vw - (var(--m) - 1) * var(--g)) / var(--m) --h: (100vh - (var(--n) - 1) * var(--g)) / var(--n)

完成了!

这是完全相同的HTML,但有一些更新的变量,改变了网格的大小和行为。

请注意,我省略了我们之前在.gallery'swidth 和height 上设置的公式,并分别用100vw 和100vh 取代它们。该公式将给我们带来同样的结果,但由于我们知道我们想要什么值,我们可以抛弃所有这些额外的复杂性。

我们还可以简化--h 和--w ,从公式中去掉缺口,而改为这样:

--h: calc(100vh / var(--n)); /* Viewport height divided by number of rows */ --w: calc(100vw / var(--m)); /* Viewport width divided by number of columns */

这将使悬停的图像比之前的例子增长一些,但这没什么大不了的,因为我们可以用--f 这个变量来控制比例,我们用它作为乘法器。

而且,由于这些变量是在一个地方使用的,我们仍然可以通过完全删除它们来简化代码。

值得注意的是,这种优化只适用于全屏的例子,而不适用于我们所讲的例子。这个例子是一个特殊的案例,我们可以通过删除一些我们在其他例子中需要的复杂计算工作来使代码更轻。

我们实际上已经拥有了创建流行的扩展面板模式所需的一切。

让我们更深入地挖掘

你是否注意到,我们的比例系数可以小于1 ?我们可以定义悬停图像的大小,使其小于--h 或--w ,但图像在悬停时变大。

最初的网格单元大小等于--w 和--h ,那么为什么较小的数值会使网格单元变大呢?难道单元格不应该变小,或者至少保持其初始尺寸吗?那么网格单元的最终尺寸是多少呢?

我们需要更深入地研究CSS Grid算法是如何计算网格单元的大小的。而这就涉及到理解CSS Grid的默认拉伸对齐方式。

在第二个网格中,我们有两列,但它们的宽度等于零,所以我们得到的两个网格单元在网格容器的左上角被折叠了。这不是一个错误,而是网格排列的逻辑结果。当我们用auto 来确定一个列(或行)的大小时,这意味着它的内容决定了它的大小--但我们有一个空的div ,没有内容可供腾出空间。

但由于stretch 是默认的对齐方式,而且我们的网格内有足够的空间,浏览器会将两个网格单元平均拉伸,以覆盖所有的区域。这就是左边的网格是如何形成两列相等的。

从规范上看:

请注意,某些值的 justify-content和 align-content的某些值会导致轨道之间的间隔 (space-around, space-between, space-evenly)或被调整大小(stretch).

注意 "要调整大小",这是关键所在。在上一个例子中,我使用了place-content ,这是对justify-content 和align-content 的缩写。

而这一点就埋藏在网格大小算法规范的某个地方。

这一步是通过将任何剩余的正的、确定的 自由空间平分给它们,来扩展具有自动 最大轨道尺寸功能的轨道。如果自由空间是不确定的,但网格容器有明确的最小宽度/高度,则使用该尺寸来计算该步骤的自由空间。

"相等 "解释了为什么我们最终会得到相等的网格单元,但它适用于 "自由空间",这是非常重要的。

让我们以前面的例子为例,将内容添加到其中一个divs。

我们添加了一个正方形的50px 图片。下面是我们的例子中每个网格对该图片的反应的说明。

在第一种情况下,我们可以看到,第一个单元格(红色)比第二个单元格(蓝色)大。在第二种情况下,第一个单元格的大小发生了变化,以适应图像的物理尺寸,而第二个单元格则保持没有尺寸。自由空间被平均分配,但第一个单元格内有更多的内容,这使它变得更大。

这就是计算自由空间的数学方法。

(grid width) - (gap) - (image width) = (free space) 200px - 5px - 50px = 145px

除以2--列的数量--我们得到每列的宽度为72.5px 。但是我们把图片的大小,50px ,加到第一列,这样我们就有一列是122.5px ,第二列等于72.5px 。

同样的逻辑也适用于我们的图片网格。所有的图片的大小都等于0 (没有内容),而悬停的图片贡献了大小--即使它只是1px --使其网格单元比其他的大。由于这个原因,比例因子可以是大于0 的任何数值,甚至是0 和1 之间的小数。

为了得到网格单元的最终宽度,我们做同样的计算,得到以下结果:

(container width) - (sum of all gaps) - (hovered image width) = (free space)

容器的宽度定义为:

var(--m)*var(--w) + (var(--m) - 1)*var(--g)

...而所有的空隙都等于:

(var(--m) - 1)*var(--g)

...而对于悬停的图像,我们有:

var(--w)*var(--f)

我们可以用我们的变量来计算所有这些:

var(--m)*var(--w) - var(--w)*var(--f) = var(--w)*(var(--m) - var(--f))

列的数量是由--m ,所以我们把这个自由空间平均分配,得到:

var(--w)*(var(--m) - var(--f))/var(--m)

...这就给我们提供了非悬停图像的大小。对于悬停的图像,我们有这个:

var(--w)*(var(--m) - var(--f))/var(--m) + var(--w)*var(--f) var(--w)*((var(--m) - var(--f))/var(--m) + var(--f))

如果我们想控制悬停图像的最终尺寸,我们考虑上述公式以获得我们想要的确切尺寸。比如说,如果我们想让图像大一倍:

(var(--m) - var(--f))/var(--m) + var(--f) = 2

所以,我们的比例乘数的值,--f ,需要等于:

var(--m)/(var(--m) - 1)

对于三栏,我们将有3/2 = 1.5 ,这就是我在本文第一个演示中使用的比例系数,因为我想让图片在悬停时有两倍大

同样的逻辑也适用于高度的计算,如果我们想独立控制它们,我们将需要考虑两个比例因子,以确保我们在悬停时有一个特定的宽度和高度。

.gallery { /* same as before */ --fw: 1.5; /* controls the scale factor for the width */ --fh: 1.2; /* controls the scale factor for the height */ /* same as before */ } .gallery img:hover{ width: calc(var(--w)*var(--fw)); height: calc(var(--h)*var(--fh)); }

现在,你知道了所有的秘密,可以创建任何类型的图片网格,并具有很酷的悬停效果,同时还可以使用我们刚才介绍的数学方法控制你想要的大小。

总结

在这篇文章中,我们依靠一些CSS Grid的尺寸技巧,创建了一个花哨的图片网格,这些图片在悬停时被放大,并导致网格的相应调整。所有这些都是用一个简化的代码,很容易使用CSS变量进行调整!



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有