GitHub Pages中404页面CSS倒计时动画显示异常求助
Let’s get this sorted out—your local preview works perfectly but GitHub Pages shows that messy giant black circle? I’ve run into this exact scenario before, and it’s almost always tied to HTML character escaping in your JavaScript innerHTML combined with how GitHub Pages parses content. Here’s how to fix it:
Step 1: Fix HTML Escaping in Your JavaScript
In your original code, you used < and > to escape HTML tags inside document.getElementById("app").innerHTML. While local servers like VS Code Live Server might handle this gracefully, GitHub Pages doesn’t parse these escaped characters back into proper HTML tags. This breaks the SVG structure entirely, leading to that broken black circle.
Replace all < with < and > with > in the innerHTML string—you don’t need to escape these tags when writing HTML directly inside a JavaScript template literal.
Step 2: Structure Your Code for Reliable Deployment
Make sure your CSS is wrapped in a <style> tag in the HTML head, and place your JavaScript at the end of the body (or wrap it in a DOMContentLoaded listener). This ensures your script only runs after all DOM elements are loaded, avoiding race conditions where the script tries to modify elements that haven’t rendered yet.
Full Fixed Code
Here’s the corrected version that will work seamlessly on GitHub Pages:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>404 - Page Not Found</title> <style> body { font-family: sans-serif; display: grid; height: 100vh; place-items: center; margin: 0; background-color: #fff; /* Add contrast for better timer visibility */ } .base-timer { position: relative; width: 300px; height: 300px; } .base-timer__svg { transform: scaleX(-1); } .base-timer__circle { fill: none; stroke: none; } .base-timer__path-elapsed { stroke-width: 7px; stroke: grey; } .base-timer__path-remaining { stroke-width: 7px; stroke-linecap: round; transform: rotate(90deg); transform-origin: center; transition: 1s linear all; fill-rule: nonzero; stroke: currentColor; } .base-timer__path-remaining.green { color: rgb(65, 184, 131); } .base-timer__path-remaining.orange { color: orange; } .base-timer__path-remaining.red { color: red; } .base-timer__label { position: absolute; width: 300px; height: 300px; top: 0; display: flex; align-items: center; justify-content: center; font-size: 48px; color: #333; } </style> </head> <body> <div id="app"></div> <script> const FULL_DASH_ARRAY = 283; const WARNING_THRESHOLD = 10; const ALERT_THRESHOLD = 5; const COLOR_CODES = { info: { color: "green" }, warning: { color: "orange", threshold: WARNING_THRESHOLD }, alert: { color: "red", threshold: ALERT_THRESHOLD } }; const TIME_LIMIT = 15; let timePassed = 0; let timeLeft = TIME_LIMIT; let timerInterval = null; let remainingPathColor = COLOR_CODES.info.color; document.getElementById("app").innerHTML = ` <div class="base-timer"> <svg class="base-timer__svg" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"> <g class="base-timer__circle"> <circle class="base-timer__path-elapsed" cx="50" cy="50" r="45"></circle> <path id="base-timer-path-remaining" stroke-dasharray="283" class="base-timer__path-remaining ${remainingPathColor}" d=" M 50, 50 m -45, 0 a 45,45 0 1,0 90,0 a 45,45 0 1,0 -90,0 "></path> </g> </svg> <span id="base-timer-label" class="base-timer__label">${formatTime(timeLeft)}</span> </div> `; startTimer(); // Trigger redirect when timer finishes function onTimesUp() { clearInterval(timerInterval); window.location.href = "/"; // Redirect to your homepage } function startTimer() { timerInterval = setInterval(() => { timePassed += 1; timeLeft = TIME_LIMIT - timePassed; document.getElementById("base-timer-label").innerHTML = formatTime(timeLeft); setCircleDasharray(); setRemainingPathColor(timeLeft); if (timeLeft === 0) { onTimesUp(); } }, 1000); } function formatTime(time) { const minutes = Math.floor(time / 60); let seconds = time % 60; if (seconds < 10) { seconds = `0${seconds}`; } return `${minutes}:${seconds}`; } function setRemainingPathColor(timeLeft) { const { alert, warning, info } = COLOR_CODES; if (timeLeft <= alert.threshold) { document.getElementById("base-timer-path-remaining").classList.remove(warning.color); document.getElementById("base-timer-path-remaining").classList.add(alert.color); } else if (timeLeft <= warning.threshold) { document.getElementById("base-timer-path-remaining").classList.remove(info.color); document.getElementById("base-timer-path-remaining").classList.add(warning.color); } } function calculateTimeFraction() { const rawTimeFraction = timeLeft / TIME_LIMIT; return rawTimeFraction - (1 / TIME_LIMIT) * (1 - rawTimeFraction); } function setCircleDasharray() { const circleDasharray = `${(calculateTimeFraction() * FULL_DASH_ARRAY).toFixed(0)} 283`; document.getElementById("base-timer-path-remaining").setAttribute("stroke-dasharray", circleDasharray); } </script> </body> </html>
Key Changes Explained
- Removed Unnecessary HTML Escaping: Replaced
</>with actual</>so GitHub Pages parses the SVG correctly. - Structured Code Properly: Wrapped CSS in a
<style>tag and placed JavaScript at the end of the body to ensure DOM readiness. - Added Background Contrast: A white body background ensures the timer is visible against any page context.
- Explicit Redirect: Added
window.location.href = "/"to guarantee the page redirects to your homepage when the timer ends.
After deploying this code to GitHub Pages, your 404 page will display the countdown timer correctly (no giant black circle) and redirect as expected—just like it did locally.
内容的提问来源于stack exchange,提问作者Rohit

