egg-timer / index.html
snoofm's picture
make it good it's not aligned, choose a nice font and buttons - Initial Deployment
f7eedb8 verified
Raw
History Blame Contribute Delete
11.6 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>7-Minute Countdown Timer</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
body {
margin: 0;
padding: 0;
font-family: 'Poppins', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
color: white;
}
.timer-container {
text-align: center;
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(12px);
border-radius: 24px;
padding: 60px 40px;
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
border: 1px solid rgba(255, 255, 255, 0.25);
max-width: 480px;
width: 90%;
}
h1 {
font-weight: 600;
margin-bottom: 30px;
font-size: 2rem;
}
.timer-display {
font-size: 5rem;
font-weight: 600;
margin: 40px 0;
text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.2);
font-family: 'Poppins', sans-serif;
letter-spacing: 1px;
}
.controls {
margin: 40px 0;
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 15px;
}
button {
background: linear-gradient(45deg, #4facfe 0%, #00f2fe 100%);
border: none;
color: white;
padding: 16px 32px;
border-radius: 12px;
font-size: 1.1rem;
font-weight: 500;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
min-width: 120px;
}
button:hover {
transform: translateY(-3px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.25);
}
button:active {
transform: translateY(1px);
}
button:disabled {
opacity: 0.7;
cursor: not-allowed;
transform: none;
background: linear-gradient(45deg, #bdc3c7, #2c3e50);
}
.time-input {
margin: 30px 0;
display: flex;
justify-content: center;
align-items: center;
gap: 15px;
}
.time-input input {
width: 80px;
padding: 12px;
border-radius: 8px;
border: none;
text-align: center;
font-size: 1.1rem;
background: rgba(255, 255, 255, 0.2);
color: white;
font-weight: 500;
}
.time-input label {
font-weight: 400;
font-size: 1.1rem;
}
.progress-bar {
width: 100%;
height: 10px;
background: rgba(255, 255, 255, 0.2);
border-radius: 5px;
margin: 30px 0;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #43e97b 0%, #38f9d7 100%);
border-radius: 5px;
transition: width 1s linear;
width: 100%;
}
.status {
font-size: 1.3rem;
margin: 30px 0;
font-weight: 400;
}
.alarm-modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.85);
z-index: 1000;
}
.alarm-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: linear-gradient(135deg, #ff4d4d, #f94336);
padding: 50px;
border-radius: 24px;
text-align: center;
box-shadow: 0 25px 70px rgba(0, 0, 0, 0.6);
animation: bounce 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
max-width: 90%;
width: 400px;
}
@keyframes bounce {
0% { transform: translate(-50%, -50%) scale(0.5); }
100% { transform: translate(-50%, -50%) scale(1); }
}
.alarm-content h2 {
font-size: 2.8rem;
margin: 0 0 25px 0;
animation: pulse 1.2s infinite;
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
.dismiss-btn {
background: white;
color: #ff4757;
margin-top: 25px;
padding: 14px 28px;
border-radius: 10px;
font-weight: 600;
}
@media (max-width: 480px) {
.timer-display {
font-size: 3.5rem;
}
.controls {
flex-direction: column;
gap: 12px;
}
button {
width: 100%;
}
}
</style>
</head>
<body>
<div class="timer-container">
<h1>Perfect Egg Timer</h1>
<div class="time-input">
<label for="minutes">Minutes:</label>
<input type="number" id="minutes" min="0" max="59" value="7">
<label for="seconds">Seconds:</label>
<input type="number" id="seconds" min="0" max="59" value="0">
</div>
<div class="timer-display" id="timerDisplay">07:00</div>
<div class="progress-bar">
<div class="progress-fill" id="progressFill"></div>
</div>
<div class="status" id="status">Ready to start</div>
<div class="controls">
<button onclick="startTimer()" id="startBtn">Start</button>
<button onclick="pauseTimer()" id="pauseBtn" disabled>Pause</button>
<button onclick="resetTimer()" id="resetBtn">Reset</button>
<button onclick="setCustomTime()" id="setTimeBtn">Set Time</button>
</div>
</div>
<div class="alarm-modal" id="alarmModal">
<div class="alarm-content">
<h2>⏰ TIME'S UP! ⏰</h2>
<p>Your 7-minute timer has finished!</p>
<button class="dismiss-btn" onclick="dismissAlarm()">Dismiss</button>
</div>
</div>
<script>
let totalTime = 7 * 60; // 7 minutes in seconds
let currentTime = totalTime;
let isRunning = false;
let timerInterval;
let audioContext;
let alarmSound;
// Initialize audio context for alarm sound
function initAudio() {
audioContext = new (window.AudioContext || window.webkitAudioContext)();
}
// Create alarm sound using Web Audio API
function createAlarmSound() {
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.frequency.setValueAtTime(800, audioContext.currentTime);
oscillator.type = 'sine';
gainNode.gain.setValueAtTime(0, audioContext.currentTime);
gainNode.gain.linearRampToValueAtTime(0.3, audioContext.currentTime + 0.1);
gainNode.gain.linearRampToValueAtTime(0, audioContext.currentTime + 0.5);
oscillator.start(audioContext.currentTime);
oscillator.stop(audioContext.currentTime + 0.5);
}
function playAlarm() {
if (!audioContext) initAudio();
// Play multiple beeps
for (let i = 0; i < 6; i++) {
setTimeout(() => createAlarmSound(), i * 600);
}
}
function updateDisplay() {
const minutes = Math.floor(currentTime / 60);
const seconds = currentTime % 60;
document.getElementById('timerDisplay').textContent =
`${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
// Update progress bar
const progress = ((totalTime - currentTime) / totalTime) * 100;
document.getElementById('progressFill').style.width = `${progress}%`;
}
function startTimer() {
if (!audioContext) initAudio();
isRunning = true;
document.getElementById('startBtn').disabled = true;
document.getElementById('pauseBtn').disabled = false;
document.getElementById('status').textContent = 'Timer running...';
timerInterval = setInterval(() => {
if (currentTime > 0) {
currentTime--;
updateDisplay();
} else {
// Timer finished
clearInterval(timerInterval);
isRunning = false;
document.getElementById('startBtn').disabled = false;
document.getElementById('pauseBtn').disabled = true;
document.getElementById('status').textContent = 'Time\'s up!';
// Show alarm modal and play sound
document.getElementById('alarmModal').style.display = 'block';
playAlarm();
}
}, 1000);
}
function pauseTimer() {
clearInterval(timerInterval);
isRunning = false;
document.getElementById('startBtn').disabled = false;
document.getElementById('pauseBtn').disabled = true;
document.getElementById('status').textContent = 'Timer paused';
}
function resetTimer() {
clearInterval(timerInterval);
isRunning = false;
currentTime = totalTime;
updateDisplay();
document.getElementById('startBtn').disabled = false;
document.getElementById('pauseBtn').disabled = true;
document.getElementById('status').textContent = 'Ready to start';
}
function dismissAlarm() {
document.getElementById('alarmModal').style.display = 'none';
resetTimer();
}
// Initialize display
updateDisplay();
// Handle browser tab visibility to continue timer
document.addEventListener('visibilitychange', function() {
if (document.hidden && isRunning) {
// Store the time when tab becomes hidden
localStorage.setItem('timerStartTime', Date.now() - (totalTime - currentTime) * 1000);
} else if (!document.hidden && isRunning) {
// Recalculate time when tab becomes visible
const startTime = localStorage.getItem('timerStartTime');
if (startTime) {
const elapsed = Math.floor((Date.now() - parseInt(startTime)) / 1000);
currentTime = Math.max(0, totalTime - elapsed);
updateDisplay();
}
}
});
</script>
</body>
</html>