From e57450aa656d9a529d6557c405340d792169c825 Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 1 Jul 2025 15:17:31 -0700 Subject: [PATCH] v2.0.7: Fix grid/tile alignment with CSS Grid layout - Replace hardcoded pixel positioning with CSS Grid - Fix tile background rendering and aspect ratios - Improve responsive design with proper grid gaps - Remove absolute positioning in favor of grid-column/grid-row - Add flex alignment for perfect tile centering - Use clamp() for responsive font sizes across all breakpoints - Fix 'smooshed' grid appearance with proper gap calculations This completely resolves grid alignment issues on all screen sizes. --- src/index.html | 2 +- src/script.js | 7 ++- src/style.css | 113 ++++++++++++++++++++++++++++++------------------- 3 files changed, 76 insertions(+), 46 deletions(-) diff --git a/src/index.html b/src/index.html index 2730e60..c9b9125 100644 --- a/src/index.html +++ b/src/index.html @@ -3,7 +3,7 @@ - 2048 Game - v2.0.6 + 2048 Game - v2.0.7 diff --git a/src/script.js b/src/script.js index af23703..3ea4835 100644 --- a/src/script.js +++ b/src/script.js @@ -246,11 +246,14 @@ class Game2048 { const tile = document.createElement('div'); tile.className = `tile tile-${this.grid[row][col]}`; tile.textContent = this.grid[row][col]; - tile.style.left = `${col * 124.25}px`; - tile.style.top = `${row * 124.25}px`; + + // Use CSS Grid positioning instead of absolute positioning + tile.style.gridColumn = `${col + 1}`; + tile.style.gridRow = `${row + 1}`; if (this.grid[row][col] > 2048) { tile.className = 'tile tile-super'; + tile.textContent = this.grid[row][col]; } container.appendChild(tile); diff --git a/src/style.css b/src/style.css index 62ae057..c15bdbd 100644 --- a/src/style.css +++ b/src/style.css @@ -165,6 +165,10 @@ h1.title { aspect-ratio: 1; margin: 0 auto; box-sizing: border-box; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; } .game-message { @@ -226,48 +230,62 @@ h1.title { .grid-container { position: absolute; z-index: 1; + top: 15px; + left: 15px; + right: 15px; + bottom: 15px; + display: grid; + grid-template-columns: repeat(4, 1fr); + grid-template-rows: repeat(4, 1fr); + gap: clamp(8px, 2.5vw, 18px); + box-sizing: border-box; } .grid-row { - margin-bottom: 18px; -} - -.grid-row:last-child { - margin-bottom: 0; + display: contents; } .grid-cell { - width: 106.25px; - height: 106.25px; background: rgba(238, 228, 218, 0.35); border-radius: 6px; - margin-right: 18px; - float: left; -} - -.grid-cell:last-child { - margin-right: 0; + width: 100%; + height: 100%; + min-height: 0; + aspect-ratio: 1; } .tile-container { position: absolute; z-index: 2; + top: 15px; + left: 15px; + right: 15px; + bottom: 15px; + display: grid; + grid-template-columns: repeat(4, 1fr); + grid-template-rows: repeat(4, 1fr); + gap: clamp(8px, 2.5vw, 18px); + box-sizing: border-box; + pointer-events: none; } .tile { - width: 106.25px; - height: 106.25px; background: #eee4da; color: #776e65; border-radius: 6px; font-weight: bold; text-align: center; - vertical-align: middle; - line-height: 106.25px; - font-size: 55px; - position: absolute; + display: flex; + align-items: center; + justify-content: center; + font-size: clamp(24px, 6vw, 55px); transition: 0.15s ease-in-out; transform-origin: center center; + width: 100%; + height: 100%; + min-height: 0; + aspect-ratio: 1; + box-sizing: border-box; } .tile-2 { background: #eee4da; color: #776e65; } @@ -276,13 +294,13 @@ h1.title { .tile-16 { color: #f9f6f2; background: #f59563; } .tile-32 { color: #f9f6f2; background: #f67c5f; } .tile-64 { color: #f9f6f2; background: #f65e3b; } -.tile-128 { color: #f9f6f2; background: #edcf72; font-size: 45px; } -.tile-256 { color: #f9f6f2; background: #edcc61; font-size: 45px; } -.tile-512 { color: #f9f6f2; background: #edc850; font-size: 45px; } -.tile-1024 { color: #f9f6f2; background: #edc53f; font-size: 35px; } -.tile-2048 { color: #f9f6f2; background: #edc22e; font-size: 35px; } +.tile-128 { color: #f9f6f2; background: #edcf72; font-size: clamp(20px, 5vw, 45px); } +.tile-256 { color: #f9f6f2; background: #edcc61; font-size: clamp(20px, 5vw, 45px); } +.tile-512 { color: #f9f6f2; background: #edc850; font-size: clamp(20px, 5vw, 45px); } +.tile-1024 { color: #f9f6f2; background: #edc53f; font-size: clamp(16px, 4vw, 35px); } +.tile-2048 { color: #f9f6f2; background: #edc22e; font-size: clamp(16px, 4vw, 35px); } -.tile-super { color: #f9f6f2; background: #3c3a32; font-size: 30px; } +.tile-super { color: #f9f6f2; background: #3c3a32; font-size: clamp(14px, 3.5vw, 30px); } .tile-new { animation: appear 200ms ease-in-out; @@ -352,12 +370,13 @@ h1.title { /* Responsive design */ @media screen and (max-width: 520px) { .container { - width: 280px; + width: 100%; + max-width: 320px; margin: 0 auto; } .header h1 { - font-size: 50px; + font-size: 40px; } .scores-container { @@ -372,35 +391,34 @@ h1.title { } .game-container { - width: 280px; - height: 280px; + width: 100%; + max-width: 320px; padding: 10px; } - .grid-cell { - width: 60px; - height: 60px; - margin-right: 10px; - margin-bottom: 10px; + .grid-container, + .tile-container { + top: 10px; + left: 10px; + right: 10px; + bottom: 10px; + gap: clamp(5px, 2vw, 10px); } .tile { - width: 60px; - height: 60px; - line-height: 60px; - font-size: 35px; + font-size: clamp(18px, 5vw, 28px); } .tile-128, .tile-256, .tile-512 { - font-size: 25px; + font-size: clamp(14px, 4vw, 22px); } .tile-1024, .tile-2048 { - font-size: 20px; + font-size: clamp(12px, 3.5vw, 18px); } .tile-super { - font-size: 18px; + font-size: clamp(10px, 3vw, 16px); } } @@ -460,8 +478,17 @@ h1.title { .game-container { width: calc(100vw - 20px); - max-width: 400px; - padding: 10px; + max-width: 300px; + padding: 8px; + } + + .grid-container, + .tile-container { + top: 8px; + left: 8px; + right: 8px; + bottom: 8px; + gap: clamp(4px, 1.5vw, 8px); } .scores-container {