BASEプロダクトチームブログ

ネットショップ作成サービス「BASE ( https://thebase.in )」、ショッピングアプリ「BASE ( https://thebase.in/sp )」のプロダクトチームによるブログです。

HTML / CSS でショップに雪をふらせましょう ⛄

おや... このページにも雪がふってきましたね...

これは BASE Advent Calendar 2023 の1日目の記事です。

なんだかさいきん寒いなぁと思っていたら、ついに雪がふってきてしまいましたね!

このはらはらと舞い落ちる雪の結晶、HTML と CSS で作れちゃいます。

そして BASE には HTML 編集 App という機能があります。この機能を使うと...?

snowrry.base.shop

↑のデモショップのように、ショップに雪をふらせることができちゃいます!是非これからの季節に試してみてください ⛄

BASE ショップに雪をふらせる方法

まず HTML 編集 App の使い方については、こちらの BASE U の記事を参考に設定してください。

baseu.jp

今回は「テーマを編集する」機能を使ってショップに HTML と CSS を追加します。

HTML と CSS をテーマに追加する

「テーマを編集する」機能のエディタ画面

まずは CSS を追加します。head タグの中に以下の style タグをコピー&ペーストして貼り付けてください。

    <!-- === snow ここから追加 === -->
    <style>
        .snow-container {
            display: flex;
            position: fixed;
            width: 100vw;
            height: 100dvh;
            z-index: -1;
        }
        .snow-container .snow span,
        .snow-container .snow::before,
        .snow-container .snow::after {
            position: absolute;
            width: 100%;
            height: 100%;
            color: snow;
            text-align: center;
        }
        .snow-container .snow.small {
            font-size: 1.2rem;
            opacity: 1;
        }
        .snow-container .snow.medium {
            font-size: 1.4rem;
            opacity: 0.8;
        }
        .snow-container .snow.large {
            font-size: 1.6rem;
            opacity: 0.6;
        }

        .snow-container .snow.small span {
            display: block;
            animation: fall-small 7s linear infinite;
        }
        .snow-container .snow.small::before {
            content: "❄";
            left: -30%;
            animation: fall-small 9s linear infinite;
        }
        .snow-container .snow.small::after {
            content: "❄";
            left: 30%;
            animation: fall-small 13s linear infinite;
        }

        .snow-container .snow.medium span {
            display: block;
            left: 10%;
            animation: fall-medium 8s linear infinite;
        }
        .snow-container .snow.medium::before {
            content: "❄";
            left: -40%;
            animation: fall-medium 10s linear infinite;
        }
        .snow-container .snow.medium::after {
            content: "❄";
            left: 40%;
            animation: fall-medium 6s linear infinite;
        }

        .snow-container .snow.large span {
            display: block;
            left: -10%;
            animation: fall-large 5s linear infinite;
        }
        .snow-container .snow.large::before {
            content: "❄";
            left: -35%;
            animation: fall-large 6s linear infinite;
        }
        .snow-container .snow.large::after {
            content: "❄";
            left: 35%;
            animation: fall-large 7s linear infinite;
        }

        @keyframes fall-small {
            0% {
            top: -20px;
            }
            3% {
            transform: translateX(5px);
            }
            7% {
            transform: translateX(5px);
            }
            18% {
            transform: translateX(-5px);
            }
            22% {
            transform: translateX(-5px);
            }
            38% {
            transform: translateX(13px);
            }
            42% {
            transform: translateX(13px);
            }
            58% {
            transform: translateX(-13px);
            }
            62% {
            transform: translateX(-13px);
            }
            78% {
            transform: translateX(13px);
            }
            82% {
            transform: translateX(13px);
            }
            100% {
            top: calc(100% + 20px);
            }
        }

        @keyframes fall-medium {
            0% {
            top: -200px;
            }
            3% {
            transform: translateX(5px);
            }
            7% {
            transform: translateX(5px);
            }
            18% {
            transform: translateX(-5px);
            }
            22% {
            transform: translateX(-5px);
            }
            38% {
            transform: translateX(13px);
            }
            42% {
            transform: translateX(13px);
            }
            58% {
            transform: translateX(-13px);
            }
            62% {
            transform: translateX(-13px);
            }
            78% {
            transform: translateX(13px);
            }
            82% {
            transform: translateX(13px);
            }
            100% {
            top: calc(100% + 20px);
            }
        }

        @keyframes fall-large {
            0% {
            top: -300px;
            }
            3% {
            transform: translateX(5px);
            }
            7% {
            transform: translateX(5px);
            }
            18% {
            transform: translateX(-5px);
            }
            22% {
            transform: translateX(-5px);
            }
            38% {
            transform: translateX(13px);
            }
            42% {
            transform: translateX(13px);
            }
            58% {
            transform: translateX(-13px);
            }
            62% {
            transform: translateX(-13px);
            }
            78% {
            transform: translateX(13px);
            }
            82% {
            transform: translateX(13px);
            }
            100% {
            top: calc(100% + 20px);
            }
        }
    </style>
    <!-- === snow ここまで === -->

次に HTML を追加します。body タグの中(できれば要素の一番最初)に以下の div 要素をコピー&ペーストして貼り付けてください。

    <!-- === snow ここから追加 === -->
    <div class="snow-container">
        <div class="snow small"><span></span></div>
        <div class="snow medium"><span></span></div>
        <div class="snow large"><span></span></div>
    </div>
    <!-- === snow ここまで === -->

これで追加する HTML と CSS は以上です。

プレビューモードをみてみましょう。

「テーマを編集する」機能のプレビュー画面

はらはらと雪の結晶が落下していたら成功です。

保存して、現在ご利用中のテーマであれば変更内容をショップページに反映させましょう。

テーマに合わせて CSS を微調整する

例えばショップの背景が白っぽかったりする場合は、CSS を調整して雪の結晶の色を変えたりすることができます。

        .snow-container .snow span,
        .snow-container .snow::before,
        .snow-container .snow::after {
            position: absolute;
            width: 100%;
            height: 100%;
            color: snow; /* <- ここの色を好きなカラーコードに変える */
            text-align: center;
        }

元のCSSでは snow (カラーコード: #fffafa )が指定されていますが、ここを #87ceeb のような水色に変えることで雪の結晶の色を変えることができます。

落ちてくる速さや雪の結晶の大きさを変えたりなど、より高度なカスタマイズがしたいときも同じように CSS のプロパティの値を変えることで柔軟にスタイルを変えることができます。


以上がショップに雪をふらせる方法になります!

ここから下は実装についての細かいお話になるので、興味のある人は読んでみてください 🥳

HTML / CSS の解説

簡単に説明すると実要素としては3つ、それに ::before::after の疑似要素をプラスした合計9つの「❄」が、アニメーションで上から下にひらひらと落ちてくるといった内容になります。雪の結晶はランダムな感じにしたかったので small / medium / large を用意しました。

.snow-container の CSS

.snow-container は雪の結晶をまとめた親要素です。画面いっぱいに広がっています。

      .snow-container {
        display: flex; // 子要素の配置のために flex にする
        position: fixed; // 要素は固定!
        width: 100vw; // 横幅いっぱいにして
        height: 100dvh; // 縦幅も dvh をつかっていっぱいに
        z-index: -1; // 背景にふらせたいので -1 を指定
      }

.snow の CSS

.snow の中の span 要素と疑似要素が実際にふっている雪の結晶です。

      .snow-container .snow span,
      .snow-container .snow::before,
      .snow-container .snow::after {
        position: absolute;
        width: 100%;
        height: 100%;
        color: snow;
        text-align: center;
      }
      .snow-container .snow.small {
        font-size: 1.2rem; // 雪の結晶の大きさ
        opacity: 1; // 小さい雪は遠くにあるのではっきりと
      }
      .snow-container .snow.medium {
        font-size: 1.4rem;
        opacity: 0.8;
      }
      .snow-container .snow.large {
        font-size: 1.6rem;
        opacity: 0.6; // 大きい雪は近くにあるので薄めに
      }

small / medium / large それぞれの snow にアニメーションをつける

animation で指定している秒数と left で指定しているパーセンテージは全体でランダムな感じになるようにキメ打ちしてあります。JS を使うとここがもっとランダムな感じになったり、foreach とか使って端的に書けたりするのかなぁ。今回は HTML / CSS だけで作りたかったのでけっこう愚直な感じで書いていきました。

      .snow-container .snow.small span {
        display: block; // span は inline なので block に
        animation: fall-small 7s linear infinite; // animation をランダムな速さでつける
      }
      .snow-container .snow.small::before {
        content: "❄"; // 疑似要素の雪の結晶
        left: -30%; // ランダムな場所に設置
        animation: fall-small 9s linear infinite;
      }

落下アニメーションの中身

こちらも small / medium / large で0%のときの内容を変えています。これで落下タイミングが変わってきます。

ひらひら舞い落ちるアニメーションがカクカクしてしまわないような工夫を少ししています。

      @keyframes fall-small {
        0% {
          top: -20px; // 少し上らへんから落ちてくるように。ここも small / medium / large で開始位置を変えてランダムにしている
        }
        3% {
          transform: translateX(5px); // 5%10の倍数の%から±2%のあたりで同じ位置になるようにゆらゆらと
        }
        7% {
          transform: translateX(5px); // ↑の3%と同じ位置
        }
        18% {
          transform: translateX(-5px); // 20%の±2%で、↑の5pxと逆の-5px
        }
        22% {
          transform: translateX(-5px); // ↑の18%と同じ位置
        }
        38% {
          transform: translateX(13px); // 最初より大きめな揺れ幅に
        }
        42% {
          transform: translateX(13px); // ↑の38%と同じ位置
        }
        58% {
          transform: translateX(-13px);
        }
        62% {
          transform: translateX(-13px);
        }
        78% {
          transform: translateX(13px);
        }
        82% {
          transform: translateX(13px);
        }
        100% {
          top: calc(100% + 20px); // 少し下らへんまで落ちきるように
        }
      }

と、このような感じで CSS を書いていきました。CSS 書くの楽しいね ☺

BASE でショップを作るとこのように HTML / CSS が編集できるので、コーディング次第でカスタム性の高いサイトを作ることができます。

以上、最後まで読んでいただきありがとうございました!今年の冬はぜひインターネットに雪をふらせてみてください ❄

明日は 大津さん の記事です。お楽しみに〜!🎄