😋😋😋网格布局(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,或者你直接写死你想要的手风琴宽度与宽度也可以的。


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

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

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

相关推荐
Martin -Tang11 分钟前
vite和webpack的区别
前端·webpack·node.js·vite
迷途小码农零零发12 分钟前
解锁微前端的优秀库
前端
王解1 小时前
webpack loader全解析,从入门到精通(10)
前端·webpack·node.js
我不当帕鲁谁当帕鲁1 小时前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段
前端·javascript·arcgis
那一抹阳光多灿烂1 小时前
工程化实战内功修炼测试题
前端·javascript
放逐者-保持本心,方可放逐2 小时前
微信小程序=》基础=》常见问题=》性能总结
前端·微信小程序·小程序·前端框架
毋若成4 小时前
前端三大组件之CSS,三大选择器,游戏网页仿写
前端·css
红中马喽4 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习
Black蜡笔小新5 小时前
网页直播/点播播放器EasyPlayer.js播放器OffscreenCanvas这个特性是否需要特殊的环境和硬件支持
前端·javascript·html
秦jh_6 小时前
【Linux】多线程(概念,控制)
linux·运维·前端