CSSアニメーションを使用して、自動的に色が切り替わる信号機を作ってみました。
以下が実際の制作物です。
コピペ用の実装コード一式とコードの解説をしていきますので、興味がある方はぜひ読んでみてください。
【コピペ用】CSSで作る信号機の実装コード一式
コピペするだけですぐに使えるように、HTMLとCSSのコード一式を用意しました。
<div class="traffic-light">
<div class="light green"></div>
<div class="light yellow"></div>
<div class="light red"></div>
</div>/* 信号機の本体 */
.traffic-light {
width: 240px;
height: 80px;
padding: 0 20px;
display: flex;
align-items: center;
justify-content: space-between;
background-color: #213435;
border-radius: 40px;
}
/* 信号機の光 */
.light {
position: relative;
width: 50px;
height: 50px;
border-radius: 50%;
animation: shadow 9s infinite;
}
/* 信号機の光に被せる要素 */
.light::after {
content: "";
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #0f1616;
animation: light 9s infinite;
}
/* 信号機の光(緑) */
.light.green {
background-color: #2ecc71;
color: #2ecc71;
}
/* 信号機の光(黄色) */
.light.yellow {
background-color: #f1c40f;
color: #f1c40f;
animation-delay: 3s;
}
.light.yellow::after {
animation-delay: 3s;
}
/* 信号機の光(赤) */
.light.red {
background-color: #df3f2e;
color: #df3f2e;
animation-delay: 6s;
}
.light.red::after {
animation-delay: 6s;
}
/* 信号機の光の影の部分のアニメーション */
@keyframes shadow {
0% {
box-shadow: 0 0 20px 4px;
}
32% {
box-shadow: 0 0 20px 4px;
}
33% {
box-shadow: none;
}
100% {
box-shadow: none;
}
}
/* 信号機の光のアニメーション */
@keyframes light {
0% {
background-color: transparent;
}
32% {
background-color: transparent;
}
33% {
background-color: #0f1616;
}
100% {
background-color: #0f1616;
}
}これらをコピペするとすぐに使えますので、自由にご利用ください。
次で実装コードの解説をしていきます。
【解説】CSSで作る信号機の実装コード解説
ここからはコードを理解したい方のために、実装コードの解説をしていきます。
HTML・CSSの順に進めていきますので、よければ参考にしてください。
HTML
まずはHTMLから見ていきます。
<div class="traffic-light">
<div class="light green"></div>
<div class="light yellow"></div>
<div class="light red"></div>
</div>信号機の本体と、3色のライトを用意して完成です。
今回のメインはCSSなので、HTMLの解説は最小限にしています。
CSS
続いてはCSSを見ていきましょう。
/* 信号機の本体 */
.traffic-light {
width: 240px;
height: 80px;
padding: 0 20px;
display: flex;
align-items: center;
justify-content: space-between;
background-color: #213435;
border-radius: 40px;
}
/* 信号機の光 */
.light {
position: relative;
width: 50px;
height: 50px;
border-radius: 50%;
animation: shadow 9s infinite;
}
/* 信号機の光に被せる要素 */
.light::after {
content: "";
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #0f1616;
animation: light 9s infinite;
}
/* 信号機の光(緑) */
.light.green {
background-color: #2ecc71;
color: #2ecc71;
}
/* 信号機の光(黄色) */
.light.yellow {
background-color: #f1c40f;
color: #f1c40f;
animation-delay: 3s;
}
.light.yellow::after {
animation-delay: 3s;
}
/* 信号機の光(赤) */
.light.red {
background-color: #df3f2e;
color: #df3f2e;
animation-delay: 6s;
}
.light.red::after {
animation-delay: 6s;
}
/* 信号機の光の影の部分のアニメーション */
@keyframes shadow {
0% {
box-shadow: 0 0 20px 4px;
}
32% {
box-shadow: 0 0 20px 4px;
}
33% {
box-shadow: none;
}
100% {
box-shadow: none;
}
}
/* 信号機の光のアニメーション */
@keyframes light {
0% {
background-color: transparent;
}
32% {
background-color: transparent;
}
33% {
background-color: #0f1616;
}
100% {
background-color: #0f1616;
}
}CSSは少し長いので、以下の4つに分けて解説していきますね。
- 信号機の本体のスタイル
- 信号機の光のスタイル
- 信号機の影のアニメーション
- 信号機の光のアニメーション
①信号機の本体のスタイル
まずは信号機のボディ部分の装飾を見ていきます。
/* 信号機の本体 */
.traffic-light {
width: 240px;
height: 80px;
padding: 0 20px;
display: flex;
align-items: center;
justify-content: space-between;
background-color: #213435;
border-radius: 40px;
}信号機本体の横幅・縦幅・背景色等はここで指定してください。
ここでは特別なことはしていないので、詳しい解説は省きます。
②信号機の光のスタイル
次は信号機の3色のライト部分の解説です。
/* 信号機の光 */
.light {
position: relative;
width: 50px;
height: 50px;
border-radius: 50%;
animation: shadow 9s infinite;
}
/* 信号機の光に被せる要素 */
.light::after {
content: "";
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #0f1616;
animation: light 9s infinite;
}
/* 信号機の光(緑) */
.light.green {
background-color: #2ecc71;
color: #2ecc71;
}
/* 信号機の光(黄色) */
.light.yellow {
background-color: #f1c40f;
color: #f1c40f;
animation-delay: 3s;
}
.light.yellow::after {
animation-delay: 3s;
}
/* 信号機の光(赤) */
.light.red {
background-color: #df3f2e;
color: #df3f2e;
animation-delay: 6s;
}
.light.red::after {
animation-delay: 6s;
}信号機の光部分は、lightクラスがついたdivタグで表現しています。
lightには3つのライトの共通スタイルを記述し、green, yellow, redクラスでそれぞれの色を指定します。
.light {
position: relative;
width: 50px;
height: 50px;
border-radius: 50%;
animation: shadow 9s infinite;
}
.light.green {
background-color: #2ecc71;
color: #2ecc71;
}
.light.yellow {
background-color: #f1c40f;
color: #f1c40f;
animation-delay: 3s;
}
.light.red {
background-color: #df3f2e;
color: #df3f2e;
animation-delay: 6s;
}この時点では、信号機の3色のライトが表示されている状態です。
しかし一度に1色のみ表示したいので、擬似要素を使用してライトの上に黒色の要素を被せます。
/* 信号機の光に被せる要素 */
.light::after {
content: "";
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #0f1616;
animation: light 9s infinite;
}これでライトの色が一旦見えなくなりましたね。
次で1色ずつ点灯するアニメーションを作成していきます。
③信号機の影のアニメーション
ここでは、信号機のライトが点灯している時の影部分のアニメーションを作成します。
/* 信号機の光の影の部分のアニメーション */
@keyframes shadow {
0% {
box-shadow: 0 0 20px 4px;
}
32% {
box-shadow: 0 0 20px 4px;
}
33% {
box-shadow: none;
}
100% {
box-shadow: none;
}
}アニメーション開始から1/3までは影を表示し、それ以降は影を非表示にしています。
例えば、animationの時間を9秒に設定した場合、3秒間は影が表示され、残りの6秒間は影が消えている状態になります。
その上でanimation-delayをかけることで、3つのライトのアニメーション開始時間をずらしています。
.light {
animation: shadow 9s infinite;
}
.light.yellow {
animation-delay: 3s;
}
.light.red {
animation-delay: 6s;
}これで、一度に1つのライトにのみ影が表示されるようになりました。
同じ要領で、ライトを点灯させるアニメーションを次で作成していきます。
④信号機の光のアニメーション
②の段階で、ライトの上に擬似要素で黒色を被せていましたね。
これを透明にすることで、信号機のライトが表示されるという仕組みにしています。
/* 信号機の光のアニメーション */
@keyframes light {
0% {
background-color: transparent;
}
32% {
background-color: transparent;
}
33% {
background-color: #0f1616;
}
100% {
background-color: #0f1616;
}
}影のアニメーションと同じように、アニメーション開始から1/3の間はライトが表示され、残りの時間は黒色を被せることで非表示にしています。
animation-delayで黄・赤のアニメーション開始時間をずらすことで、一度に一つのライトのみが点灯するようになります。
.light::after {
animation: light 9s infinite;
}
.light.yellow::after {
animation-delay: 3s;
}
.light.red::after {
animation-delay: 6s;
}以上の方法で、信号機を実装することができました。
これで解説は終わりですが、今回の信号機を実装する上で、コード簡略化のために工夫した部分がいくつかあります。
少し難しい内容になりますが、興味がある方は読み進めてください。
【中級者向け】CSSのみで信号機を実装する上でのコード簡略化のポイント
ここでは、コードを簡略化するために工夫した2つのポイントを紹介します。
- 擬似要素を使用し、点灯のアニメーションを1つにまとめる
box-shadowとcolorの性質を利用し、影のアニメーションを1つにまとめる
ポイント①擬似要素を使用し、点灯のアニメーションを1つにまとめる
3色のライトを点灯させるにあたって、lightクラスのbackground-colorにアニメーションをかけるとすると、緑・黄・赤の3つの@keyframesを作成する必要がありますよね。
@keyframes green-light {
0% {
background-color: transparent;
}
32% {
background-color: transparent;
}
33% {
background-color: #2ecc71;
}
100% {
background-color: #2ecc71;
}
}
@keyframes yellow-light {
0% {
background-color: transparent;
}
32% {
background-color: transparent;
}
33% {
background-color: #f1c40f;
}
100% {
background-color: #f1c40f;
}
}
@keyframes red-light {
0% {
background-color: transparent;
}
32% {
background-color: transparent;
}
33% {
background-color: #df3f2e;
}
100% {
background-color: #df3f2e;
}
}このように、background-colorの値が違うだけで他の部分は共通しており、無駄なコードが多いです。
なので、3色分の@keyframesを作るのではなく、1色(黒色)の透明・不透明を切り替える@keyframesを1つ作成することでコードを簡略化しました。
@keyframes light {
0% {
background-color: transparent;
}
32% {
background-color: transparent;
}
33% {
background-color: #0f1616;
}
100% {
background-color: #0f1616;
}
}この方法だと3色分作成する必要はなくなり、最低限のコードでライトの点灯を表現することができます。
ポイント②box-shadowとcolorの性質を利用し、影のアニメーションを1つにまとめる
影のアニメーションを見ると、box-shadowに影の色が指定されていないことに気がつくかと思います。
@keyframes shadow {
0% {
box-shadow: 0 0 20px 4px;
}
32% {
box-shadow: 0 0 20px 4px;
}
33% {
box-shadow: none;
}
100% {
box-shadow: none;
}
}box-shadowには、box-shadow-colorなど色のみを指定するプロパティはないので、ポイント①と同じで3色分の影の@keyframesを作成してしまいがちです。
@keyframes green-shadow {
0% {
box-shadow: 0 0 20px 4px #2ecc71;
}
32% {
box-shadow: 0 0 20px 4px #2ecc71;
}
33% {
box-shadow: none;
}
100% {
box-shadow: none;
}
}
@keyframes yellow-shadow {
0% {
box-shadow: 0 0 20px 4px #f1c40f;
}
32% {
box-shadow: 0 0 20px 4px #f1c40f;
}
33% {
box-shadow: none;
}
100% {
box-shadow: none;
}
}
@keyframes red-shadow {
0% {
box-shadow: 0 0 20px 4px #df3f2e;
}
32% {
box-shadow: 0 0 20px 4px #df3f2e;
}
33% {
box-shadow: none;
}
100% {
box-shadow: none;
}
}これだと影の色以外は共通しているので、できれば1つにまとめたいですよね。
そこで、box-shadowとcolorプロパティの性質を利用します。
その性質とは、box-shadowに色が指定されていない時、影の色はcolorに設定されている色が適用されるというものです。
/* 信号機の光(緑) */
.light.green {
background-color: #2ecc71;
color: #2ecc71;
}
/* 信号機の光(黄色) */
.light.yellow {
background-color: #f1c40f;
color: #f1c40f;
animation-delay: 3s;
}
/* 信号機の光(赤) */
.light.red {
background-color: #df3f2e;
color: #df3f2e;
animation-delay: 6s;
}lightクラスのスタイルを確認してみると、本来は文字色を指定するためのcolorプロパティに色が設定されていますね。
box-shadowに色を設定しない場合は、このcolorに指定された色が影の色として反映されます。
そのため、3色分の@keyframesを作成する必要はなくなり、影の表示/非表示を切り替える@keyframesのみ作成すればいいというわけですね。
colorの性質に関して詳しく知りたい方は、MDNのこちらのページ内のcurrentcolorを参照してください。
【まとめ】CSSのみで色が自動的に切り替わる信号機を作成する方法
CSSのみで色が切り替わる信号機を作成する方法を紹介しました。
案件で使う機会はまずないかと思いますが、CSSアニメーションの使い方やbox-shadow, colorの性質など、参考になった部分があれば幸いです。
今回はCSSのみなのであまり綺麗な書き方ではなく無理矢理な部分が多いですが、次回はJavaScriptを併用してより綺麗なコードで作成してみようと思います。


コメント