銀河鉄道

【CSS】だけで星をたくさん作る方法[JSやdivタグ不要]

サムネイル
box-shadowの星空

星を作りたい。

でも、JavaScriptは 使いたくない。

それなら、CSSの box-shadow が便利。

box-shadowでこんな感じにしてみよう

擬似要素に、box-shadowで円を作る

まずは円を1個作ってみよう。

青が本体:わかりやすく高さを10pxに。

赤が疑似要素:10pxの位置に。

ここをクリックしてコードを見る
.item {
  position: relative;
  width: 100%;
  height: 10px;
  background: blue;
  
  &::after {
   position: absolute;
   content: '';
   width: 10px;
   height: 10px;
   border-radius: 50%;
   box-shadow: 10px 10px red;
  }
}

【 Point 】

「boxshadow: 10px 10px red」

X方向に10px・Y方向に10px・赤

shadow(影)だから、名のごとく本体の分身だ。

box-shadowは、カンマ区切りで複数配置できる

20pxの位置にも作ってみよう。

ここをクリックしてコードを見る
box-shadow: 10px 10px red,
            20px 20px red;

【 Point 】

「boxshadow: 10px 10px red, 20px 20px red」

カンマ区切りで複数設置。

エディタでは、カンマで改行しておくと後で見やすい。

マイナス数値で逆側に配置

わかりやすいように、次は before で作ってみよう。

黄色が before。

ここをクリックしてコードを見る
.item {
 〜〜

  &::before {
   〜〜
   box-shadow: -10px -10px yellow,
               -20px -20px yellow;
  }

  &::after {
   〜〜
   box-shadow: 10px 10px red,
               20px 20px red;
  }
}

同じ数値をマイナスにすれば、ちょうど逆側になるんだ。

カンマ区切りで何個でも作れる

いっぱい作ってみよう。

ここをクリックしてコードを見る
.item {
 〜〜

  &::before {
   〜〜
   box-shadow: -10px -10px yellow,
               -20px -20px yellow,
               -30px -30px yellow,
               -40px -40px yellow,
               -50px -50px yellow,
               -60px -60px yellow,
               -70px -70px yellow;
  }

  &::after {
   〜〜
   box-shadow: 10px 10px red,
               20px 20px red,
               30px 30px red,
               40px 40px red,
               50px 50px red,
               60px 60px red,
               70px 70px red;
  }
}

グラフみたいで綺麗。

でも、散りばめたいときは、位置の指定が大変そう。

Sass関数のrandomでランダム配置

ランダムを使ってみよう。

数値は変数にしておくと、後から調整がしやすいよ。

ここをクリックしてコードを見る
// 変数で数値を一括管理できるようにする
$max: 100;
$x: 0.1vw;
$y: 0.1vh;

.item {
 〜〜

  &::before {
   〜〜
   box-shadow: random($max) * -$x random($max) * -$y yellow,
               random($max) * -$x random($max) * -$y yellow,
               random($max) * -$x random($max) * -$y yellow,
               random($max) * -$x random($max) * -$y yellow,
               random($max) * -$x random($max) * -$y yellow,
               random($max) * -$x random($max) * -$y yellow,
               random($max) * -$x random($max) * -$y yellow;
  }

  &::after {
   〜〜
   box-shadow: random($max) * $x random($max) * $y red,
               random($max) * $x random($max) * $y red,
               random($max) * $x random($max) * $y red,
               random($max) * $x random($max) * $y red,
               random($max) * $x random($max) * $y red,
               random($max) * $x random($max) * $y red,
               random($max) * $x random($max) * $y red;
  }
}

ランダムになった。

あとは、自分で変数の数値をいじってみればいいんだ。

【 Point 】

random(最大値)

最大値までの数値で、ランダムな数を生成。

そこに、単位付き数値を掛け算する。

random(100) * 0.1vw = 〇〇vw

大きさもランダムにできる

実はbox-shadowには、4つ目の数値がある。

4つ目は伸縮。それをランダムにすれば、いろんな大きさが作れる。

本体の青は、高さ200px にしたよ。

ここをクリックしてコードを見る
$max: 300;
$x: 0.1vw;
$y: 0.1vh;
$max_s: 50;
$s: -0.01rem;

.item {
 height: 200px;
 〜〜

  &::before {
   〜〜
   box-shadow: random($max) * -$x random($max) * -$y 0 random($max_s) * -$s yellow,
               〜〜; //同じ式をたくさん
  }

  &::after {
   〜〜
   box-shadow: random($max) * $x random($max) * $y 0 random($max_s) * -$s red,
               〜〜; //同じ式をたくさん
  }
}

【 Point 】

box-shadowには4つの数値が指定できる(最後の2つは省略可能)

「X方向の位置・Y方向の位置・ぼかし・伸縮」

box-shadow: 1px 1px 1px 1px color;

※4つ目の数値をランダムでマイナスにすれば、いろんな比率で小さくなる

いい感じのランダムになった。

でも、たくさん配置するのは、やっぱり大変。

補足:同じ式を何度も繰り返す場合は、 for関数が便利

for $i form 1 through $count は、Sass関数のなかで一番よく使うよ。

ここをクリックしてコードを見る
$shadow1:"";
$shadow2:"";
$count: 100;
$max: 300;

@for $i from 1 through $count {
 $shadow1: $shadow1 + random($max) * $x + " " + random($max) * $y + " " + 0 + " " + random(50) * -0.01rem +  " " + #fff;
 $shadow2: $shadow2 + random($max) * $x + " " + random($max) * $y + " " + 0 + " " + random(50) * -0.01rem +  " " +  #fff;
  @if $i < $count {
   $shadow1: $shadow1 + ",";
   $shadow2: $shadow2 + ",";
	}
}


.item {
  &::before {
   box-shadow: #{$shadow1};
  }

  &::after {
   box-shadow: #{$shadow2};
 }
}

ところで、奥行きも出してほしい。

filter: blur() で奥行きを出す

before と after で ぼかし具合を変えると奥行きっぽくなる

ここをクリックしてコードを見る
.item {
  &::before {
   filter: blur(0.5px);
  }

  &::after {
   filter: blur(2px);
 }
}

これなら雪にも使えそう。

【 Point 】

box-shadow の 3つ目の数値を使っても、ぼかしができる。

ただ、filter: blur() のほうが、アニメーションで変更できたりと使い勝手がいい。

※box-shadowをアニメーションに使うと、重くなる。

opacity で点滅させてみる

1個1個の円を個別で動かすことはできないけれど、

before と after を時間差にするだけでも、それっぽく見える。

ここをクリックしてコードを見る
.item {
  &::before,
  &::after {
   animation: star-anim 2s infinite alternate;
  }

  &::after {
   animation-delay: -1s;
  }
}


@keyframes star-anim {
 100% {
  opacity: .3;
 }
}

こっちが付いたら、向こうは消える。

animation-delayで調整すればいいんだ。

translate で移動させてみる

上から下でもいいけど、下から上の浮かび上がる感じも美しい。

ここをクリックしてコードを見る
@keyframes star-up {
  100% {
   transform: translateY(-200px);
 }
}

泡にも使えそう。

まとめ

box-shadowは1つで複数設置できる。

本体は bodyタグや mainタグ でもOKなので、疑似要素で星を作れば divタグも要らないよ。

  • box-shadowは、カンマ区切りで複数設置が可能
  • box-shadowの4つの数値の意味
    • 「X方向の位置・Y方向の位置・ぼかし・伸縮」
  • random()で、X・Y・伸縮をランダム指定
  • @for で繰り返し処理
  • filter: blur()でぼかして、奥行き表現
    • box-shadowのぼかしを使うより使い勝手がいい
  • before と after で違う数値にすれば、1つのクラスで2倍
ここをクリックしてコードを見る
<body class="c-stars">
  <main class="c-stars--02">
    〜〜
  </main>
</body>
$shadow1:"";
$shadow2:"";
$shadow3:"";
$shadow4:"";
$x: 0.1vw;
$y: 0.1vh;
$count: 100;
$max: 1000;
@for $i from 1 through $count {
 $shadow1: $shadow1 + random($max) * $x + " " + random($max) * $y + " " + 0 + " " + random(50) * -0.01rem +  " " + #fff;
 $shadow2: $shadow2 + random($max) * $x + " " + random($max) * $y + " " + 0 + " " + random(50) * -0.01rem +  " " +  #fff;
 $shadow3: $shadow3 + random($max) * $x + " " + random($max) * $y + " " + 0 + " " + random(50) * -0.01rem +  " " + yellow;
 $shadow4: $shadow4 + random($max) * $x + " " + random($max) * $y + " " + 0 + " " + random(50) * -0.01rem +  " " +  yellow;
  @if $i < $count {
		$shadow1: $shadow1 + ",";
		$shadow2: $shadow2 + ",";
		$shadow3: $shadow3 + ",";
		$shadow4: $shadow4 + ",";
	}
}

.c-stars {
 position: relative;

 &::before,
 &::after {
   position: absolute;
   content: '';
   top: 0;
   width: 10px;
   height: 10px;
   border-radius: 50%;
   background: #fff;
   animation-name: star1;
   animation-duration: 30s;
   animation-iteration-count: infinite;
   animation-direction: alternate;
	}

 &::before {
   box-shadow: #{$shadow1};
   filter: blur(1px);
 }
	
 &::after {
   box-shadow: #{$shadow2};
   filter: blur(1px);
   animation-delay: 1s;
 }
	
 &--02 {
  @extend .c-stars;
  &::before,
  &::after {
   width: 8px;
   height: 8px;
  }

  &::before {
   box-shadow: #{$shadow3};
   filter: blur(1px);
   animation-name: star2;
   animation-duration: 2s;
  }
		
  &::after {
   box-shadow: #{$shadow4};
   filter: blur(1px);
   animation-name: star2;
   animation-duration: 2s;
   animation-delay: 2s;
  }
 }
}

@keyframes star1 {
	100% {
		transform: translateY(-100vh);
	}
}
@keyframes star2 {
	100% {
		opacity: .2;
	}
}
bodyタグとmainタグでアニメーションを変える例

アニメーションをそれぞれ変えれば、いろんな星を量産することができるんだ。

雪にもなる

著者

author
月うさぎ

編集後記:
この記事の内容がベストではないかもしれません。

記事一覧