Webサイトにクーラーを取り付けて暑い夏を乗り切る!!

UI開発者 板垣

もうすぐ7月、梅雨も明ければ夏本番ですね。みなさまは来る夏に向けて暑さ対策の準備はしていますか?
例年、日傘や帽子を使って日差しをよけたり、手持ちの本で扇いで少しでも風をあびたりと、いろいろな方法で暑さ対策している方々を見かけます。
今回、それらの方法とは打って変わったWebエンジニアならではの新しい暑さ対策を考えてみました。

私が考えた暑さ対策とは、タイトルにある通り「Webサイトにクーラーを設置する」です。
クーラーに模した要素をWebサイトに設置し、そこから涼しげな雰囲気を視覚に与えればプラシーボ効果で体温を下げられそう!という安易な考えから生まれた方法です。
なんとも無謀そうではありますが、何事も試してみないことには結果はわかりませんのでまずは作っていきましょう!

完成イメージ

一般家庭によくあるような形状のクーラーをHTMLとCSSを使って3D的に作成します。

HTML

<div class="airConditioner">
    <div class="airConditioner-inr">
        <div class="front-panel-top"></div>
        <div class="front-panel-bottom">
            <div class="front-panel-bottom__cover"></div>
        </div>
        <div class="side-panel-top"></div>
        <div class="side-panel-bottom"></div>
    </div>
</div>

各要素の役割について説明します。

.airConditioner
幅や高さの基準となる要素で、最終的な位置はこの要素に記述します。
.airConditioner-inr
要素全体の傾きを指定する要素です。
.front-panel-top
前面(上側)パネル用の要素です。
.front-panel-bottom
前面(下側)パネル用の要素です。
.front-panel-bottom__cover
風が出てくる穴をふさいでいる蓋用の要素です。
.side-panel-top
左側面(上側)のパネル用の要素です。
.side-panel-bottom
左側面(下側)のパネル用の要素です。

CSS

:root{--mainColor:#EEEEEE;--subColor:#BDBDBD;--airColor:179,229,252;--shadowRgb:97,97,97}.airConditioner{width:250px;height:80px;position:fixed;left:100px;top:60px;transform:perspective(280px);transform-style:preserve-3d}.airConditioner *,.airConditioner ::after,.airConditioner ::before{transform-style:preserve-3d}.airConditioner-inr{width:100%;height:100%;position:relative;transform:rotateX(10deg) rotateY(41deg)}.airConditioner-inr *,.airConditioner-inr ::after,.airConditioner-inr ::before{position:absolute}.front-panel-top{width:100%;height:100%;background:var(--mainColor);border-left:1px solid var(--subColor);box-shadow:-50px -10px 30px -10px rgba(var(--shadowRgb),.1) inset;top:0;left:0}.front-panel-top::before{content:"";width:100%;height:101.2132034356px;box-shadow:-10px 25px 60px 0 rgba(var(--shadowRgb),.3),-10px 0 10px 0 rgba(var(--shadowRgb),.2),-1px 1px 5px 0 rgba(var(--shadowRgb),.8);display:block;transform:translate3d(0,0,-60px)}.front-panel-top::after{content:"";background:url(https://www.mitsue.co.jp/cmn/img/logo.png) left top/100% no-repeat;width:80px;height:14.0206186px;display:block;left:10px;bottom:5px;transform:translate3d(0,0,1px)}.front-panel-bottom{width:100%;height:30px;background:var(--mainColor);border-left:1px solid var(--subColor);top:100%;left:50%;transform-origin:top center;transform:rotateX(-45deg) translate(-50%);box-shadow:0 0 30px 0 rgba(var(--shadowRgb),.5) inset}.front-panel-bottom::before{content:"";width:80%;height:18px;display:block;box-shadow:3px 3px 12px 5px rgba(66,66,66,1) inset;left:5%;top:50%;border-radius:5px;transform:translateY(-50%)}.front-panel-bottom::after{content:"";width:50%;height:60%;box-shadow:0 0 10px 10px rgba(var(--airColor),.4),0 0 20px 20px rgba(var(--airColor),.8);display:block;background:rgba(var(--airColor),1);left:50%;top:50%;border-radius:5px;transform:translate(-50%,-50%) rotateX(90deg);animation:airAnime 10s linear 0s infinite}@keyframes airAnime{0%{opacity:0}29%{opacity:0}30%{transform:translate3d(-50%,-50%,-50px) rotateX(90deg) scale(1);opacity:.8}70%{transform:translate3d(-50%,-50%,20px) rotateX(90deg) scale(1.6);opacity:.6}100%{transform:translate3d(-50%,-50%,30px) rotateX(90deg) scale(2);opacity:0}}.front-panel-bottom__cover{width:80%;height:60%;background:var(--mainColor);border:1px solid var(--subColor);left:5%;top:50%;border-radius:5px;transform-origin:bottom center;transform:translate3d(0,50%,.5px);animation:coverAnime 10s linear 0s infinite;box-shadow:0 0 30px 0 rgba(var(--shadowRgb),.3) inset}@keyframes coverAnime{0%{transform:translate3d(0,-50%,1px) rotateX(0)}10%{transform:translate3d(0,-50%,1px) rotateX(0)}30%{transform:translate3d(0,-50%,1px) rotateX(-80deg)}80%{transform:translate3d(0,-50%,1px) rotateX(-80deg)}100%{transform:translate3d(0,-50%,1px) rotateX(0)}}.side-panel-top{width:60px;height:100%;background:var(--mainColor);left:0;top:0;transform-origin:right center;transform:rotateY(-90deg) translate3d(0,0,60px);border-left:20px solid var(--subColor);box-sizing:border-box;box-shadow:10px -10px 10px -5px rgba(var(--shadowRgb),.1) inset}.side-panel-bottom{display:block;width:60px;height:21.2132034356px;left:0;top:100%;transform-origin:right center;transform:rotateY(-90deg) translate3d(0,0,60px);overflow:hidden}.side-panel-bottom::before{content:"";display:block;width:100%;height:100%;background:var(--mainColor);box-sizing:border-box;left:-10px;top:0;transform-origin:right center;transform:skew(-45deg);border-left:20px solid var(--subColor);box-shadow:0 0 10px 10px rgba(var(--shadowRgb),.1) inset}

HTMLと比べるとCSSは少し長いですが、やっていることはあまり難しくありません。そのためポイントを絞ってコードについて説明します。

3D表現

.airConditioner {
    ...
    transform: perspective(280px);
    transform-style: preserve-3d;
}

.airConditioner * {
    transform-style: preserve-3d;
}

今回の肝と言っても過言ではない3D表現ですが、この表現をするにあたって.airConditionertransform: perspective(280px);transform-style: preserve-3d;を付与しています。
また、.airConditionerの子要素すべてに対してもtransform-style: preserve-3d;を付与しています。
まずtransformプロパティのperspective()関数についてですが、このプロパティを使うと遠近感を表現することが可能になります。数値が低くなれば遠近感が強くなり、逆に大きくなると遠近感が弱くなります。
perspectiveという名前が似ているプロパティもありますが、挙動が少し異なるので注意が必要です。
続いて、transform-styleプロパティですが、preserve-3dを使うと付与された要素の子要素を立体的に表示することが可能になります。
今回はtransformプロパティを使って各要素の位置変更や変形を多くするため.airConditionerの子要素すべてに対してtransform-style: preserve-3d;を付与しています。

要素の背後にある影

.front-panel-top::before {
    content: "";
    width: 100%;
    height: 101.2132034356px;
    box-shadow: -10px 25px 60px 0px rgba(var(--shadowRgb), 0.3), -10px 0px 10px 0px rgba(var(--shadowRgb), 0.2), -1px 1px 5px 0px rgba(var(--shadowRgb), 0.8);
    display: block;
    transform: translate3d(0, 0, -60px);
}

要素の背後に影が付いていることにお気づきでしょうか?
この影は.front-panel-topのbefore疑似要素にbox-shadowプロパティを3重にして付けています。 heightの数値は.front-panel-top.front-panel-bottomの高さを足したものになっています。

吹いている風

.front-panel-bottom::after {
    content: "";
    width: 50%;
    height: 60%;
    box-shadow: 0 0 10px 10px rgba(var(--airColor), 0.4), 0 0 20px 20px rgba(var(--airColor), 0.8);
    display: block;
    background: rgba(var(--airColor), 1);
    left: 50%;
    top: 50%;
    border-radius: 5px;
    transform: translate(-50%, -50%) rotateX(90deg);
    animation: airAnime 10s linear 0s infinite;
}

@keyframes airAnime {
    0% {
        opacity: 0;
    }
    29% {
        opacity: 0;
    }
    30% {
        transform: translate3d(-50%, -50%, -50px) rotateX(90deg) scale(1);
        opacity: 0.8;
    }
    70% {
        transform: translate3d(-50%, -50%, 20px) rotateX(90deg) scale(1.6);
        opacity: 0.6;
    }
    100% {
        transform: translate3d(-50%, -50%, 30px) rotateX(90deg) scale(2);
        opacity: 0;
    }
}

この風は.front-panel-bottomのafter疑似要素で作成していて、風がWebサイト全体に広がっていくようなアニメーションを付けています。
風の色をコマーシャルでよく使われる青色にすることでヒンヤリ感を倍増させています。

まとめ

近いうちに、ボタンひとつでWebサイトにクーラーが出てくるエクステンションを作って、実際にこの対策が有効なのかを試そうと思います。
今回ご紹介した方法はまだ実験段階なので、みなさまはしっかりとした方法で暑さ対策を行ってくださいね!