纯CSS实现动态九宫格效果

1
2
3
4
5
6
7
8
9


分享一个实用的css技巧:用纯CSS实现动态九宫格效果。九个元素排列成3×3的网格,当鼠标悬停在某个元素上时,该元素会放大,其他元素自动缩小,保持整个容器大小不变。

这种效果很适合用在图片展示、产品陈列等场景,能够突出当前查看的内容,给用户更好的浏览体验。


核心原理

实现这个效果主要依赖几个CSS特性:

  • CSS Grid 布局:创建九宫格基础结构

  • CSS自定义属性:动态控制行列尺寸

  • :has() 伪类:检测子元素的悬停状态

  • transition:添加平滑的动画过渡


具体实现步骤

html结构

HTML部分很简单,就是一个容器包含九个项目:

<div class="grid-container">
  <div class="grid-item">1</div>
  <div class="grid-item">2</div>
  <div class="grid-item">3</div>
  <div class="grid-item">4</div>
  <div class="grid-item">5</div>
  <div class="grid-item">6</div>
  <div class="grid-item">7</div>
  <div class="grid-item">8</div>
  <div class="grid-item">9</div>
</div>

CSS样式

下面是完整的CSS代码

.grid-container {
  /* 容器尺寸 */
  width: 300px;
  height: 300px;
  
  /* Grid布局 */
  display: grid;
  
  /* 定义行高变量 */
  --row-1: 1fr;
  --row-2: 1fr;
  --row-3: 1fr;
  
  /* 应用行高变量 */
  grid-template-rows: var(--row-1) var(--row-2) var(--row-3);
  
  /* 定义列宽变量 */
  --col-1: 1fr;
  --col-2: 1fr;
  --col-3: 1fr;
  
  /* 应用列宽变量 */
  grid-template-columns: var(--col-1) var(--col-2) var(--col-3);
  
  /* 网格间距 */
  gap: 5px;
  
  /* 背景色 */
  background-color: #f0f0f0;
  
  /* 过渡动画 */
  transition: all 0.3s ease;
}

/* 网格项基础样式 */
.grid-item {
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #4CAF50;
  color: white;
  cursor: pointer;
  border-radius: 4px;
}

/* 交替背景色便于区分 */
.grid-item:nth-child(even) {
  background-color: #2196F3;
}

/* 使用:has()伪类实现悬停效果 */
.grid-container:has(.grid-item:nth-child(1):hover) {
  --row-1: 2fr;
  --col-1: 2fr;
}

.grid-container:has(.grid-item:nth-child(2):hover) {
  --row-1: 2fr;
  --col-2: 2fr;
}

.grid-container:has(.grid-item:nth-child(3):hover) {
  --row-1: 2fr;
  --col-3: 2fr;
}

.grid-container:has(.grid-item:nth-child(4):hover) {
  --row-2: 2fr;
  --col-1: 2fr;
}

.grid-container:has(.grid-item:nth-child(5):hover) {
  --row-2: 2fr;
  --col-2: 2fr;
}

.grid-container:has(.grid-item:nth-child(6):hover) {
  --row-2: 2fr;
  --col-3: 2fr;
}

.grid-container:has(.grid-item:nth-child(7):hover) {
  --row-3: 2fr;
  --col-1: 2fr;
}

.grid-container:has(.grid-item:nth-child(8):hover) {
  --row-3: 2fr;
  --col-2: 2fr;
}

.grid-container:has(.grid-item:nth-child(9):hover) {
  --row-3: 2fr;
  --col-3: 2fr;
}


代码解析

:has() 伪类的作用

:has() 伪类是实现这个效果的关键。它允许我们根据子元素的状态来为父元素设置样式。

比如这段代码:

.grid-container:has(.grid-item:nth-child(1):hover) {
  --row-1: 2fr;
  --col-1: 2fr;
}

意思是:当网格容器中第一个子元素被悬停时,修改容器的CSS变量,让第一行和第一列占据更多空间。

CSS变量的动态更新

我们定义了六个CSS变量来控制三行三列的尺寸:

  • --row-1, --row-2, --row-3 控制行高

  • --col-1, --col-2, --col-3 控制列宽

默认情况下,所有行列都是1fr(平均分配空间)。当某个网格项被悬停时,对应的行和列变为2fr,其他行列自动调整以保持总尺寸不变。

过渡动画

通过transition: all 0.3s ease,当CSS变量值改变时,布局变化会有一个平滑的过渡效果,让交互更加自然。


Sass 简化版:

.box {
/* 定义父元素的框 */
width: 300px;
height: 300px;
/* 使用 grid 布局 */
display: grid;
/* 声明三个自定义属性 表示布局中三行的行高 */
--row1: 1fr;
--row2: 1fr;
--row3: 1fr;
/* 使用三个自定义属性 设置对应的行高 */
grid-template-rows: var(--row1) var(--row2) var(--row3);
/* 声明三个自定义属性 表示布局中三列的列宽 */
--col1: 1fr;
--col2: 1fr;
--col3: 1fr;
/* 使用三个自定义属性 设置对应的列宽 */
grid-template-columns: var(--col1) var(--col2) var(--col3);
/* 设置间距 */
grid-gap: 5px;
background: #f1f1f1;
/* 设置过渡动画效果 */
transition: all 0.25s linear;
}
/* 设置每个单元格的样式 */
.item {
display: flex;
align-items: center;
justify-content: center;
background: #42d392;
color: #fff;
cursor: pointer;
}
/* 设置不同的背景颜色 以作区分 */
.item:nth-child(2n) {
background-color: #1677ff;
}
/* 使用 Sass 提供的 循环语法 */
@for $i from 1 through 9 {
/* 使用 :has() 伪类选择器 结合 nth-child() 和 :hover 设置9个选择器 */
/* 实现当特定的子元素触发hover时 修改父元素中的样式 */
.box:has(.item:nth-child(#{$i}):hover) {
/* 计算当前hover的子元素 所在的行 */
$rowIndex: floor(calc(($i - 1) / 3) + 1);
/* 计算当前hover的子元素 坐在的列 */
$colIndex: ($i - 1) % 3 + 1;
/* 修改对应的自定义属性 从而修改对应的行高和列宽 */
/* 再加上父元素设置的过渡属性 形成了动态九宫格效果 */
--row#{$rowIndex}: 2fr;
--col#{$colIndex}: 2fr;
}
}


浏览器兼容性说明

:has() 伪类是一个相对较新的CSS特性,目前主要在现代浏览器中得到支持:

  • Chrome 105+ ✅

  • Safari 15.4+ ✅

  • Firefox 121+ ✅

  • Edge 105+ ✅

如果需要兼容旧版浏览器,可以考虑使用JavaScript来实现类似效果。


实际应用建议

这个九宫格效果可以应用在很多场景:

  1. 产品展示:电商网站的商品陈列

  2. 图片画廊:照片或艺术作品的展示

  3. 功能导航:仪表盘或控制面板的菜单

  4. 数据可视化:关键指标的展示

你可以根据实际需求调整网格项的样式,比如替换数字为图片、图标或其他内容。


扩展思路

掌握了这个基础效果后,你还可以尝试:

  • 调整放大的比例(不只是2fr)

  • 添加缩放或旋转变换

  • 结合模糊效果突出当前项

  • 实现点击锁定放大的功能

这个纯CSS方案展示了现代CSS的强大能力,不需要JavaScript就能实现复杂的交互效果。

本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!

链接: https://fly63.com/course/33_2159

目录选择