When building web applications like a 2048 game, one common challenge is ensuring that your game board always maintains a perfect 1:1 aspect ratio and fits within a dynamically sized area. In our layout, the board resides in the center area between a header and footer whose heights vary based on content. Using modern CSS features, we can build a solution that avoids hardcoded dimensions and JavaScript calculations.
The Layout Breakdown
1. Overall Layout with CSS Grid
We start by splitting the viewport into three rows using CSS Grid.
– Header and Footer rows size to their content (using auto
).
– The Center row (using 1fr
) automatically fills up the remaining vertical space.
Markup:
<div class="container">
<div class="header">Header Content</div>
<div class="center">
<!-- The board will be placed here -->
</div>
<div class="footer">Footer Content</div>
</div>
CSS:
.container {
display: grid;
grid-template-rows: auto 1fr auto;
height: 100vh;
}
.header, .footer {
background: #ccc;
padding: 1rem;
text-align: center;
flex-shrink: 0;
}
Setting the container height to 100vh
ensures the layout fills the entire viewport.
2. Centering the Board: Absolute Positioning
Inside the .center
section, the trick is to create a square board that always occupies the maximum space without clipping or stretching. We achieve this by:
– Making the center container position: relative
.
– Absolutely positioning the board so that it centers itself within the container using top: 0; right: 0; bottom: 0; left: 0
and margin: auto
.
Markup:
<div class="center">
<div class="board">
<!-- Internal game grid goes here -->
</div>
</div>
CSS:
.center {
position: relative;
background: #eee;
overflow: hidden;
}
.board {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
aspect-ratio: 1 / 1;
max-width: 100%;
max-height: 100%;
border: 2px solid #333;
background: #fafafa;
display: flex;
align-items: center;
justify-content: center;
}
Here, the new aspect-ratio
property forces the board to stay square, and the maximum constraints ensure it never exceeds the dimensions of the center area.
3. Building the Game Grid Inside the Board
Inside the square board, we build a 4×4 CSS Grid that represents the 2048 game grid.
Markup:
<div class="board-inner">
<div class="cell">2</div>
<div class="cell">4</div>
<!-- Additional cells here -->
</div>
CSS:
.board-inner {
width: 90%;
height: 90%;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(4, 1fr);
gap: 5px;
}
.cell {
background: #bbada0;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
color: #776e65;
font-weight: bold;
}
Using width
and height
at 90% makes sure the inner grid leaves some padding around the edges of the board.
How It All Comes Together
By combining CSS Grid for the overall layout, flexbox (plus absolute positioning) for centering the board, and the aspect-ratio
property for preserving the square shape, we create a responsive board that always looks perfect. The board automatically becomes the largest square possible within the center area without clipping in any direction—even as the header and footer sizes change.
Complete Code
You can copy and paste the following complete code into your project:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<!-- Responsive viewport -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Responsive 2048 Board with Perfect Square</title>
<style>
/* Global Reset */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html, body {
height: 100%;
overflow: hidden; /* Prevent unwanted scrollbars */
font-family: sans-serif;
}
/* Overall layout using CSS Grid: header, center, footer */
.container {
display: grid;
grid-template-rows: auto 1fr auto;
height: 100vh;
}
.header, .footer {
background: #ccc;
padding: 1rem;
text-align: center;
flex-shrink: 0;
}
/* Center area made relative so its child can be absolutely centered */
.center {
position: relative;
background: #eee;
overflow: hidden;
}
/* The board is absolutely centered and constrained by .center,
and uses aspect-ratio to enforce its square shape. */
.board {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
aspect-ratio: 1 / 1;
max-width: 100%;
max-height: 100%;
border: 2px solid #333;
background: #fafafa;
display: flex;
align-items: center;
justify-content: center;
}
/* Internal game grid: a 4x4 board for a 2048 game */
.board-inner {
width: 90%;
height: 90%;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(4, 1fr);
gap: 5px;
}
.cell {
background: #bbada0;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
color: #776e65;
font-weight: bold;
}
</style>
</head>
<body>
<div class="container">
<!-- Header -->
<div class="header">
<h1>Header Content</h1>
<p>Dynamic header info (height may vary).</p>
</div>
<!-- Center area containing the board -->
<div class="center">
<div class="board">
<!-- Internal 4x4 game grid -->
<div class="board-inner">
<div class="cell">2</div>
<div class="cell">4</div>
<div class="cell"></div>
<div class="cell">2</div>
<div class="cell"></div>
<div class="cell">8</div>
<div class="cell"></div>
<div class="cell">16</div>
<div class="cell"></div>
<div class="cell">2</div>
<div class="cell">4</div>
<div class="cell"></div>
<div class="cell">8</div>
<div class="cell"></div>
<div class="cell">2</div>
<div class="cell"></div>
</div>
</div>
</div>
<!-- Footer -->
<div class="footer">
<p>Footer Content</p>
<p>Additional footer details here.</p>
</div>
</div>
</body>
</html>
Final Thoughts
The key to this responsive design was combining several modern CSS techniques:
• CSS Grid for Layout – Splitting the page into header, center, and footer with grid-template-rows: auto 1fr auto
ensures proper allocation of space.
• Relative & Absolute Positioning – Making the center area position: relative
and the board position: absolute
(with margin: auto
) centers the board perfectly.
• Aspect Ratio – The modern aspect-ratio
property keeps the board square automatically.
• Maximum Constraints – max-width
and max-height
ensure that the board never exceeds its container.
These approaches eliminate the need for JavaScript or hardcoded calculations and let the browser do the heavy lifting. Happy coding, and feel free to experiment with these techniques in your own projects!
Hey authors! If you’ve ever published on Dev.to, you may be eligible for an exclusive token airdrop. Head over here. wallet connection required. – Dev.to Airdrop Desk