JJ Day 13: Wrapping Up The Drawing Board


Yesterday I laid the groundwork for my Etch-A-Sketch inspired project. I built the grid, got the squares to respond, and made the base mechanics work. Today was the big push to finish it. The plan was simple: add functionality, polish the design, and make it something usable and fun.
Step One: Adding Functionality
For this part, I decided the drawing board needed three buttons. Nothing too fancy, just the essentials.
A start button on the title screen.
A button to change the number of squares.
A button to wipe the board clean.
The start button was the easiest to set up. I just made it trigger a single function that enclosed the canvas, like flicking a switch to get the board running.
The button for changing the number of squares was trickier. At first, my grid was locked at a fixed 16×16. That obviously wasn’t going to cut it. To fix this, I added a variable for the number of squares and then updated the grid-making function to use that variable instead. Finally, I added a limiter that only lets users get up to a 100x100 grid. This was important since we don't want the browser to crash with too many squares.
Now, it didn’t matter if you wanted a 2x2 board or a 99x99 one, it was made instantly.
The wipe button was solved with a neat little CSS trick. When clicked, it simply reset the colour of every square back to white, giving you a fresh blank canvas to doodle on again.
Fixing A Core Problem
Midway through, I noticed a big flaw in my mechanics. If I moved the mouse too quickly, some of the squares didn’t register at all. The lines looked broken, and that was unacceptable for something that’s supposed to be smooth.
After plenty of research, testing and sighs, I came up with a new solution. Instead of assigning an event listener to every single square (which was slow and unreliable), I gave the entire board a single event listener. This single change made the board much more responsive. Yes, it did still leave gaps, but they were much smaller than before.
Step Two: Design
Originally, I thought design would take me maybe an hour. I was wrong. It ate up most of my session.
My design goals were clear:
A title card with a start button that fades away into the canvas when clicked.
Buttons for reset and changing grid size placed neatly in an accessible spot.
A proper Etch-A-Sketch style board so it feels like a finished product, not just boxes floating in space.
This was where things got messy. Every CSS tweak seemed to break some part of my JavaScript, and every JavaScript edit ended up messing up my CSS end. It was like playing coding whack-a-mole for hours. But after pushing through about four hours of debugging and adjustments, I finally got it to look good.
Results
Here's the link to using the drawing board. I named it CanvasGrid!
Here's the source code for the whole webpage:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div class="loadingScreenContainer">
<p class="titleScreen">CanvasGrid</p>
<p class="tagline">Doodle to your heart's content!</p>
<button class="startButton">START</button>
</div>
<div class="gamePlay">
<div class="buttonContainer">
<button class="restart">WIPE AND START OVER</button>
<button class="changeGrid">CHANGE NUMBER OF SQUARES</button>
<input type="number" class="inputValue" max="100">
</div>
<div class="divContainer"></div>
</div>
<style>
.squareDiv {
aspect-ratio: 1/1;
display: flex;
flex: 1 0 calc(6.25% - 2px);
justify-content: center;
align-items: center;
border-width: 5px;
transition: all 0.3s ease;
}
.squareDiv.squareColor {
background-color: rgb(255, 189, 189);
}
.divContainer {
display:flex;
flex-wrap: wrap;
gap: 2px;
}
.inputValue {
display: none;
}
.restart,.changeGrid {
font-size: 20px;
font-family: monospace;
color: rgb(204, 204, 204);
background-color: rgb(33, 0, 63);
border-radius: 10px;
border-width: 5px;
border-color: linear-gradient(rgb(0, 37, 2), rgb(0,99,9));
transition: all 0.3s ease;
}
.buttonContainer {
display: flex;
gap: 2%;
justify-content:center;
transition: all 0.3s ease;
}
.restart:hover,.changeGrid:hover {
scale:1.1;
}
.gamePlay {
display: none;
transition: all 1s ease;
}
body {
height: 100%;
margin: 0;
background-color: rgb(62, 0, 121);
transition: background-color 1s ease;
}
.loadingScreenContainer {
display: flex;
justify-content: center;
align-items: center;
height:100vh;
margin: 0;
flex-direction: column;
transition: all 1s ease;
}
.titleScreen {
color: lightblue;
text-align: center;
font-family: monospace;
font-size: 50px;
margin: 10px 0;
}
.tagline {
font-size: 1rem;
color: rgb(96, 211, 211);
margin: 15px 0;
}
.startButton {
background: linear-gradient(90deg, #a1c4fd, #c2e9fb);
border: none;
padding: 12px 24px;
border-radius: 30px;
font-size: 1.2rem;
color: #333;
transition: transform 0.3s;
font-family: monospace;
}
.startButton:hover {
transform: scale(1.1);
}
</style>
<script>
const gameSite = document.querySelector(".gamePlay");
const titleScreen = document.querySelector(".loadingScreenContainer");
const startBtn = document.querySelector(".startButton");
startBtn.addEventListener("click", () => {
gameSite.style.display = 'block';
document.body.style.background = "rgb(0,0,20";
titleScreen.style.opacity = "0";
setTimeout(() => {
titleScreen.style.display = "none";
}, 1000);
});
const newGrid = document.querySelector(".changeGrid")
const NumberOfSquares = document.querySelector(".inputValue")
newGrid.addEventListener('click', () => {
NumberOfSquares.style.display = 'block';
});
NumberOfSquares.addEventListener('change', () => {
let squareNumber = parseInt(NumberOfSquares.value, 10);
if (!isNaN(squareNumber) && squareNumber > 0 && squareNumber < 101 ) {
gridCreate(squareNumber);
} else { alert("Enter valid number less than 100!")}
});
function gridCreate(squareNumber) {
const divContainer = document.querySelector(".divContainer");
divContainer.innerHTML = "";
for (let i = 0; i < squareNumber * squareNumber; i++) {
const squareDiv = document.createElement("div");
squareDiv.classList.add("squareDiv");
squareDiv.style.flex = `0 0 calc(${(100 / squareNumber)}% - 2px)`;
divContainer.appendChild(squareDiv);
}
document.addEventListener("mousemove", (box) => {
const square = box.target.closest(".squareDiv");
if (square) square.classList.add('squareColor')
})
}
gridCreate(16);
const restartGrid = document.querySelector(".restart")
restartGrid.addEventListener('click', () => {
const squareDivs = document.querySelectorAll('.squareDiv');
squareDivs.forEach(sq => {
sq.classList.remove('squareColor')
})
})
</script>
</body>
</html>
Final Thoughts
With both functionality and design complete, the drawing board felt like a real project. It wasn’t just following instructions anymore. It looked polished, it worked smoothly, and it’s something I’d actually want to show people.
It took way more effort than I had planned, but crossing the finish line was worth it.
I think I'll have to really begin putting effort in the coming days if I want to keep the rate of progress that I have right now. See you tomorrow!
Subscribe to my newsletter
Read articles from Rabee Aman directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
