【CSS】だけで星をたくさん作る方法[JSやdivタグ不要]
記事更新日:2022-01-31
星を作りたい。
でも、JavaScriptは 使いたくない。
それなら、CSSの 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;
}
}
アニメーションをそれぞれ変えれば、いろんな星を量産することができるんだ。
2022-01-31
編集後記:
この記事の内容がベストではないかもしれません。