Создание интерактивной праздничной открытки с использованием JavaScript-анимации и DOM-манипуляций.
Что должно происходить:
Создай новый файл otkrytka.html и напиши следующую структуру:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Праздничная открытка</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.card {
width: 600px;
height: 600px;
position: relative;
background-color: #ff4444;
border: 3px solid gold;
border-radius: 20px;
overflow: hidden;
box-shadow: 0 20px 40px rgba(0,0,0,0.3);
}
.card img,
.wish-label,
.wish-container {
opacity: 0;
transition: opacity 0.8s ease;
}
</style>
</head>
<body>
<div class="card">
<div class="title-wrapper">
<h1>С днём рождения!</h1>
<div class="shutter">
<div class="gleam"></div>
</div>
</div>
<img src="https://emojicdn.elk.sh/🌸" alt="Цветы" width="200">
<div class="wish-label">Желаем</div>
<div class="wish-container"></div>
</div>
<script>
// Здесь будет JavaScript-код
</script>
</body>
</html>
.card — контейнер открытки 600×600px с красным фоном.overflow: hidden — прячет элементы, выходящие за границы.opacity: 0 — изображение и пожелания изначально прозрачны.Подключим красивые шрифты с Google Fonts. Добавь в <head> перед </head>:
<link href="https://fonts.googleapis.com/css2?family=Lobster&family=Marck+Script&display=swap" rel="stylesheet">
А теперь добавим стили для всех элементов. Допиши их внутрь тега <style>:
/* Заголовок */
.title-wrapper {
position: relative;
}
.card h1 {
font-family: 'Lobster', cursive;
font-size: 48px;
text-align: center;
color: gold;
text-shadow: 3px 3px 0 #cc8800;
margin-top: 60px;
position: relative;
letter-spacing: 2px;
z-index: 1;
}
/* Изображение */
.card img {
display: block;
margin: 30px auto;
width: 150px;
filter: drop-shadow(0 0 10px rgba(255,215,0,0.5));
}
/* Надпись «Желаем» */
.wish-label {
font-family: 'Marck Script', cursive;
font-size: 36px;
text-align: center;
color: #fffae6;
margin: 20px 0;
}
/* Контейнер для пожеланий */
.wish-container {
min-height: 80px;
text-align: center;
font-family: 'Lobster', cursive;
font-size: 24px;
color: #ffdd99;
position: relative;
}
/* Стиль для каждого пожелания */
.wish-item {
position: absolute;
width: 100%;
text-align: center;
transition: opacity 0.5s ease;
opacity: 0;
}
.wish-item.active {
opacity: 1;
}
Чтобы надпись появлялась слева направо с эффектом «следуя за бликом», мы спрячем её за ширмой, а потом уберём ширму.
Добавь в <style> после стилей для .card h1:
/* Ширма, которая закрывает заголовок */
.shutter {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #ff4444;
z-index: 20;
transition: left 1.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
/* Блик — световое пятно */
.gleam {
position: absolute;
top: 0;
left: -20%;
width: 40%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.7), transparent);
transform: skewX(-20deg);
pointer-events: none;
}
.shutter) полностью закрывает заголовок..gleam) — это световое пятно, которое движется вместе с ширмой.left: 110%), заголовок постепенно открывается.Внутри тега <script> создадим список пожеланий. Ты можешь изменить их на свои!
// Массив с пожеланиями — можешь добавить свои!
const wishes = [
"🌟 Счастья тебе!",
"🎉 Улыбок и радости!",
"⭐ Исполнения мечтаний!",
"🍰 Вкусных тортов!",
"🎁 Море подарков!",
"💖 Любви и добра!"
];
Добавь в <script> следующий код. Он будет управлять всей анимацией:
// Находим все элементы
const img = document.querySelector('.card img');
const shutter = document.querySelector('.shutter');
const wishLabel = document.querySelector('.wish-label');
const wishContainer = document.querySelector('.wish-container');
let wishItems = [];
let currentWishIndex = 0;
let intervalId = null;
// Функция создания элементов пожеланий
function createWishElements() {
wishes.forEach((wish, index) => {
const div = document.createElement('div');
div.className = 'wish-item';
div.textContent = wish;
if (index === 0) div.classList.add('active');
wishContainer.appendChild(div);
wishItems.push(div);
});
}
// Функция переключения пожеланий
function nextWish() {
wishItems[currentWishIndex].classList.remove('active');
currentWishIndex = (currentWishIndex + 1) % wishItems.length;
wishItems[currentWishIndex].classList.add('active');
}
// Запускаем всё через 3 секунды после загрузки
setTimeout(() => {
// 1. Убираем ширму — заголовок открывается слева направо с бликом
shutter.style.left = '110%';
// 2. Через 0.3 секунды появляются цветы
setTimeout(() => {
img.style.opacity = '1';
}, 300);
// 3. Через 1 секунду появляется надпись «Желаем»
setTimeout(() => {
wishLabel.style.opacity = '1';
}, 1000);
// 4. Через 1.5 секунды появляются пожелания и запускается карусель
setTimeout(() => {
createWishElements();
wishContainer.style.opacity = '1';
intervalId = setInterval(nextWish, 2500);
}, 1500);
}, 3000);
3000 мс (3 сек) — ширма начинает уезжать → заголовок открывается с бликом;3300 мс (3.3 сек) — появляются цветы;4000 мс (4 сек) — появляется «Желаем»;4500 мс (4.5 сек) — появляются пожелания и запускается их смена каждые 2500 мс.wishes.Подключи библиотеку в <head>:
<script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1"></script>
И добавь в setTimeout после появления элементов:
canvasConfetti({ particleCount: 150, spread: 70, origin: { y: 0.6 } });
Открой файл в браузере и наслаждайся результатом. Не забудь поделиться открыткой с друзьями!