LoginSignup
6
4

More than 5 years have passed since last update.

CSSのみで動くグリッチエフェクトをデザインする

Posted at

グリッチエフェクトってかっこよくない?

あのブラウン管に写ったジャギジャギチカチカした感じのことをグリッチエフェクトといいます。
不穏なイメージや怪しいイメージにピッタリのエフェクトですが
そんなエフェクトをCSSだけで実装していきます!

まずは完成品を

gifanimation.gif
これをなんとかしてCSSでデザインしてみます。
理屈は結構簡単です。

まずは土台を作る

index.html
<!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>
style.css
#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;
}

実行するとこんな感じになります
SnapCrab_NoName_2018-12-29_16-24-3_No-00.png
一見普通のテキストですが、実際には同じテキスト5つが重なっています。
#noise_box内の.blockposition:absoluteが掛かっているためですね。
ではこれをベースに手を加えていきます。

テキストを横に分割する

style.css
#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);
}

実行するとこんな感じになります。
SnapCrab_NoName_2018-12-29_16-28-41_No-00.png
テキストが横に分割されて理解しやすいように色を付けました。
どういった仕組みかというと
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にします。

分割したそれぞれにエフェクトを掛けていく

style.css
#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);
}

実行するとこんな感じになります。
gifanimation.gif
仕組みを解説すると
分割したそれぞれの.blockanimationで動きを付けています。

グリッチエフェクトっぽくアニメーションするために
・ズレた動きをするの%を小数点単位で指定し一瞬になるようにする。
・ズレたときに色を変えるためにfilter:hue-rotate(90deg) invert(70%);などフィルターを掛ける。
・他の.blockとアニメーションが被らないようにanimation-durationanimation-directionをバラバラに指定する。
ようにしています。

もっとリアリティを出すためにtransform:skew()なんてのも掛けても良いかもしれませんね。

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4