🏋️
ChristmasだからCSSで雪を降らせよう
はじめに
こんにちは。GENDAエンジニアの西尾です。
この記事は GENDA Advent Calendar 2024 24日目の記事です。
今日はクリスマスイブなので、CSSで雪を降らせました。
TL;DR
- CSSでアニメーションを表現する方法は主に2つある。
- 1つはtransitionを使った仕組みで、あるCSSプロパティの値が変化したとき、その変化をスムーズに行うような仕組みでアニメーションを表現できる。
- もう1つは
@keyframes
とanimationプロパティを利用した仕組みで、時間に沿って要素を継続的に動かす場合に便利である。
CSSで雪が降るよ
.snowflake
クラスを定義してJSを使わずに簡単に雪を降らせられます。
サンプルコード
<style>
/* customizable snowflake styling */
.snowflake {
color: #fff;
font-size: 1em;
font-family: Arial, sans-serif;
text-shadow: 0 0 5px #000;
}
.snowflake,.snowflake .inner{animation-iteration-count:infinite;animation-play-state:running}@keyframes snowflakes-fall{0%{transform:translateY(0)}100%{transform:translateY(110vh)}}@keyframes snowflakes-shake{0%,100%{transform:translateX(0)}50%{transform:translateX(80px)}}.snowflake{position:fixed;top:-10%;z-index:9999;-webkit-user-select:none;user-select:none;cursor:default;animation-name:snowflakes-shake;animation-duration:3s;animation-timing-function:ease-in-out}.snowflake .inner{animation-duration:10s;animation-name:snowflakes-fall;animation-timing-function:linear}.snowflake:nth-of-type(0){left:1%;animation-delay:0s}.snowflake:nth-of-type(0) .inner{animation-delay:0s}.snowflake:first-of-type{left:10%;animation-delay:1s}.snowflake:first-of-type .inner,.snowflake:nth-of-type(8) .inner{animation-delay:1s}.snowflake:nth-of-type(2){left:20%;animation-delay:.5s}.snowflake:nth-of-type(2) .inner,.snowflake:nth-of-type(6) .inner{animation-delay:6s}.snowflake:nth-of-type(3){left:30%;animation-delay:2s}.snowflake:nth-of-type(11) .inner,.snowflake:nth-of-type(3) .inner{animation-delay:4s}.snowflake:nth-of-type(4){left:40%;animation-delay:2s}.snowflake:nth-of-type(10) .inner,.snowflake:nth-of-type(4) .inner{animation-delay:2s}.snowflake:nth-of-type(5){left:50%;animation-delay:3s}.snowflake:nth-of-type(5) .inner{animation-delay:8s}.snowflake:nth-of-type(6){left:60%;animation-delay:2s}.snowflake:nth-of-type(7){left:70%;animation-delay:1s}.snowflake:nth-of-type(7) .inner{animation-delay:2.5s}.snowflake:nth-of-type(8){left:80%;animation-delay:0s}.snowflake:nth-of-type(9){left:90%;animation-delay:1.5s}.snowflake:nth-of-type(9) .inner{animation-delay:3s}.snowflake:nth-of-type(10){left:25%;animation-delay:0s}.snowflake:nth-of-type(11){left:65%;animation-delay:2.5s}
</style>
<div class="snowflakes" aria-hidden="true">
<div class="snowflake">
<div class="inner">❅</div>
</div>
<div class="snowflake">
<div class="inner">❅</div>
</div>
<div class="snowflake">
<div class="inner">❅</div>
</div>
<div class="snowflake">
<div class="inner">❅</div>
</div>
<div class="snowflake">
<div class="inner">❅</div>
</div>
<div class="snowflake">
<div class="inner">❅</div>
</div>
<div class="snowflake">
<div class="inner">❅</div>
</div>
<div class="snowflake">
<div class="inner">❅</div>
</div>
<div class="snowflake">
<div class="inner">❅</div>
</div>
<div class="snowflake">
<div class="inner">❅</div>
</div>
<div class="snowflake">
<div class="inner">❅</div>
</div>
<div class="snowflake">
<div class="inner">❅</div>
</div>
</div>
どうやってんねん
HTMLとCSSだけでアニメーションを実装する方法は主に以下の2つです。
- トランジション(transition) を使う方法
- キーフレームアニメーション(@keyframes + animationプロパティ) を使う方法
transition
トランジションは「あるCSSプロパティの値が変化したとき、その変化をスムーズに行う」という仕組みです。イベントやホバー時など、「状態の変化」を伴う場合に便利です。
以下のような構文で書けます。
.selector {
transition: プロパティ 対象時間 イージング 遅延時間;
}
- プロパティ: width, height, background-color など、トランジションでアニメーションさせるCSSプロパティ
- 対象時間: 変化を何秒かけて行うか (例: 0.3s, 1s)
- イージング: 変化の速度のカーブ (例: linear, ease-in, ease-out, cubic-bezier(...))
- 遅延時間: 変化を何秒待ってから始めるか (オプション)
以下のサンプルでは、マウスのホバー時に0.3秒かけて色が滑らかに変わるようなアニメーションを表現しています。
<style>
/* ボタンのスタイル */
.btn {
background-color: #3498db;
color: #fff;
padding: 10px 20px;
border: none;
cursor: pointer;
/* ボタンの背景色が変化するときに0.3秒かけて変化する */
transition: background-color 0.3s ease-in-out;
}
.btn:hover {
background-color: #2ecc71;
}
</style>
<button class="btn">Hover me!</button>
keyframesアニメーション
一方で、keyframesアニメーションは、「状態の変化」ではなく、「時間に沿って要素を継続的に動かす」ようなアニメーションを作りたいときに便利です。
以下のような形式で、アニメーションの「どの時点(0%〜100%)でどのようにスタイルを変化させるか」を記述します。
@keyframes slide-down {
0% {
transform: translateY(-50px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
以下のサンプルでは"Hello CSS Animation"の文字列が2秒かけて現れるアニメーションを表現しています。
<style>
@keyframes fadein {
0% { opacity: 0; }
100% { opacity: 1; }
}
.box {
animation-name: fadein;
animation-duration: 2s; /* 2秒かけて変化 */
animation-timing-function: ease-in-out;
animation-iteration-count: 1; /* 1回のみ再生 */
animation-fill-mode: forwards; /* 終了後、最終状態を保持 */
}
</style>
<div class="box">Hello CSS Animation</div>
CSSのアニメーションプロパティは他にも色々あります。
プロパティ | 説明 | 例 |
---|---|---|
animation-name |
@keyframes で定義したアニメーション名を指定 |
animation-name: slide-down; |
animation-duration |
アニメーションの所要時間 | animation-duration: 2s; |
animation-timing-function |
アニメーション速度のカーブ (ease , linear , ease-in , ease-out , cubic-bezier など) |
animation-timing-function: ease; |
animation-iteration-count |
アニメーションを何回繰り返すか (数値または infinite ) |
animation-iteration-count: 3; |
animation-delay |
アニメーション開始を遅らせる時間 | animation-delay: 1s; |
animation-fill-mode |
アニメーション終了後、どの状態を維持するか (none , forwards , backwards , both ) |
animation-fill-mode: forwards; |
animation-direction |
再生方向 (normal , reverse , alternate など) |
animation-direction: alternate; |
animation-play-state |
アニメーションの再生・一時停止を制御 (running / paused ) |
animation-play-state: running; |
今回の雪を降らせたアニメーションもこちらの@keyframe
とanimationプロパティを利用しています。縦方向の落下のsnowflakes-fall
と左右に揺れるsnowflakes-shake
の2つを組み合わせて雪の感じが表現されていました。
@keyframes snowflakes-fall {
0% { transform: translateY(0); }
100% { transform: translateY(110vh); }
}
@keyframes snowflakes-shake {
0%, 100% { transform: translateX(0); }
50% { transform: translateX(80px); }
}
最後に
CSSでアニメーションを表現する方法を知らなかったので知れて良かった。
Discussion