如何检测CSS Grid相邻单元格class实现网格点击变色交互
CSS Grid 网格小游戏通用交互实现方案
核心思路是用事件委托+坐标映射替代逐元素绑定、硬编码相邻关系的冗余写法,不管网格多大都可以复用同一套逻辑,不用单独给每个单元格写事件处理代码。
核心实现逻辑
- 抛弃逐单元格绑定事件的写法,仅在最外层网格容器上绑定1次点击事件,通过事件冒泡捕获所有单元格的点击行为,减少重复代码和内存占用
- 给每个单元格添加
data-row、data-col自定义属性存储自身行列坐标,点击时直接读取坐标,自动计算上下左右相邻单元格的位置,无需硬编码相邻元素ID - 抽离统一的相邻单元格状态检测逻辑,自动过滤超出网格边界的无效位置,按交互规则统一处理类名添加
可直接复用的代码
HTML 结构参考
<!-- 网格外层容器 --> <div class="grid" id="gridContainer"> <!-- 单元格示例,按需设置行列数,需要触发死亡效果的单元格提前加death类即可 --> <div class="cell green" data-row="1" data-col="1"></div> <!-- 初始起始绿色块 --> <div class="cell" data-row="1" data-col="2"></div> <div class="cell death" data-row="1" data-col="3"></div> <!-- 其余单元格可直接用JS循环动态生成,无需手写 --> </div>
JavaScript 逻辑
// 网格配置,根据自己的实际网格尺寸修改即可 const GRID_CONFIG = { rows: 5, // 总行数 cols: 5 // 总列数 } const gridContainer = document.getElementById('gridContainer'); // 仅绑定一次事件,代理所有单元格的点击 gridContainer.addEventListener('click', (e) => { // 仅处理点击到单元格的情况 const currentCell = e.target.closest('.cell'); if (!currentCell) return; // 命中死亡格规则:直接变红 if (currentCell.classList.contains('death')) { currentCell.classList.add('red'); return; } // 读取当前格坐标 const curRow = Number(currentCell.dataset.row); const curCol = Number(currentCell.dataset.col); // 生成所有相邻格坐标,自动过滤超出网格范围的无效坐标 const adjacentList = [ [curRow - 1, curCol], // 上方相邻 [curRow + 1, curCol], // 下方相邻 [curRow, curCol - 1], // 左侧相邻 [curRow, curCol + 1] // 右侧相邻 ].filter(([r, c]) => { return r >= 1 && r <= GRID_CONFIG.rows && c >=1 && c <= GRID_CONFIG.cols }); // 检测是否存在任意相邻绿色格 const hasGreenNeighbor = adjacentList.some(([r, c]) => { const neighbor = gridContainer.querySelector(`.cell[data-row="${r}"][data-col="${c}"]`); return neighbor?.classList.contains('green'); }); // 满足条件则当前格变绿 if (hasGreenNeighbor) { currentCell.classList.add('green'); } })
扩展提示
- 所有单元格可以在页面初始化时通过双层循环动态生成,不需要手写每个单元格的HTML,批量给指定单元格加
death类也只需要维护一个坐标配置数组即可 - 如果需要支持斜向相邻判定,只需要在
adjacentList的初始数组里追加斜向坐标(比如[curRow-1, curCol-1]对应左上)即可,其余逻辑无需改动 - 后续调整网格尺寸、修改判定规则只需要改配置项和对应判定逻辑,不需要逐单元格修改代码
内容的提问来源于stack exchange,提问作者dandomin
相关产品推荐
相关产品推荐

