😋😋😋网格布局(grid)中的图片缩放-CSS

写在开头

哈喽,各位看官早上好呀。😀

人活着要有生活的目标,一辈子的目标,一段时间的目标,一个阶段的目标,一年的目标,一个月的目标,一个星期的目标,一天一小时一分钟的目标。

------(俄国)列夫·托尔斯泰

离过年已经过去一个多月了,都说人活着要有目标,新的一年小编也给自己定了各种各样的目标,足足十大项,每天忙得不亦乐乎,刷手机短视频时间也减少很多了耶😆,就是不知道到年底能完成几个Flag,尽力而为吧,加油❗

今天给各位大大分享的是一篇 CSS 技巧的文章,主要是网格布局(grid)与 var() 函数相结合应用方面的。

如果你觉得内容还不错,希望您能给小编点个赞呗,谢谢了。😁

九宫格

如上图,这是我们要实现的第一个效果,可能看着挺复杂的,实际我们仅需 HTML+CSS 就能完成啦。

在继续往下看之前,小编希望你对 grid 布局有一定了解哦,不了解其实也没关系,小编标上详细注释,问题不大。😂

先来构建一个九宫格结构:

javascript 复制代码
<div class="box">
  <img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c09cf20b89f64392a5a3348ab2700201~tplv-k3u1fbpfcp-jj:135:90:0:0:q75.avis" />
  <img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9e32595c18264cb19d253e3818780fdf~tplv-k3u1fbpfcp-jj:135:90:0:0:q75.avis" />
  <img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/012f26b7191a479fb170d919c4ffbe5f~tplv-k3u1fbpfcp-jj:135:90:0:0:q75.avis" />
  <img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/da61b167975f4d0f97aeb0efb733f39c~tplv-k3u1fbpfcp-jj:135:90:0:0:q75.avis#?w=2560&h=1440&s=1383522&e=jpg&b=84713e" />
  <img src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/17afe5f019774f85bf7f5463e92e95c4~tplv-k3u1fbpfcp-jj:135:90:0:0:q75.avis#?w=3840&h=2160&s=2406233&e=jpg&b=e59c77" />
  <img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3a5273c488dc46cba4bec37c93897eba~tplv-k3u1fbpfcp-jj:135:90:0:0:q75.avis#?w=1920&h=1080&s=517958&e=jpg&b=78d1e3" />
  <img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/34e76d8eefc14e46be3a78a2f9ff7ee0~tplv-k3u1fbpfcp-jj:135:90:0:0:q75.avis#?w=1920&h=1080&s=959879&e=jpg&b=dac6b7" />
  <img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/abfe0341b25d4db8853f6bb3ace73f40~tplv-k3u1fbpfcp-jj:135:90:0:0:q75.avis" />
  <img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/49951c3ded774e62bbd1ce76b2a24de6~tplv-k3u1fbpfcp-jj:135:90:0:0:q75.avis" />
</div>

样式:

css 复制代码
.box {
  /* 定义一个格子大小 */
  --size: 100px;
  /* 定义格子之间的间隔 */
  --gap: 10px;
  
  display: grid;
  /* 格子之间的间隔 */
  gap: var(--gap);
  /* 容器宽度=3个格子+2个间隔 */
  width: calc(3 * var(--size) + 2 * var(--gap));
  /* 保持格子的宽高比例 */
  aspect-ratio: 1;  
  /* 生成三列 */
  grid-template-columns: repeat(3, auto);
}
.box img {
  width: 0;
  height: 0;
  min-height: 100%;
  min-width: 100%;
  object-fit: cover;
  transition: 0.28s linear;
}

aspect-ratio: 1; 等同于 height: calc(3 * var(--size) + 2 * var(--gap));

grid-template-columns: repeat(3, auto); 等同于 grid-template-columns: auto auto auto;

为什么说要稍微了解一下 grid 布局,就是怕这两个属性有的小伙伴没接触过😄,可以上MDN瞧瞧哈,挺简单基础的东西了。

还有就是子元素图片的样式,这里的图片既没有宽度也没有高度,但是最小宽度和高度都为 100% ,这是一个非常巧妙的技巧,后面我们的图片缩放效果就是依赖这个样式实现。

上面我们仅通过 grid-template-columns: repeat(3, auto); 属性就创造了一个九宫格,可能你会想,这个属性不是仅定义了吗?呢?浏览器怎么知道我们要创建多少行?

这主要是我们并不需要显示的定义行的数量,CSS Grid 能够自动将子元素放置在隐式的行和列上。

Em...这是 Grid 的一个基础规则吧,学了你就懂了。😁

现在我们就拥有一个最简单的九宫格结构了,接下来我们来给它加上缩放的效果。

css 复制代码
.box {
  ...
  /* 定义缩放比例 */
  --scale: 1.2;
  
  ...
}
.box img:hover{
  width:  calc(var(--size) * var(--scale));
  height: calc(var(--size) * var(--scale));
}

没了,就这样😦,我们轻易完成了上面动图的效果,是不是非常简单。但在没有 CSS Grid 之前,要实现这么一个效果,可是要费不少劲来着。

当然,尽管这个过程看起来很简单,代码量也不多,但要深入理解其背后的原理,你需要对 CSS Grid 有足够的了解和基础知识。😗

任意数量

上面,我们成功构建了一个 3x3 的九宫格,但实际情况中,我们可能需要不同尺寸的网格布局,比如 3x44x4 等等,接下来我们就来解决这个问题。

css 复制代码
.box {
  ...
  /* 定义行数量 */
  --row: 3;
  /* 定义列数量 */
  --column: 4;
  
  display: grid;
  gap: var(--gap);
  /* 容器宽度=列数*格子大小 + 格子间隔 */
  width: calc(var(--column) * var(--size) + (var(--column) - 1) * var(--gap));
  /* 容器宽度=行数*格子大小 + 格子间隔 */
  height: calc(var(--row) * var(--size) + (var(--row) - 1) * var(--gap));
  /* 列数根据需求生成 */
  grid-template-columns: repeat(var(--column), auto);
}

我们把 单独抽出来定义成变量,让容器的宽度和高度、列数的生成都通过这些变量来重新计算。

这样我们就能生成任意数量的网格了,对了,记得把子元素的图片补齐噢❗

不定宽高

既然都能任意数量的格子了,那么,格子的宽度与高度我们肯定也希望不是固定的,像上面例子都是 100px 的正方形,能不能搞个长方形呢?😐

当然可以,这不 so easy 的事嘛!

css 复制代码
.box {
  ...
  /* 定义格子宽度 */
  --width: 150px;
  /* 定义格子高度 */
  --height: 120px;
  
  display: grid;
  gap: var(--gap);
  /* 容器宽度=列数*格子大小 + 格子间隔 */
  width: calc(var(--column) * var(--width) + (var(--column) - 1) * var(--gap));
  /* 容器宽度=行数*格子大小 + 格子间隔 */
  height: calc(var(--row) * var(--height) + (var(--row) - 1) * var(--gap));
  grid-template-columns: repeat(var(--column), auto);
}
.box img:hover{
  width:  calc(var(--width) * var(--scale));
  height: calc(var(--height) * var(--scale));
}

一样,我们被格子的宽度和高度单独定义成变量,替换原理的 --size 即可。

全屏

有时,我们希望做一个全屏的照片墙,这又要如何解决呢❓

要做一个全屏的照片墙,意味我们要把 .box 容器铺满一屏,而铺满一屏的容器宽度和高度我们可以直接使用 100vw100vh

css 复制代码
.box {
  ...
  width: 100vw;
  height: 100vh;
  ...
}

但是,这还没完,里面格子的宽度与高度呢?

最开始我们提过,容器宽度=3个格子+2个间隔,其实就是"容器宽度=格子总宽度+格子之间的总间隔"。

也就可以推断出如下:

javascript 复制代码
100vw = var(--column) * var(--width) + (var(--column) - 1) * var(--gap)
100vh = var(--row) * var(--height) + (var(--row) - 1) * var(--gap)

再反推格子的宽度与高度,可以得到:

javascript 复制代码
--width: (100vw - (var(--column) - 1) * var(--gap)) / var(--column) 
--height: (100vh - (var(--row) - 1) * var(--gap)) / var(--row)

最后,把它们带入我们定义的样式变量即可:

css 复制代码
.box {
  ...
  /* 不需要太大的缩放,防止溢出屏幕外 */
  --scale: 1;
  --width: calc((100vw - (var(--column) - 1) * var(--gap)) / var(--column));
  --height: calc((100vh - (var(--row) - 1) * var(--gap)) / var(--row));
  
  display: grid;
  gap: var(--gap);
  width: 100vw;
  height: 100vh;
  ...
  
  /* 防止出行滚动条 */
  box-sizing: border-box;
}
body {
  padding: 0;
  margin: 0;
  display: grid;
  place-content: center;
  box-sizing: border-box;
}

由于我们是全屏铺满,注意要清一下 body 的默认样式,还有 :hover 的时候由于是全屏铺满,可能会导致出现滚动条,需要我们设置 box-sizing: border-box; 样式,并且适当的调整缩放比例(--scale),防止溢出屏幕外。

(效果图就不放了,质量太大,有点卡😅)

手风琴

最后,我们再来做一个手风琴的效果来结尾。

其实也比较简单了,我们仅需要调整相应的样式变量即可。

html 复制代码
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <style>
    body {
      height: 100vh;
      display: grid;
      place-content: center;
    }
    .box {
      /* 注意是0px,不是0 */
      --gap: 0px;
      --scale: 1.5;
      --row: 1;
      --column: 5;
      --width: 100px;
      --height: 300px;

      display: grid;
      gap: var(--gap);
      width: calc(var(--column) * var(--width) + (var(--column) - 1) * var(--gap));
      height: calc(var(--row) * var(--height) + (var(--row) - 1) * var(--gap));
      grid-template-columns: repeat(var(--column), auto);
    }
    .box img {
      width: 0;
      height: 0;
      min-height: 100%;
      min-width: 100%;
      object-fit: cover;
      transition: 0.28s linear;
    }
    .box img:hover{
      width:  calc(var(--width) * var(--scale));
     /* 高度不变 */
      height: var(--height);
    }
  </style>
</head>
<body>
  <div class="box">
    <img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c09cf20b89f64392a5a3348ab2700201~tplv-k3u1fbpfcp-jj:135:90:0:0:q75.avis" />
    <img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9e32595c18264cb19d253e3818780fdf~tplv-k3u1fbpfcp-jj:135:90:0:0:q75.avis" />
    <img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/012f26b7191a479fb170d919c4ffbe5f~tplv-k3u1fbpfcp-jj:135:90:0:0:q75.avis" />
    <img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/da61b167975f4d0f97aeb0efb733f39c~tplv-k3u1fbpfcp-jj:135:90:0:0:q75.avis#?w=2560&h=1440&s=1383522&e=jpg&b=84713e" />
    <img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3a5273c488dc46cba4bec37c93897eba~tplv-k3u1fbpfcp-jj:135:90:0:0:q75.avis#?w=1920&h=1080&s=517958&e=jpg&b=78d1e3" />
  </div>
</body>
</html>

注意,间隔(--gap)是 0px 不是 0,或者你直接写死你想要的手风琴宽度与宽度也可以的。


至此,本篇文章就写完啦,撒花撒花。

希望本文对你有所帮助,如有任何疑问,期待你的留言哦。

老样子,点赞+评论=你会了,收藏=你精通了。

相关推荐
文刀竹肃16 小时前
DVWA -SQL Injection-通关教程-完结
前端·数据库·sql·安全·网络安全·oracle
LYFlied16 小时前
【每日算法】LeetCode 84. 柱状图中最大的矩形
前端·算法·leetcode·面试·职场和发展
Bigger16 小时前
Tauri(21)——窗口缩放后的”失焦惊魂”,游戏控制权丢失了
前端·macos·app
Bigger17 小时前
Tauri (20)——为什么 NSPanel 窗口不能用官方 API 全屏?
前端·macos·app
bug总结17 小时前
前端开发中为什么要使用 URL().origin 提取接口根地址
开发语言·前端·javascript·vue.js·html
一招定胜负18 小时前
网络爬虫(第三部)
前端·javascript·爬虫
Shaneyxs18 小时前
从 0 到 1 实现CloudBase云开发 + 低代码全栈开发活动管理小程序(13)
前端
半山烟雨半山青18 小时前
微信内容emoji表情包编辑器 + vue3 + ts + WrchatEmogi Editor
前端·javascript·vue.js
码途潇潇18 小时前
Vue 事件机制全面解析:原生事件、自定义事件与 DOM 冒泡完全讲透
前端·javascript
zmirror18 小时前
Monorepo 在 Docker 中的构建方案方案
前端