Webサイトに「星がまたたく背景アニメーション」を入れるだけで、世界観は一気に洗練され、訪れたユーザーの第一印象は大きく変わります。しかし、いざ自分で実装しようとすると「CSSだけでキレイな星空を作れるの?」「流れ星をどう表現するのか分からない…」「ランダム点滅ってどう書けば良い?」と、最初の一歩で止まってしまう方が少なくありません。さらに、ネット上には断片的なコードや説明が多く、初心者はもちろん、中級者でも“本当に使える”星空アニメーションの情報にたどり着くのは意外と難しいものです。
本記事では、CSSだけで作る星空アニメーションの基礎はもちろん、@keyframes を使った星の点滅、radial-gradient を活用した星の生成、さらには複数レイヤーを使ったリアルな奥行き表現まで、様々なテクニックを惜しみなく解説します。さらに、流れ星の実装、パララックス効果、SP向けの最適化、JavaScript併用での高度な表現など、幅広いレベルの制作者がすぐに使える知識をまとめています。
「CSSだけでどこまで星空が作れるのか」
「JSを組み合わせるとどこまで表現が広がるのか」
その違いも明確に理解でき、あなたのサイトやポートフォリオでもすぐに応用できる内容になっています。
この記事を読み終える頃には、あなたは「自分でも星空アニメーションを自由にデザインできる」状態になっています。ぜひ、あなたのサイトや作品に、特別な星空の“世界観”を加えてみてください。
格安ドメイン取得サービス─ムームードメイン─CSSだけで作る星空背景アニメーションの基本
CSS背景アニメーションで星空を表現する最大のメリットは、JavaScriptを一切使わずに軽量な実装ができる点です。このセクションでは、初心者でもすぐに使えるコピペ可能なコードから、CSS @keyframesとradial-gradientを活用した本格的な星空表現まで、基礎から丁寧に解説します。

コピペで使える星空背景の完成コード(HTML+CSS)
まずは今すぐ使える完成コードをご紹介します。このコードはHTML5とCSS3のみで、キラキラと瞬く星空背景を実装できます。
<div class="stars"></div>
<div class="content">
<h1>CSS星空背景アニメーション</h1>
<p>JavaScriptを使わずにCSSだけで実装</p>
</div> body {
margin: 0;
padding: 0;
overflow: hidden;
background: #000814;
}
.stars {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image:
radial-gradient(2px 2px at 20% 30%, white, transparent),
radial-gradient(2px 2px at 60% 70%, white, transparent),
radial-gradient(1px 1px at 50% 50%, white, transparent),
radial-gradient(1px 1px at 80% 10%, white, transparent),
radial-gradient(2px 2px at 90% 60%, white, transparent),
radial-gradient(1px 1px at 33% 80%, white, transparent),
radial-gradient(1px 1px at 15% 90%, white, transparent);
background-size: 200% 200%;
background-position: 0% 0%;
animation: twinkle 4s ease-in-out infinite;
}
@keyframes twinkle {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
.content {
position: relative;
z-index: 1;
color: white;
text-align: center;
padding-top: 20vh;
font-family: sans-serif;
}See the Pen star-background-animation-01 by watashi-xyz (@watashi-xyz) on CodePen.
コードのポイント
.stars要素をposition: fixedで画面全体に配置し、背景として機能させていますz-indexにより、コンテンツは星空の上に重ねて表示されますradial-gradientで複数の星を配置し、animationプロパティで点滅効果を実現background: #000814は深い夜空の色を表現した濃紺色です
@keyframesで作る星のキラキラ・点滅アニメーションの基礎
CSS星背景アニメーションの核となるのが@keyframesです。このプロパティを使えば、星の点滅やキラキラといった動きを自由に制御できます。
基本的な点滅アニメーション:
.star {
width: 2px;
height: 2px;
background: white;
border-radius: 50%;
animation: blink 2s infinite;
}
@keyframes blink {
0%, 100% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.3;
transform: scale(0.8);
}
}このコードでは、opacityとtransform: scale()を組み合わせることで、星が明滅しながらサイズも変化するリアルな表現を実現しています。
キラキラ感を強調するアニメーション:
@keyframes sparkle {
0%, 100% {
opacity: 0.8;
box-shadow: 0 0 2px white;
}
25% {
opacity: 1;
box-shadow: 0 0 8px white, 0 0 12px rgba(255,255,255,0.5);
}
50% {
opacity: 0.9;
box-shadow: 0 0 4px white;
}
75% {
opacity: 1;
box-shadow: 0 0 10px white, 0 0 15px rgba(255,255,255,0.6);
}
}
.star-sparkle {
animation: sparkle 3s ease-in-out infinite;
}box-shadowを使うことで、星の周りに光の拡散効果を加え、より幻想的なキラキラエフェクトを実現できます。
アニメーション速度のバリエーション:
.star-slow { animation-duration: 5s; }
.star-medium { animation-duration: 3s; }
.star-fast { animation-duration: 1.5s; }同じアニメーションでもanimation-durationを変えることで、星ごとに異なる点滅速度を設定でき、自然でランダムな星空を演出できます。
背景全体に星を敷き詰めるradial-gradientとbackground-imageの活用
CSS背景アニメーションで星を大量に配置するには、radial-gradientをbackground-imageで重ねる手法が最も効率的です。この方法ならDOM要素を増やさず軽量に実装できます。
基本的な星の配置パターン:
.starry-sky {
width: 100%;
height: 100vh;
background-color: #0a0e27;
background-image:
radial-gradient(2px 2px at 10% 20%, white, transparent),
radial-gradient(1px 1px at 30% 40%, white, transparent),
radial-gradient(2px 2px at 50% 10%, white, transparent),
radial-gradient(1px 1px at 70% 60%, white, transparent),
radial-gradient(2px 2px at 85% 30%, white, transparent),
radial-gradient(1px 1px at 25% 80%, white, transparent),
radial-gradient(1px 1px at 65% 90%, white, transparent),
radial-gradient(2px 2px at 90% 75%, white, transparent);
background-size: 100% 100%;
background-repeat: no-repeat;
}大量の星を効率的に配置する応用テクニック:
.dense-stars {
background: #000428;
background-image:
radial-gradient(1px 1px at 20% 10%, white, transparent),
radial-gradient(1px 1px at 40% 30%, rgba(255,255,255,0.8), transparent),
radial-gradient(2px 2px at 60% 20%, white, transparent),
radial-gradient(1px 1px at 80% 50%, white, transparent),
radial-gradient(1px 1px at 15% 60%, rgba(255,255,255,0.9), transparent),
radial-gradient(2px 2px at 35% 75%, white, transparent),
radial-gradient(1px 1px at 55% 85%, white, transparent),
radial-gradient(1px 1px at 75% 95%, rgba(255,255,255,0.7), transparent);
background-size: 250% 250%;
background-position: 0% 0%;
animation: moveStars 50s linear infinite;
}
@keyframes moveStars {
from {
background-position: 0% 0%;
}
to {
background-position: 100% 100%;
}
}実装のポイント:
radial-gradientの1つ目の値(2px 2pxなど)が星のサイズを決定しますat 20% 10%の部分で星の配置座標を指定(左からの距離%, 上からの距離%)rgba(255,255,255,0.8)で透明度を調整し、星の明るさに変化をつけられますbackground-sizeを200%以上にすることで、星の密度を調整可能- 複数の
radial-gradientを重ねることで、何百もの星を軽量に表現できます
色付きの星を表現する方法:
.colored-stars {
background: linear-gradient(to bottom, #000428, #004e92);
background-image:
radial-gradient(2px 2px at 25% 25%, #ffffff, transparent),
radial-gradient(1px 1px at 45% 15%, #b8e6ff, transparent),
radial-gradient(1px 1px at 65% 35%, #ffe4b5, transparent),
radial-gradient(2px 2px at 85% 45%, #ffcccb, transparent);
}白だけでなく青白い星や淡いオレンジ色の星を混ぜることで、よりリアルな星空を表現できます。
このradial-gradient手法は、パフォーマンスに優れ、レスポンシブ対応も容易で、CSS背景アニメーションで星を実装する際の最も実用的な方法と言えます。
流れ星・パララックス・複数レイヤーなど動きのある星空表現
静止した星空も美しいですが、流れ星やパララックス効果を加えることで、CSS背景アニメーションはさらにドラマチックな表現になります。このセクションでは、CSSだけで実装できる動的な星空エフェクトを、実装ステップとともに詳しく解説します。

CSSで実現する流れ星アニメーション(実装ステップ+サンプルコード)
流れ星エフェクトは、CSS背景アニメーションの中でも特に人気の高い表現です。transformとopacityを組み合わせることで、JavaScriptを使わずに実装できます。
完成コード(HTML+CSS):
<div class="shooting-star"></div>
<div class="shooting-star"></div>
<div class="shooting-star"></div>
<div class="shooting-star"></div>body {
margin: 0;
background: radial-gradient(ellipse at bottom, #1b2735 0%, #090a0f 100%);
height: 100vh;
overflow: hidden;
}
.shooting-star {
position: absolute;
width: 2px;
height: 2px;
background: white;
border-radius: 50%;
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.1),
0 0 0 4px rgba(255, 255, 255, 0.1), 0 0 10px rgba(255, 255, 255, 1);
animation: shoot 3s ease-in infinite;
}
.shooting-star::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 1px;
background: linear-gradient(90deg, white, transparent);
transform: translateX(-100px) translateY(0);
}
@keyframes shoot {
0% {
transform: translateX(0) translateY(0);
opacity: 1;
}
70% {
opacity: 1;
}
100% {
transform: translateX(-300px) translateY(300px);
opacity: 0;
}
}
/* 複数の流れ星を配置 */
.shooting-star:nth-child(1) {
top: 10%;
right: 10%;
animation-delay: 0s;
animation-duration: 2.5s;
}
.shooting-star:nth-child(2) {
top: 30%;
right: 30%;
animation-delay: 1.2s;
animation-duration: 3s;
}
.shooting-star:nth-child(3) {
top: 50%;
right: 20%;
animation-delay: 2.5s;
animation-duration: 2.8s;
}
.shooting-star:nth-child(4) {
top: 20%;
right: 50%;
animation-delay: 4s;
animation-duration: 3.2s;
}実際の表示
See the Pen star-background-animation-02 by watashi-xyz (@watashi-xyz) on CodePen.
実装ステップの解説:
ステップ1:流れ星の本体を作成
.shooting-star {
width: 2px;
height: 2px;
background: white;
border-radius: 50%;
box-shadow: 0 0 10px rgba(255, 255, 255, 1);
}小さな点とbox-shadowで光る星の核を表現します。
ステップ2:尾を追加
.shooting-star::before {
content: '';
width: 100px;
height: 1px;
background: linear-gradient(90deg, white, transparent);
}::before疑似要素で流れ星の尾を作成。linear-gradientで先端から透明へのグラデーションを実現します。
ステップ3:移動アニメーションを設定
@keyframes shoot {
0% {
transform: translateX(0) translateY(0);
opacity: 1;
}
100% {
transform: translateX(-300px) translateY(300px);
opacity: 0;
}
}右上から左下へ斜めに移動し、最後にフェードアウトします。
カスタマイズのポイント:
animation-durationを変えることで流れ星の速度を調整animation-delayをずらすことでランダムなタイミングで出現translateXとtranslateYの値で流れる角度を変更可能- 尾の長さは
::beforeのwidthで調整できます
星を大小・速度差で表現する複数レイヤー構造の作り方
リアルな星空を作るには、遠近感のある複数レイヤーが不可欠です。大きさと速度が異なる星のレイヤーを重ねることで、立体的なCSS背景アニメーションを実現できます。
3層構造の星空実装コード:
<div class="stars-far"></div>
<div class="stars-mid"></div>
<div class="stars-near"></div>body {
margin: 0;
background: #000000;
height: 100vh;
overflow: hidden;
position: relative;
}
/* 遠い星(小さく、ゆっくり) */
.stars-far {
--size: 2px;
position: absolute;
width: 100%;
height: 100%;
background-image: radial-gradient(1px 1px at 20% 30%, white, transparent),
radial-gradient(var(--size) var(--size) at 40% 70%, white, transparent),
radial-gradient(var(--size) var(--size) at 60% 20%, white, transparent),
radial-gradient(var(--size) var(--size) at 80% 60%, white, transparent),
radial-gradient(var(--size) var(--size) at 10% 80%, white, transparent),
radial-gradient(var(--size) var(--size) at 90% 40%, white, transparent);
background-size: 200% 200%;
animation: driftFar 120s linear infinite;
opacity: 0.5;
}
/* 中距離の星(中サイズ、中速) */
.stars-mid {
--size: 5px;
position: absolute;
width: 100%;
height: 100%;
background-image: radial-gradient(var(--size) var(--size) at 15% 40%, white, transparent),
radial-gradient(var(--size) var(--size) at 45% 60%, white, transparent),
radial-gradient(var(--size) var(--size) at 65% 30%, white, transparent),
radial-gradient(var(--size) var(--size) at 85% 70%, white, transparent);
background-size: 150% 150%;
animation: driftMid 80s linear infinite;
opacity: 0.7;
}
/* 近い星(大きく、速い) */
.stars-near {
--size: 10px;
position: absolute;
width: 100%;
height: 100%;
background-image: radial-gradient(var(--size) var(--size) at 25% 25%, white, transparent),
radial-gradient(var(--size) var(--size) at 55% 55%, white, transparent),
radial-gradient(var(--size) var(--size) at 75% 35%, white, transparent);
background-size: 100% 100%;
animation: driftNear 50s linear infinite;
opacity: 0.9;
}
@keyframes driftFar {
from {
transform: translateX(0) translateY(0);
}
to {
transform: translateX(-50px) translateY(50px);
}
}
@keyframes driftMid {
from {
transform: translateX(0) translateY(0);
}
to {
transform: translateX(-100px) translateY(80px);
}
}
@keyframes driftNear {
from {
transform: translateX(0) translateY(0);
}
to {
transform: translateX(-150px) translateY(120px);
}
}
/* 点滅効果を追加 */
.stars-far {
animation: driftFar 120s linear infinite, twinkleFar 3s ease-in-out infinite;
}
.stars-mid {
animation: driftMid 80s linear infinite, twinkleMid 2.5s ease-in-out infinite;
}
.stars-near {
animation: driftNear 50s linear infinite, twinkleNear 2s ease-in-out infinite;
}
@keyframes twinkleFar {
0%,
100% {
opacity: 0.5;
}
50% {
opacity: 0.3;
}
}
@keyframes twinkleMid {
0%,
100% {
opacity: 0.7;
}
50% {
opacity: 0.5;
}
}
@keyframes twinkleNear {
0%,
100% {
opacity: 0.9;
}
50% {
opacity: 0.7;
}
}
実際の表示
See the Pen star-background-animation-03 by watashi-xyz (@watashi-xyz) on CodePen.
レイヤー構造のデザインポイント:
- サイズの差異化
- 遠い星:2px(小さく)
- 中距離の星:5px(中サイズ)
- 近い星:10px(大きく)
- 速度の差異化
- 遠い星:120秒(ゆっくり)
- 中距離:80秒(中速)
- 近い星:50秒(速い)
- 透明度の調整
- 遠い星:opacity 0.5(薄く)
- 近い星:opacity 0.9(濃く)
この視差効果(パララックス)により、奥行きのある自然な星空表現が可能になります。
◆◇◆ 【衝撃価格】VPS512MBプラン!1時間1.3円【ConoHa】 ◆◇◆パララックス風に星が動く背景アニメーションの設計方法
スクロール連動のパララックス効果をCSS背景アニメーションで再現することで、ユーザーの操作に反応する動的な星空を作れます。
スクロールに連動するパララックス星空:
<div class="parallax-container">
<div class="star-layer layer-1"></div>
<div class="star-layer layer-2"></div>
<div class="star-layer layer-3"></div>
</div>
<div class="content">
<section>CSS パララックス星空</section>
<section>スクロールで奥行きを体験</section>
</div>body {
margin: 0;
background: #0a0a0a;
height: 300vh; /* スクロール可能にする */
}
.parallax-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
overflow: hidden;
}
.star-layer {
position: absolute;
width: 100%;
height: 100%;
}
.layer-1 {
background-image: radial-gradient(2px 2px at 20% 30%, white, transparent),
radial-gradient(2px 2px at 60% 70%, white, transparent),
radial-gradient(2px 2px at 80% 20%, white, transparent);
background-size: 100% 100%;
animation: parallax1 30s ease-in-out infinite alternate;
}
.layer-2 {
background-image: radial-gradient(3px 3px at 40% 40%, white, transparent),
radial-gradient(3px 3px at 70% 60%, white, transparent);
background-size: 100% 100%;
animation: parallax2 25s ease-in-out infinite alternate;
opacity: 0.8;
}
.layer-3 {
background-image: radial-gradient(4px 4px at 30% 50%, white, transparent),
radial-gradient(4px 4px at 80% 80%, white, transparent);
background-size: 100% 100%;
animation: parallax3 20s ease-in-out infinite alternate;
opacity: 0.9;
}
@keyframes parallax1 {
from {
transform: translateY(0) translateX(0);
}
to {
transform: translateY(30px) translateX(20px);
}
}
@keyframes parallax2 {
from {
transform: translateY(0) translateX(0);
}
to {
transform: translateY(60px) translateX(40px);
}
}
@keyframes parallax3 {
from {
transform: translateY(0) translateX(0);
}
to {
transform: translateY(90px) translateX(60px);
}
}
.content {
position: relative;
z-index: 10;
color: white;
padding: 100vh 5%;
font-family: sans-serif;
}
.content section {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
font-size: 2rem;
}実際の表示
See the Pen star-background-animation-04 by watashi-xyz (@watashi-xyz) on CodePen.
パララックス設計の要点
position: fixedで星空を固定し、コンテンツだけスクロール- 各レイヤーの
transform移動量を変えることで遠近感を表現 animation-durationを変え、レイヤーごとに異なる移動速度を設定alternateを使い、アニメーションを往復させることで自然な動きを実現
このテクニックはJavaScriptなしで擬似的なパララックスを再現でき、軽量な実装が可能です。
専門的な知識不要!誰でも簡単に使える『XWRITE(エックスライト)』スマホでも軽く動く最適化ポイント(transform、opacityの使い方)
CSS背景アニメーションで星を実装する際、モバイル端末でのパフォーマンスは重要な課題です。適切な最適化により、カクつきのないスムーズな星空を実現できます。
パフォーマンス最適化の基本原則:
/* ❌ 重い実装(避けるべき) */
.star-bad {
animation: moveBad 3s infinite;
}
@keyframes moveBad {
from {
top: 0;
left: 0;
}
to {
top: 100px;
left: 100px;
}
}
/* ✅ 軽い実装(推奨) */
.star-good {
animation: moveGood 3s infinite;
will-change: transform; /* GPU加速を有効化 */
}
@keyframes moveGood {
from {
transform: translate(0, 0);
}
to {
transform: translate(100px, 100px);
}
}
最適化の重要ポイント:
1. transformとopacityのみを使用
/* GPUアクセラレーションが効く */
@keyframes optimized {
0% {
transform: translateX(0) scale(1);
opacity: 1;
}
100% {
transform: translateX(100px) scale(0.8);
opacity: 0.5;
}
}top、left、width、heightなどのプロパティはレイアウト再計算を引き起こし重いため、transformを使います。
2. will-changeでブラウザに最適化を指示
.star-optimized {
will-change: transform, opacity;
animation: drift 5s linear infinite;
}ただし、will-changeは使いすぎるとメモリを消費するため、アニメーションする要素にのみ適用してください。
3. レイヤー数を制限
/* モバイル向け:2層まで */
@media (max-width: 768px) {
.stars-far {
display: block;
}
.stars-mid {
display: block;
}
.stars-near {
display: none; /* 3層目は非表示 */
}
}4. radial-gradientの数を調整
/* デスクトップ:多数の星 */
.stars-desktop {
background-image:
radial-gradient(1px 1px at 10% 10%, white, transparent),
radial-gradient(1px 1px at 20% 30%, white, transparent),
radial-gradient(1px 1px at 30% 50%, white, transparent),
/* ...20個以上 */;
}
/* モバイル:最小限 */
@media (max-width: 768px) {
.stars-mobile {
background-image:
radial-gradient(1px 1px at 20% 20%, white, transparent),
radial-gradient(1px 1px at 60% 50%, white, transparent),
radial-gradient(1px 1px at 80% 70%, white, transparent);
}
}5. animationの最適化
.star-smooth {
/* linear か ease-out を推奨 */
animation: move 3s linear infinite;
/* 不要な複雑なイージング関数は避ける */
}完全最適化版サンプルコード:
.optimized-starry-sky {
position: fixed;
width: 100%;
height: 100%;
background: #000;
will-change: transform;
}
.star-layer-optimized {
position: absolute;
width: 100%;
height: 100%;
background-image:
radial-gradient(2px 2px at 25% 25%, white, transparent),
radial-gradient(1px 1px at 75% 75%, white, transparent);
background-size: 200% 200%;
animation: smoothDrift 60s linear infinite;
transform: translateZ(0); /* GPU加速を強制 */
}
@keyframes smoothDrift {
from {
transform: translate(0, 0) translateZ(0);
opacity: 0.8;
}
to {
transform: translate(-50px, 50px) translateZ(0);
opacity: 1;
}
}
/* モバイル最適化 */
@media (max-width: 768px) {
.star-layer-optimized {
animation-duration: 40s; /* 速度を落とす */
background-size: 150% 150%; /* 星の数を減らす */
}
}パフォーマンスチェックリスト
これらの最適化により、60fpsでスムーズに動作するCSS背景アニメーションを実現できます。
Amazon.co.jpCSS+JavaScriptで作る高度な星アニメーション
CSSだけでも美しい星空を実装できますが、JavaScriptを組み合わせることでインタラクティブでダイナミックな表現が可能になります。このセクションでは、マウス操作に反応する星や、リアルタイムでカスタマイズできる高度な実装方法を紹介します。

マウス追従やインタラクション対応の星アニメーション
マウスの動きに反応する星空は、ユーザー体験を大きく向上させます。以下は軽量で実用的な実装例です。
マウス追従型星空の完成コード:
<div class="cursor"></div>body {
margin: 0;
overflow: hidden;
background: radial-gradient(ellipse at bottom, #1b2735 0%, #090a0f 100%);
height: 100vh;
cursor: none;
}
.star {
position: absolute;
width: 3px;
height: 3px;
background: white;
border-radius: 50%;
pointer-events: none;
box-shadow: 0 0 6px rgba(255, 255, 255, 0.8);
transition: transform 0.3s ease-out, opacity 0.3s ease-out;
}
.star.active {
transform: scale(2);
box-shadow: 0 0 20px rgba(255, 255, 255, 1), 0 0 30px rgba(255, 255, 255, 0.5);
}
.cursor {
position: fixed;
width: 20px;
height: 20px;
border: 2px solid rgba(255, 255, 255, 0.5);
border-radius: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
transition: transform 0.1s ease-out;
z-index: 1000;
}
.cursor.clicked {
transform: translate(-50%, -50%) scale(1.5);
border-color: rgba(255, 255, 255, 1);
}
// 星を生成
const starCount = 100;
const stars = [];
const container = document.body;
for (let i = 0; i < starCount; i++) {
const star = document.createElement("div");
star.className = "star";
star.style.left = Math.random() * 100 + "%";
star.style.top = Math.random() * 100 + "%";
star.style.animationDelay = Math.random() * 3 + "s";
container.appendChild(star);
stars.push({
element: star,
x: parseFloat(star.style.left),
y: parseFloat(star.style.top),
baseX: parseFloat(star.style.left),
baseY: parseFloat(star.style.top)
});
}
// カーソル要素
const cursor = document.querySelector(".cursor");
let mouseX = 0;
let mouseY = 0;
// マウス移動イベント
document.addEventListener("mousemove", (e) => {
mouseX = e.clientX;
mouseY = e.clientY;
// カスタムカーソルを移動
cursor.style.left = mouseX + "px";
cursor.style.top = mouseY + "px";
// 星をマウスに反応させる
stars.forEach((star) => {
const rect = star.element.getBoundingClientRect();
const starCenterX = rect.left + rect.width / 2;
const starCenterY = rect.top + rect.height / 2;
const distance = Math.sqrt(
Math.pow(mouseX - starCenterX, 2) + Math.pow(mouseY - starCenterY, 2)
);
// マウスが近づいたら星を動かす
if (distance < 150) {
const angle = Math.atan2(mouseY - starCenterY, mouseX - starCenterX);
const force = (150 - distance) / 150;
const moveX = Math.cos(angle) * force * 30;
const moveY = Math.sin(angle) * force * 30;
star.element.style.transform = `translate(${-moveX}px, ${-moveY}px)`;
star.element.classList.add("active");
} else {
star.element.style.transform = "translate(0, 0)";
star.element.classList.remove("active");
}
});
});
// クリックエフェクト
document.addEventListener("mousedown", () => {
cursor.classList.add("clicked");
// クリック位置に新しい星を生成
const newStar = document.createElement("div");
newStar.className = "star active";
newStar.style.left = mouseX + "px";
newStar.style.top = mouseY + "px";
container.appendChild(newStar);
setTimeout(() => {
newStar.style.opacity = "0";
newStar.style.transform = "scale(3)";
setTimeout(() => newStar.remove(), 300);
}, 100);
});
document.addEventListener("mouseup", () => {
cursor.classList.remove("clicked");
});
// タッチデバイス対応
document.addEventListener("touchmove", (e) => {
const touch = e.touches[0];
mouseX = touch.clientX;
mouseY = touch.clientY;
});
実際の表示
See the Pen star-background-animation-05 by watashi-xyz (@watashi-xyz) on CodePen.
実装のポイント解説:
1. 星の動的生成
for (let i = 0; i < starCount; i++) {
const star = document.createElement('div');
star.style.left = Math.random() * 100 + '%';
star.style.top = Math.random() * 100 + '%';
}JavaScriptで星をランダムに配置することで、毎回異なる星空を生成できます。
2. マウスとの距離計算
const distance = Math.sqrt(
Math.pow(mouseX - starCenterX, 2) +
Math.pow(mouseY - starCenterY, 2)
);ピタゴラスの定理を使い、マウスと各星の距離を計算します。
3. 反発エフェクト
if (distance < 150) {
const angle = Math.atan2(mouseY - starCenterY, mouseX - starCenterX);
const force = (150 - distance) / 150;
const moveX = Math.cos(angle) * force * 30;
const moveY = Math.sin(angle) * force * 30;
star.element.style.transform = `translate(${-moveX}px, ${-moveY}px)`;
}マウスが近づくと星が逃げるように動きます。距離に応じて力を調整し、自然な動きを実現しています。
より高度なインタラクション例:
// 星をマウスに引き寄せる(吸引エフェクト)
if (distance < 200) {
const angle = Math.atan2(mouseY - starCenterY, mouseX - starCenterX);
const force = (200 - distance) / 200;
const moveX = Math.cos(angle) * force * 50;
const moveY = Math.sin(angle) * force * 50;
// マイナスを付けない = 引き寄せる
star.element.style.transform = `translate(${moveX}px, ${moveY}px)`;
}パフォーマンスの最適化:
// requestAnimationFrame を使った最適化版
let rafId;
document.addEventListener('mousemove', (e) => {
mouseX = e.clientX;
mouseY = e.clientY;
if (!rafId) {
rafId = requestAnimationFrame(updateStars);
}
});
function updateStars() {
stars.forEach(star => {
// 星の更新処理
});
rafId = null;
}requestAnimationFrameを使うことで、ブラウザの描画タイミングに合わせて更新し、スムーズな動作を保証します。
星の数・速度・色をリアルタイム変更できるカスタマイズ方法
JavaScriptを使えば、ユーザーがリアルタイムで星空をカスタマイズできるインタラクティブなコントロールパネルを実装できます。
完全カスタマイズ可能な星空システム:
<div id="starfield"></div>
<div class="control-panel">
<h3 style="margin-top: 0;">星空コントローラー</h3>
<div class="control-group">
<label>星の数: <span class="value-display" id="countValue">100</span></label>
<input type="range" id="starCount" min="10" max="500" value="100">
</div>
<div class="control-group">
<label>星のサイズ: <span class="value-display" id="sizeValue">2px</span></label>
<input type="range" id="starSize" min="1" max="5" value="2" step="0.5">
</div>
<div class="control-group">
<label>点滅速度: <span class="value-display" id="speedValue">3s</span></label>
<input type="range" id="twinkleSpeed" min="1" max="10" value="3">
</div>
<div class="control-group">
<label>星の色:</label>
<input type="color" id="starColor" value="#ffffff">
</div>
<div class="control-group">
<label>背景色:</label>
<input type="color" id="bgColor" value="#000000">
</div>
<button onclick="resetDefaults()">デフォルトに戻す</button>
</div>body {
margin: 0;
background: #000;
font-family: sans-serif;
overflow: hidden;
}
#starfield {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
}
.star {
position: absolute;
border-radius: 50%;
animation: twinkle linear infinite;
}
@keyframes twinkle {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.3;
}
}
.control-panel {
position: fixed;
top: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.8);
padding: 20px;
border-radius: 10px;
color: white;
z-index: 100;
min-width: 250px;
backdrop-filter: blur(10px);
}
.control-group {
margin-bottom: 15px;
}
.control-group label {
display: block;
margin-bottom: 5px;
font-size: 14px;
}
input[type="range"] {
width: 100%;
}
input[type="color"] {
width: 100%;
height: 30px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.value-display {
display: inline-block;
margin-left: 10px;
font-weight: bold;
color: #4caf50;
}
button {
width: 100%;
padding: 10px;
margin-top: 10px;
background: #4caf50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
}
button:hover {
background: #45a049;
}
const starfield = document.getElementById("starfield");
let stars = [];
let config = {
count: 100,
size: 2,
speed: 3,
color: "#ffffff",
bgColor: "#000000"
};
// 星を生成する関数
function generateStars() {
// 既存の星を削除
starfield.innerHTML = "";
stars = [];
for (let i = 0; i < config.count; i++) {
const star = document.createElement("div");
star.className = "star";
const x = Math.random() * 100;
const y = Math.random() * 100;
const size = config.size * (0.5 + Math.random() * 0.5);
const duration = config.speed * (0.5 + Math.random() * 1.5);
const delay = Math.random() * config.speed;
star.style.left = x + "%";
star.style.top = y + "%";
star.style.width = size + "px";
star.style.height = size + "px";
star.style.backgroundColor = config.color;
star.style.animationDuration = duration + "s";
star.style.animationDelay = delay + "s";
star.style.boxShadow = `0 0 ${size * 2}px ${config.color}`;
starfield.appendChild(star);
stars.push(star);
}
}
// 星の色を更新
function updateStarColor() {
stars.forEach((star) => {
star.style.backgroundColor = config.color;
const size = parseFloat(star.style.width);
star.style.boxShadow = `0 0 ${size * 2}px ${config.color}`;
});
}
// 星のサイズを更新
function updateStarSize() {
stars.forEach((star) => {
const size = config.size * (0.5 + Math.random() * 0.5);
star.style.width = size + "px";
star.style.height = size + "px";
star.style.boxShadow = `0 0 ${size * 2}px ${config.color}`;
});
}
// 点滅速度を更新
function updateTwinkleSpeed() {
stars.forEach((star) => {
const duration = config.speed * (0.5 + Math.random() * 1.5);
star.style.animationDuration = duration + "s";
});
}
// イベントリスナー
document.getElementById("starCount").addEventListener("input", (e) => {
config.count = parseInt(e.target.value);
document.getElementById("countValue").textContent = config.count;
generateStars();
});
document.getElementById("starSize").addEventListener("input", (e) => {
config.size = parseFloat(e.target.value);
document.getElementById("sizeValue").textContent = config.size + "px";
updateStarSize();
});
document.getElementById("twinkleSpeed").addEventListener("input", (e) => {
config.speed = parseInt(e.target.value);
document.getElementById("speedValue").textContent = config.speed + "s";
updateTwinkleSpeed();
});
document.getElementById("starColor").addEventListener("input", (e) => {
config.color = e.target.value;
updateStarColor();
});
document.getElementById("bgColor").addEventListener("input", (e) => {
config.bgColor = e.target.value;
document.body.style.background = config.bgColor;
});
// デフォルトに戻す
function resetDefaults() {
config = {
count: 100,
size: 2,
speed: 3,
color: "#ffffff",
bgColor: "#000000"
};
document.getElementById("starCount").value = 100;
document.getElementById("starSize").value = 2;
document.getElementById("twinkleSpeed").value = 3;
document.getElementById("starColor").value = "#ffffff";
document.getElementById("bgColor").value = "#000000";
document.getElementById("countValue").textContent = "100";
document.getElementById("sizeValue").textContent = "2px";
document.getElementById("speedValue").textContent = "3s";
document.body.style.background = "#000000";
generateStars();
}
// 初期化
generateStars();
実際の表示
See the Pen star-background-animation-06 by watashi-xyz (@watashi-xyz) on CodePen.
カスタマイズ機能の実装ポイント:
1. 動的な星の再生成
function generateStars() {
starfield.innerHTML = ''; // 既存を削除
for (let i = 0; i < config.count; i++) {
// 新しい星を生成
}
}星の数を変更したときに、すべての星を再生成します。
2. 既存の星の属性更新
function updateStarColor() {
stars.forEach(star => {
star.style.backgroundColor = config.color;
star.style.boxShadow = `0 0 ${size * 2}px ${config.color}`;
});
}色やサイズの変更は、既存の星の属性を更新するだけで対応できます。
3. ランダム性の導入
const size = config.size * (0.5 + Math.random() * 0.5);
const duration = config.speed * (0.5 + Math.random() * 1.5);基本値にランダム係数を掛けることで、自然なバリエーションを実現します。
より高度なカスタマイズ例:
// プリセット機能
const presets = {
classic: { count: 100, size: 2, speed: 3, color: '#ffffff' },
colorful: { count: 150, size: 3, speed: 2, color: '#88ccff' },
minimal: { count: 30, size: 1, speed: 5, color: '#ffffff' },
galaxy: { count: 300, size: 1.5, speed: 4, color: '#b8a9ff' }
};
function applyPreset(presetName) {
config = { ...config, ...presets[presetName] };
generateStars();
}Three.jsなど外部ライブラリを使った高品質な星空表現と比較ポイント
より高品質な3D星空を実装したい場合、Three.jsなどの3Dライブラリが選択肢になります。ここでは純粋なCSS/JavaScript実装との比較も含めて解説します。
Three.jsによる3D星空の実装例:
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>body {
margin: 0;
overflow: hidden;
background: #000;
}
canvas {
display: block;
}// シーン、カメラ、レンダラーの初期化
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 星のジオメトリとマテリアル
const starGeometry = new THREE.BufferGeometry();
const starCount = 10000;
const positions = new Float32Array(starCount * 3);
const colors = new Float32Array(starCount * 3);
for (let i = 0; i < starCount * 3; i += 3) {
// ランダムな位置に配置
positions[i] = (Math.random() - 0.5) * 2000;
positions[i + 1] = (Math.random() - 0.5) * 2000;
positions[i + 2] = (Math.random() - 0.5) * 2000;
// 色のバリエーション(白から青白)
colors[i] = 0.8 + Math.random() * 0.2;
colors[i + 1] = 0.8 + Math.random() * 0.2;
colors[i + 2] = 1;
}
starGeometry.setAttribute("position", new THREE.BufferAttribute(positions, 3));
starGeometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));
// マテリアル設定
const starMaterial = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true
});
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
camera.position.z = 5;
// マウス追従
let mouseX = 0;
let mouseY = 0;
document.addEventListener("mousemove", (e) => {
mouseX = (e.clientX / window.innerWidth) * 2 - 1;
mouseY = -(e.clientY / window.innerHeight) * 2 + 1;
});
// アニメーションループ
function animate() {
requestAnimationFrame(animate);
// 星を回転
stars.rotation.x += 0.0005;
stars.rotation.y += 0.0005;
// マウスに反応してカメラを移動
camera.position.x += (mouseX * 5 - camera.position.x) * 0.05;
camera.position.y += (mouseY * 5 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
renderer.render(scene, camera);
}
animate();
// リサイズ対応
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
実際の表示
See the Pen star-background-animation-07 by watashi-xyz (@watashi-xyz) on CodePen.
CSS/JS vs Three.js 比較表:
| 項目 | CSS/JavaScript | Three.js |
|---|---|---|
| 実装難易度 | ★★☆☆☆ 初心者でも可能 | ★★★★☆ 3Dの知識が必要 |
| ファイルサイズ | ~5KB 超軽量 | ~600KB ライブラリが重い |
| 表現力 | 2D的な表現 | 本格的な3D空間 |
| 星の数 | ~500個が現実的 | 10,000個以上も可能 |
| パフォーマンス | 軽量だが限界あり | GPU活用で高速 |
| カスタマイズ性 | シンプルで直感的 | 高度だが複雑 |
| モバイル対応 | 最適化すれば良好 | デバイス性能に依存 |
| 保守性 | 容易 | 専門知識が必要 |
どちらを選ぶべきか:
CSS/JavaScriptを選ぶべき場合:
- シンプルな背景装飾として使いたい
- ページの読み込み速度を最優先したい
- モバイルファーストのデザイン
- 保守・更新を簡単にしたい
- チームに3Dの知識がない
Three.jsを選ぶべき場合:
- リッチな3D表現が必須
- 10,000個以上の星を表示したい
- 複雑なカメラワークが必要
- WebGLを活用したい
- パフォーマンスに余裕がある環境
ハイブリッドアプローチ:
// デバイス性能で切り替え
const isHighPerformance = navigator.hardwareConcurrency > 4;
if (isHighPerformance && window.WebGLRenderingContext) {
// Three.jsで高品質版を読み込み
loadThreeJsStarfield();
} else {
// CSSで軽量版にフォールバック
loadCSSStarfield();
}このように、ユーザーの環境に応じて最適な実装を選択することで、すべてのユーザーに最高の体験を提供できます。
実装の判断基準まとめ
- まずはCSS/JavaScriptで実装し、必要性を評価
- パフォーマンス問題が出たら最適化を検討
- どうしても表現力が足りない場合のみThree.jsを検討
- プログレッシブエンハンスメントの考え方で段階的に実装
CSS背景アニメーションで星を実装する場合、ほとんどのケースでは純粋なCSS/JavaScriptで十分です。Three.jsは本当に必要なときだけ使うことで、メンテナンス性とパフォーマンスのバランスを保てます。
コストパフォーマンスに優れた高性能なレンタルサーバー
【Hostinger】よくある質問(FAQ)
ここでは、「css 背景 アニメーション 星」を実装する際によくある疑問や、パフォーマンスに関する質問にお答えします。
-
モバイル(スマートフォン)でアニメーションがカクつきます。対策はありますか?
-
はい、モバイルでのパフォーマンス低下はよくある問題です。主な原因は、GPU(グラフィック処理装置)への負荷が高いプロパティを使っていることです。
最も効果的な対策は、アニメーションに
transformプロパティ(特にtranslateやscale)とopacityプロパティのみを使用することです。これらのプロパティはGPUで処理されるため、CPUで処理されるtopやleft、widthなどと比べて遥かに軽量です。will-changeプロパティを星要素に追加することで、ブラウザに「この要素はアニメーションで変化するよ」と事前に伝えることができ、最適化が促進される場合があります。/* カクつき対策の例 */ .star { /* transformとopacityを使う */ animation: twinkle 5s infinite; will-change: transform, opacity; /* 最適化を促す */ }
-
星空アニメーションと他のコンテンツの重なり順(z-index)はどう設定すべきですか?
-
星空アニメーションは背景として機能させたい場合がほとんどですので、通常は他の要素よりも低い
z-indexを設定します。- 背景コンテナ:アニメーション全体を包むコンテナ(例:
.star-background)にposition: fixed;またはposition: absolute;を設定し、z-index: -1;またはz-index: 0;など他の要素より低い値を設定します。 - 前面コンテンツ:記事本文やナビゲーションなど、前面に表示したいコンテンツのコンテナ(例:
.main-content)にはposition: relative;を設定し、z-index: 1;以上の高い値を設定することで、星空の上に表示されます。
/* z-index 設定のベストプラクティス例 */ .star-background { position: fixed; top: 0; left: 0; width: 100%; height: 100vh; z-index: -1; /* 背景なので最も低い値 */ } .main-content { position: relative; z-index: 10; /* 背景より上に表示 */ } - 背景コンテナ:アニメーション全体を包むコンテナ(例:
まとめ
この記事では、CSS背景アニメーションで星空を実装する方法を、基礎から応用まで徹底的に解説してきました。CSSだけで作れるシンプルな星空から、JavaScriptを組み合わせた高度なインタラクティブ表現まで、実際にコピペで使えるコードとともにお届けしました。
CSS背景アニメーションで星を実装する際は、まずシンプルなCSSから始めて、必要に応じて機能を追加していくアプローチがおすすめです。この記事で紹介したテクニックを活用すれば、あなたのWebサイトに美しく軽量な星空を簡単に実装できます。ぜひ実際のプロジェクトで試してみてください。


