You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何防止Grid尺寸变化?切换边框及调单元格数时保持大小

Etch-a-Sketch 问题解决方案

一、避免切换单元格边框时Grid整体尺寸变化

边框默认会额外占用元素空间,导致Grid整体大小波动。解决核心是让边框尺寸被包含在单元格自身尺寸内,同时用透明边框替代移除边框的操作,保持元素尺寸稳定。

修改方案

  1. 给单元格添加box-sizing: border-box属性,让边框计入元素宽高计算:
.box {
  padding: 0; /* 移除默认padding,避免干扰单元格均分 */
  border: 1px solid black;
  box-sizing: border-box; /* 关键:边框纳入元素尺寸 */
}
  1. 用CSS类切换边框可见性,替代直接修改style:
.grid-border-hidden {
  border-color: transparent; /* 透明边框保持尺寸不变 */
}
  1. 调整JS边框切换逻辑:
gridBorder.addEventListener('click', function () {
  document.querySelectorAll('.box').forEach(box => {
    box.classList.toggle('grid-border-hidden');
  });
});

二、实现“调整尺寸”按钮,保持Grid整体大小不变

需要给Grid设置固定宽高,调整单元格数量时先清空旧单元格,再让新单元格自动均分固定空间。

修改方案

  1. 给Grid设置固定宽高:
#grid {
  display: grid;
  width: 600px; /* 固定宽度 */
  height: 600px; /* 固定高度 */
  border: 1px solid #ccc;
}
  1. 重构makeGrid函数,添加清空逻辑:
function makeGrid(number) {
  grid.innerHTML = ''; // 清空旧单元格
  grid.style.gridTemplateColumns = `repeat(${number}, 1fr)`;
  grid.style.gridTemplateRows = `repeat(${number}, 1fr)`;
  for (let i = 0; i < number * number; i++) {
    let cell = document.createElement('div');
    cell.classList.add('box'); // 用class替代重复id,符合HTML规范
    cell.classList.add('grid-border');
    grid.appendChild(cell);
  }
}
  1. 绑定尺寸按钮事件,添加输入验证:
size.addEventListener('click', function () {
  const newSize = prompt('请输入单元格数量(正整数):');
  if (newSize && !isNaN(newSize) && parseInt(newSize) > 0) {
    makeGrid(parseInt(newSize));
    bindDrawingEvents(); // 重新绑定绘图事件
    // 保持边框状态一致
    const isBorderHidden = document.querySelector('.box')?.classList.contains('grid-border-hidden');
    if (isBorderHidden) {
      document.querySelectorAll('.box').forEach(box => box.classList.add('grid-border-hidden'));
    }
  }
});
  1. 提取绘图/擦除逻辑为独立函数,避免重复绑定:
function bindDrawingEvents() {
  function drawColor(e) {
    if (e.target.classList.contains('box')) {
      e.target.style.backgroundColor = 'black';
    }
  }

  function eraseColor(e) {
    if (e.target.classList.contains('box')) {
      e.target.style.backgroundColor = 'white';
    }
  }

  // 移除旧事件,防止重复触发
  grid.removeEventListener('mouseover', drawColor);
  grid.removeEventListener('mouseover', eraseColor);

  color.addEventListener('click', () => grid.addEventListener('mouseover', drawColor));
  eraser.addEventListener('click', () => grid.addEventListener('mouseover', eraseColor));
}

完整修改后的代码

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Etch-a-Sketch</title>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js" defer></script>
  </head>
  <body>
    <div id="title">
      <h1>Etch-a-Sketch</h1>
    </div>
    <main id="container">
      <div id="menu">
        <button id="size">Canvas Size</button>
        <button id="color">Color</button>
        <button id="eraser">Eraser</button>
        <button id="grid-borders">Grid Borders</button>
      </div>
      <div id="grid"></div>
    </main>
  </body>
</html>

CSS

body {
  height: 100vh;
}

#grid {
  display: grid;
  width: 600px;
  height: 600px;
  border: 1px solid #ccc;
}

.box {
  padding: 0;
  border: 1px solid black;
  box-sizing: border-box;
}

.grid-border-hidden {
  border-color: transparent;
}

#title {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  height: 230px;
}

#container {
  display: flex;
  height: 60%;
  width: 1204px;
  align-items: flex-start;
  justify-content: flex-end;
  gap: 20px;
}

#menu {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

JS

const grid = document.getElementById('grid');
const sizeBtn = document.getElementById('size');
const eraser = document.getElementById('eraser');
const color = document.getElementById('color');
const gridBorder = document.getElementById('grid-borders');

// 创建网格
function makeGrid(number) {
  grid.innerHTML = '';
  grid.style.gridTemplateColumns = `repeat(${number}, 1fr)`;
  grid.style.gridTemplateRows = `repeat(${number}, 1fr)`;
  for (let i = 0; i < number * number; i++) {
    let cell = document.createElement('div');
    cell.classList.add('box');
    grid.appendChild(cell);
  }
}

// 绑定绘图与擦除事件
function bindDrawingEvents() {
  function drawColor(e) {
    if (e.target.classList.contains('box')) {
      e.target.style.backgroundColor = 'black';
    }
  }

  function eraseColor(e) {
    if (e.target.classList.contains('box')) {
      e.target.style.backgroundColor = 'white';
    }
  }

  grid.removeEventListener('mouseover', drawColor);
  grid.removeEventListener('mouseover', eraseColor);

  color.addEventListener('click', () => grid.addEventListener('mouseover', drawColor));
  eraser.addEventListener('click', () => grid.addEventListener('mouseover', eraseColor));
}

// 切换网格边框
gridBorder.addEventListener('click', () => {
  document.querySelectorAll('.box').forEach(box => box.classList.toggle('grid-border-hidden'));
});

// 初始化
makeGrid(16);
bindDrawingEvents();

// 尺寸调整按钮逻辑
sizeBtn.addEventListener('click', () => {
  const newSize = prompt('请输入单元格数量(正整数):');
  if (newSize && !isNaN(newSize) && parseInt(newSize) > 0) {
    makeGrid(parseInt(newSize));
    bindDrawingEvents();
    // 继承之前的边框状态
    const isHidden = document.querySelector('.box')?.classList.contains('grid-border-hidden');
    if (isHidden) {
      document.querySelectorAll('.box').forEach(box => box.classList.add('grid-border-hidden'));
    }
  }
});

内容的提问来源于stack exchange,提问作者MasterBlaster

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 06:15:40