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

如何解决Etch-a-Sketch网格特定尺寸下右、底边变白问题?

问题分析与解决方案

核心原因

你遇到的问题本质是小数像素的渲染精度问题:当800除以51、44这类数时,得到的是带小数的像素值(比如800/51≈15.686px),浏览器无法渲染真正的小数像素,会进行取整处理。加上flex布局的换行计算误差,导致所有方块的总宽度/高度略小于容器的800px,露出容器的白色背景;Firefox对flex小数像素的处理逻辑更严格,所以错乱更严重。

另外,每个方块的1px边框会进一步加剧尺寸计算的偏差——即使你用了box-sizing:border-box,小数像素加上边框后,总尺寸的累积误差会被放大。

修复方案

改用CSS Grid布局代替flex,它天生就是为网格场景设计的,能自动处理单元格的尺寸分配,彻底避免手动计算像素带来的精度问题。同时调整边框的实现方式,用gap或仅添加部分边框来减少尺寸干扰。

修改后的代码

JavaScript

let container = document.querySelector(".container");

createGrid(16);

function createGrid(gridDimensions) {  
  // 用CSS Grid设置网格布局,自动分配单元格尺寸
  container.style.gridTemplateColumns = `repeat(${gridDimensions}, 1fr)`;
  container.style.gridTemplateRows = `repeat(${gridDimensions}, 1fr)`;

  // 清空容器后创建方块
  container.innerHTML = "";
  for(let row = 1; row <= gridDimensions; row++) {
    for(let column = 1; column <= gridDimensions; column++) {
      let square = document.createElement("div");
      square.id = `square-${row}-${column}`;
      square.className = "squares";
      container.appendChild(square);
    }
  }
  drawOnGrid();
}

function drawOnGrid() {
  let squares = document.querySelectorAll(".squares");
  let hasColorBeenSet = []; // 移到函数内,避免作用域问题

  squares.forEach((square) => {
    let squareDark = document.createElement("div");
    squareDark.className = "square-dark"; // 用CSS类代替内联样式
    square.appendChild(squareDark);

    let squareDarkOpacity = 0;
    square.addEventListener("mouseover", (e) => {
      if(!hasColorBeenSet.includes(square)) {
        hasColorBeenSet.push(square);
        let randomColor = Math.floor(Math.random() * 16777215).toString(16);
        square.style.backgroundColor = `#${randomColor}`;
      }

      squareDarkOpacity = Math.min(squareDarkOpacity + 0.1, 1); // 限制不超过1
      squareDark.style.opacity = squareDarkOpacity;
    });
  });
}

function changeGridSize() {
  let validAnswer = false;
  while(!validAnswer) {
    let userInput = prompt("How big should the grid be? Enter a number between 8 to 100.");
    userInput = Number(userInput);
    userInput = Math.round(userInput);

    if(userInput >= 8 && userInput <= 100) {
      validAnswer = true;
      createGrid(userInput);
    }
  }
}

CSS

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

body {
  height: 100vh;
  background-color: rgb(90, 101, 110);
  display: flex;
  flex-direction: column;
  gap: 50px;
  justify-content: center;
  align-items: center;
}

.container-border {
  border: 1px solid black;
}

.container {
  height: 800px;
  width: 800px;
  background-color: white;
  display: grid; /* 改用Grid布局 */
  gap: 1px; /* 用gap实现方块之间的分隔线,代替每个方块的边框 */
}

.squares {
  background-color: white; /* 初始白色背景 */
}

.square-dark {
  width: 100%;
  height: 100%;
  background-color: black;
  opacity: 0;
}

button {
  font-size: 26px;
  padding: 10px 20px;
  border-radius: 5px;
}

button:hover {
  transition: 0.2s;
  background-color: orange;
  cursor: pointer;
}

HTML

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="./style.css">
    <script src="main.js" defer></script>
    <title>Etch-a-sketch</title>
  </head>
  <body>
    <button onclick="changeGridSize()">Change grid size...</button>
    <div class="container-border">
      <div class="container"></div>
    </div>
  </body>
</html>

关键修改点

  1. CSS Grid替代Flex:用repeat(gridDimensions, 1fr)让每个单元格自动占满容器的1/N,完全避免手动计算小数像素。
  2. 用gap代替边框:gap:1px实现方块之间的黑色分隔线,不需要给每个方块加边框,消除边框带来的尺寸偏差。
  3. 自适应内部元素:.square-dark用100%宽高自适应单元格,不需要传递像素尺寸。
  4. 修复作用域问题:把hasColorBeenSet移到drawOnGrid函数内部,避免多次调用时的变量污染。
  5. 限制不透明度上限:添加Math.min(...,1)防止不透明度超过1。

这样修改后,不管输入任何8-100之间的数值,网格都能完美填满容器,不会出现白边或布局错乱的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 21:35:08