グリッチエフェクトってかっこよくない?
あのブラウン管に写ったジャギジャギチカチカした感じのことをグリッチエフェクトといいます。
不穏なイメージや怪しいイメージにピッタリのエフェクトですが
そんなエフェクトをCSSだけで実装していきます!
まずは完成品を
これをなんとかしてCSSでデザインしてみます。
理屈は結構簡単です。
まずは土台を作る
<!DOCTYPE html>
<html>
<head>
<title>ノイズアニメーション</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="noise_box">
<div class="block">
<span>9時間9人9の扉</span>
</div>
<div class="block">
<span>9時間9人9の扉</span>
</div>
<div class="block">
<span>9時間9人9の扉</span>
</div>
<div class="block">
<span>9時間9人9の扉</span>
</div>
<div class="block">
<span>9時間9人9の扉</span>
</div>
</div>
</body>
</html>
#noise_box{
--noise_box_height:100px;
position:relative;
top:500px;
left:500px;
width:500px;
height:var(--noise_box_height);
font-size:72px;
color:#FFFFFF;
background:#000000;
}
.block{
overflow:hidden;
position:absolute;
left:0px;
width:100%;
height:100%;
}
.block>span{
display:inline-block;
position:absolute;
left:0px;
width:100%;
line-height:var(--noise_box_height);
text-align:center;
}
実行するとこんな感じになります
一見普通のテキストですが、実際には同じテキスト5つが重なっています。
#noise_box
内の.block
にposition:absolute
が掛かっているためですね。
ではこれをベースに手を加えていきます。
テキストを横に分割する
#noise_box{
--noise_box_height:100px;
position:relative;
top:500px;
left:500px;
width:500px;
height:var(--noise_box_height);
font-size:72px;
color:#FFFFFF;
background:#000000;
}
.block{
overflow:hidden;
position:absolute;
left:0px;
width:100%;
height:100%;
}
.block>span{
display:inline-block;
position:absolute;
left:0px;
width:100%;
line-height:var(--noise_box_height);
text-align:center;
}
.block:nth-child(1){
top:calc(var(--noise_box_height) * 0);
height:calc(var(--noise_box_height) * 0.3);
color:#FFFFFF;
}
.block:nth-child(1)>span{
top:calc(var(--noise_box_height) * -0);
}
.block:nth-child(2){
top:calc(var(--noise_box_height) * 0.3);
height:calc(var(--noise_box_height) * 0.1);
color:#FF0000;
}
.block:nth-child(2)>span{
top:calc(var(--noise_box_height) * -0.3);
}
.block:nth-child(3){
top:calc(var(--noise_box_height) * 0.4);
height:calc(var(--noise_box_height) * 0.2);
color:#00FF00;
}
.block:nth-child(3)>span{
top:calc(var(--noise_box_height) * -0.4);
}
.block:nth-child(4){
top:calc(var(--noise_box_height) * 0.6);
height:calc(var(--noise_box_height) * 0.1);
color:#0000FF;
}
.block:nth-child(4)>span{
top:calc(var(--noise_box_height) * -0.6);
}
.block:nth-child(5){
top:calc(var(--noise_box_height) * 0.7);
height:calc(var(--noise_box_height) * 0.3);
color:#FFFFFF;
}
.block:nth-child(5)>span{
top:calc(var(--noise_box_height) * -0.7);
}
実行するとこんな感じになります。
テキストが横に分割されて理解しやすいように色を付けました。
どういった仕組みかというと
5つの同じテキストの高さをそれぞれ縮めて、他の.block
の縮めた分の位置を調整して、さらに中のspan
の位置を調整を調整してます。
例えば1つ目の.block
で言えば
.block
の高さを100px*0.3=30pxにして
1つ目より前の.block
の高さを考慮してtop:0px
にして
中のspan
の位置をtop:0px
にします。
さらに例えば3つ目の.block
で言うなら
.block
の高さを100px*0.2=20pxにして
3つ目より前の.block
の高さ(30px+10px)を考慮してtop:40px
にして
中のspan
の位置をtop:-40px
にします。
分割したそれぞれにエフェクトを掛けていく
#noise_box{
--noise_box_height:100px;
position:relative;
top:500px;
left:500px;
width:500px;
height:var(--noise_box_height);
font-size:72px;
color:#FF8800;
background:#000000;
}
.block{
overflow:hidden;
position:absolute;
left:0px;
width:100%;
height:100%;
}
.block>span{
display:inline-block;
position:absolute;
left:0px;
width:100%;
line-height:var(--noise_box_height);
text-align:center;
}
@keyframes noise_animation{
0%{left:0px;}
10%{left:0px;filter:none;}10.25%{left:30px;filter:hue-rotate(90deg) invert(70%);}10.5%{left:0px;filter:none;}
70%{left:0px;filter:none;}70.25%{left:-30px;filter:hue-rotate(270deg) invert(30%);}70.5%{left:0px;filter:none;}
100%{left:0px;}
}
.block:nth-child(1){
top:calc(var(--noise_box_height) * 0);
height:calc(var(--noise_box_height) * 0.3);
}
.block:nth-child(1)>span{
top:calc(var(--noise_box_height) * -0);
animation:noise_animation 11s linear alternate infinite;
}
.block:nth-child(2){
top:calc(var(--noise_box_height) * 0.3);
height:calc(var(--noise_box_height) * 0.1);
}
.block:nth-child(2)>span{
top:calc(var(--noise_box_height) * -0.3);
animation:noise_animation 10s linear infinite;
}
.block:nth-child(3){
top:calc(var(--noise_box_height) * 0.4);
height:calc(var(--noise_box_height) * 0.2);
}
.block:nth-child(3)>span{
top:calc(var(--noise_box_height) * -0.4);
animation:noise_animation 9s linear infinite;
}
.block:nth-child(4){
top:calc(var(--noise_box_height) * 0.6);
height:calc(var(--noise_box_height) * 0.1);
}
.block:nth-child(4)>span{
top:calc(var(--noise_box_height) * -0.6);
animation:noise_animation 11s linear reverse infinite;
}
.block:nth-child(5){
top:calc(var(--noise_box_height) * 0.7);
height:calc(var(--noise_box_height) * 0.3);
}
.block:nth-child(5)>span{
top:calc(var(--noise_box_height) * -0.7);
}
実行するとこんな感じになります。
仕組みを解説すると
分割したそれぞれの.block
にanimation
で動きを付けています。
グリッチエフェクトっぽくアニメーションするために
・ズレた動きをするの%を小数点単位で指定し一瞬になるようにする。
・ズレたときに色を変えるためにfilter:hue-rotate(90deg) invert(70%);
などフィルターを掛ける。
・他の.block
とアニメーションが被らないようにanimation-duration
やanimation-direction
をバラバラに指定する。
ようにしています。
もっとリアリティを出すためにtransform:skew()
なんてのも掛けても良いかもしれませんね。