Table of Contents
Learn how to take a simple grid and modify it to take up all available space in the browser. As always, some surprises await!
We have our perfect grid, but it could be a bit more perfect. Our grid currently has a fixed size and is centered on our screen. What would truly make it perfect is if it was fullscreen and took up all of the available space in the browser:
In the following sections, we’ll learn how to take a grid and add the appropriate CSS and JavaScript (yes, JavaScript!) to have our grid take up all available space.
Onwards!
Instead of starting a grid from scratch, we are going to build upon the perfect grid we created earlier. Create a new document and copy/paste the following starter HTML, CSS, and JavaScript into it:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>A Perfect Grid</title>
<style>
#myCanvas {
outline: 2px solid #333;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="500" height="500"> </canvas>
<script>
// Get the canvas context
let myCanvas = document.querySelector("#myCanvas");
const ctx = myCanvas.getContext("2d");
function accountForDPI() {
// Get the current device pixel ratio
const dpr = window.devicePixelRatio || 1;
// Get the canvas size from CSS
const rect = myCanvas.getBoundingClientRect();
// Set the canvas internal dimensions to match DPI
myCanvas.width = rect.width * dpr;
myCanvas.height = rect.height * dpr;
// Scale all canvas operations to account for DPI
ctx.scale(dpr, dpr);
// Reset the canvas display size
myCanvas.style.width = `${rect.width}px`;
myCanvas.style.height = `${rect.height}px`;
}
accountForDPI();
function drawGrid(lineWidth, cellWidth, cellHeight, color) {
// Set line properties
ctx.strokeStyle = color;
ctx.lineWidth = lineWidth;
// Get size
let width = myCanvas.width;
let height = myCanvas.height;
// Draw vertical lines
for (let x = 0; x <= width; x += cellWidth) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, height);
ctx.stroke();
}
// Draw horizontal lines
for (let y = 0; y <= height; y += cellHeight) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(width, y);
ctx.stroke();
}
}
drawGrid(1, 20, 10, "#CCC");
</script>
</body>
</html>
Once you have added this content into a new HTML document, you should see something that looks as follows when you preview it in your browser:
Take a few moments to look at the full code and understand what is going on. The Drawing a Perfect Grid tutorial can help you if you are stuck at any point.
With our starting point all set, we are going to go through the various stages of making our grid take up all available space.
For our first step, let's have our canvas element take up all available space. Let's jump to the CSS, and add the following highlighted lines to our #myCanvas style rule:
#myCanvas {
outline: 2px solid #333;
width: 100vw;
height: 100vh;
}
By using viewport units for the width and height, a value of 100 for both means that we take up all available space across the entirety of our browser window.
Next, because our web pages often have a default margin and padding, we want to override that and set it to 0. Because all of the existing content inside the body style rule isn't necessary for creating a fullscreen canvas, replace it entirely with the following:
body {
margin: 0;
padding: 0;
}
The full CSS at this moment will look as follows:
#myCanvas {
outline: 2px solid #333;
width: 100vw;
height: 100vh;
}
body {
margin: 0;
padding: 0;
}
If we preview our page right now, we will see that our grid properly takes up all available space. Does this mean we are done? Not quite...
While our grid takes up all available space when we load our example, notice what happens when we resize our browser window by making it larger:
Our grid doesn't grow or shrink to accommodate the changing size of our viewport (aka browser window). To fix this, we'll need to add some JavaScript that listens to the window resize event and:
To do all of this, add the following code below all of our existing code inside our script element:
window.addEventListener("resize", () => {
requestAnimationFrame(() => {
myCanvas.style.width = window.innerWidth + "px";
myCanvas.style.height = window.innerHeight + "px";
accountForDPI();
drawGrid(1, 20, 10, "#CCC");
});
});
Once you have added this code at the bottom of your existing code, preview your example again and try resizing your browser window. This time, our grid will properly resize and appear fullscreen:
Now, we can better say that we have our grid set up to appear in fullscreen. Before we wrap all of this up, let's explain what the code we added does.
First, we'll talk about the most interesting two lines:
window.addEventListener("resize", () => {
requestAnimationFrame(() => {
myCanvas.style.width = window.innerWidth + "px";
myCanvas.style.height = window.innerHeight + "px";
accountForDPI();
drawGrid(1, 20, 10, "#CCC");
});
});
In the first line, we listen to the resize event that fires each time our browser window is resized. Because this event has the potential to be very chatty, we need to throttle it so it does not run unnecessarily. That is where the second line with the requestAnimationFrame call comes in.
By using requestAnimationFrame, we ensure the code doesn't immediately execute each time our resize event fires. Instead, requestAnimationFrame schedules the function to run before the next browser repaint. This helps to synchronize the code with the browser's rendering cycle, resulting in fewer unnecessary redraws. This becomes especially important when we expect the browser window to be resized frequently.
Next up are the actual changes we make to our grid:
window.addEventListener("resize", () => {
requestAnimationFrame(() => {
myCanvas.style.width = window.innerWidth + "px";
myCanvas.style.height = window.innerHeight + "px";
accountForDPI();
drawGrid(1, 20, 10, "#CCC");
});
});
Resizing a canvas element requires both updating the visual appearance of the canvas (handled by CSS) and the actual rendered size (handled by the width and height properties directly on the canvas). The first two highlighted lines update the CSS to the resized size of our window. The call to accountForDPI handles setting the rendered size of the canvas.
The last thing we do is call drawGrid, and this ensures we draw the appropriate rows and columns based on how much space is now available.
Our full code after making all of the changes in the above sections will look as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>A Perfect Grid</title>
<style>
#myCanvas {
outline: 2px solid #333;
width: 100vw;
height: 100vh;
}
body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="500" height="500"> </canvas>
<script>
// Get the canvas context
let myCanvas = document.querySelector("#myCanvas");
const ctx = myCanvas.getContext("2d");
function accountForDPI() {
// Get the current device pixel ratio
const dpr = window.devicePixelRatio || 1;
// Get the canvas size from CSS
const rect = myCanvas.getBoundingClientRect();
// Set the canvas internal dimensions to match DPI
myCanvas.width = rect.width * dpr;
myCanvas.height = rect.height * dpr;
// Scale all canvas operations to account for DPI
ctx.scale(dpr, dpr);
// Reset the canvas display size
myCanvas.style.width = `${rect.width}px`;
myCanvas.style.height = `${rect.height}px`;
}
accountForDPI();
function drawGrid(lineWidth, cellWidth, cellHeight, color) {
// Set line properties
ctx.strokeStyle = color;
ctx.lineWidth = lineWidth;
// Get size
let width = myCanvas.width;
let height = myCanvas.height;
// Draw vertical lines
for (let x = 0; x <= width; x += cellWidth) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, height);
ctx.stroke();
}
// Draw horizontal lines
for (let y = 0; y <= height; y += cellHeight) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(width, y);
ctx.stroke();
}
}
drawGrid(1, 20, 10, "#CCC");
window.addEventListener("resize", () => {
requestAnimationFrame(() => {
myCanvas.style.width = window.innerWidth + "px";
myCanvas.style.height = window.innerHeight + "px";
accountForDPI();
drawGrid(1, 20, 10, "#CCC");
});
});
</script>
</body>
</html>
If we hadn't had to worry about resizing our viewport, this entire tutorial could have been just a few lines covering our CSS changes. Because we want to be thorough and account for browser resizes, we added the extra code to (performantly) ensure our canvas takes up all of the available space even as the available space changes.
Just a final word before we wrap up. If you have a question and/or want to be part of a friendly, collaborative community of over 220k other developers like yourself, post on the forums for a quick response!
:: Copyright KIRUPA 2025 //--