blog post cover image

Bootstrap5 でDark Mode切り替えのサイトを作る

投稿日付:10/1/2022
1

前置き


最近Bootstrap5をずっと触ってます、alpha1ではありますが、バージョン4に比べて柔軟性が上がりました、中でも個人的にとても良かったのはUtility APIとjQueryの排除ですね。 前まではわざわざcssクラスを書かないとカスタマイズがあまり効かないBootstrapでしたが、バージョン5 からUtility APIを使えばSass関数使うだけで自由にレスポンシブ可能なクラスが追加できるので、とても便利です。 もう一つはjQueryですね、プロジェクトでは全く使わないのに、Bootstrapを入れたらついて来るというのがとても嫌でした、今回それも解決されました。

さて本題ですが、今回はBootstrap5を使いながらダークモードに切り替えられる簡単なサイトを作ってみようと思います、もう新しい技術ではないですが、既にjsのライブラリとか出てますが、ライブラリ使わずに考え方だけ欲しい人向けに書き残しておきたいと思います。

環境


  1. node.js及びnpmのインストール (なくても大丈夫)

  2. VScodeの拡張機能live sass compilerをインストール

構築


  1. npm init -y package.jsonファイルを作成

  2. npm i bootstrap@next をたたく、今回はnpmを使ってインストールします。Bootstrap公式からソースファイル -> https://v5.getbootstrap.jp/docs/5.0/getting-started/download/#%E3%82%BD%E3%83%BC%E3%82%B9%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB ダウンロードしても大丈夫です

  3. トップディレクトリにindex.htmlファイルを作成

ディレクトリ構成


ファイルディレクトリ sun.svg は使いませんので無視してください😅、紛らわしくてすみません。

サイトレイアウト


layout

考え方


  1. bodyタグにdata-themeという属性を付ける

  2. 事前にsassで属性セレクトを使ってダークモードの時のスタイルを設定しておく body[data-theme="dark"]{ background-color:black } 👈こんな感じ

  3. 属性の切り替えでcssスタイルが上書きされるもしくは無効になる


index.html


<!DOCTYPE html>
<html lang="ja" class="h-100">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="./css/main.css">
    <title>
        Bootstrap5 dark mode
    </title>
</head>
<body data-theme class="h-100">

<main class="h-100 d-flex flex-column">
    <div class="banner-wrapper flex-grow-1">
        <div class="container h-100">
            <div class="banner h-100 d-flex align-items-center justify-content-center">
                <div class="logo">
                    <img src="./img/bootstrap-icon.png" alt="">
                </div>
            </div>
        </div>
    </div>
    <nav class="navbar">
        <div class="container my-4 justify-content-center">
            <div class="form-check form-switch">
                <input class="form-check-input" type="checkbox" id="darkModaSwticher">
                <label class="form-check-label" for="darkModaSwticher">swtich</label>
            </div>
        </div>
    </nav>
    <div class="content py-5">
        <div class="container">
            <section class="my-3">
                <div class="section-title">
                    <h2 class="text-center mt-2 mb-4">Cards</h2>
                </div>
                <div class="row g-4">
                    <div class="col-4">
                        <div class="card shadow">
                            <div class="card-body">
                                <div class="card-text">
                                    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Quidem ipsum consequuntur dolorum, dignissimos minus id. Veritatis saepe esse modi! Cumque error nobis adipisci maiores laudantium quam aliquam veniam quas saepe.</p>
                                </div>
                            </div>
                            <div class="card-image">
                                <img src="" alt="">
                            </div>
                        </div>
                    </div>

                    <div class="col-4">
                        <div class="card shadow">
                            <div class="card-body">
                                <div class="card-text">
                                    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Quidem ipsum consequuntur dolorum, dignissimos minus id. Veritatis saepe esse modi! Cumque error nobis adipisci maiores laudantium quam aliquam veniam quas saepe.</p>
                                </div>
                            </div>
                            <div class="card-image">
                            </div>
                        </div>
                    </div>

                    <div class="col-4">
                        <div class="card shadow">
                            <div class="card-body">
                                <div class="card-text">
                                    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Quidem ipsum consequuntur dolorum, dignissimos minus id. Veritatis saepe esse modi! Cumque error nobis adipisci maiores laudantium quam aliquam veniam quas saepe.</p>
                                </div>
                            </div>
                            <div class="card-image">
                                <img src="" alt="">
                            </div>
                        </div>
                    </div>
                </div>
            </section>
            <section class="my-3">
                <div class="section-title">
                    <h2 class="text-center mt-4 mb-3">
                        Form
                    </h2>
                </div>
                <form class="w-75 mx-auto">
                    <div class="mb-3">
                        <label for="name" class="form-label">Name</label>
                        <input type="text" name="name" id="name" class="form-control">
                    </div>
                    <div class="mb-3">
                        <label for="email" class="form-label">E-mail</label>
                        <input type="text" name="email" id="email" class="form-control">
                    </div>
                    <div class="mb-3">
                        <label for="subject" class="form-label">Subject</label>
                        <textarea name="subject" id="subject" class="form-control" cols="30" rows="10"></textarea>
                    </div>
                    <div class="mb-3">
                        <button type="submit" class="btn btn-primary w-100">Submit</button>
                    </div>
                </form>
            </section>
        </div>
    </div>
    <footer class="text-center">
        <h2 class="text-center my-4">footer</h2>
        <small class="text-muted">&copy;2020</small>
    </footer>
</main>
<script src="./js/main.js"></script>
</body>
</html>

main.scssにnode_modulesからbootstrapのsassをimportする

今回は使わないですが、Utility APIに興味ある人はみて見てください Bootstrap5 Utility API https://v5.getbootstrap.jp/docs/5.0/utilities/api/

main.scss



/* botstrapのsassをインポート */
@import '../node_modules/bootstrap/scss/bootstrap.scss';

/* ボタンの色 */
$b5-purple: #6B10F3;
$b5-dark-purple: #5b0ece;

/* ダークモードになった時のスタイル */
body[data-theme="dark"] {
    background-color: #212121;
    h1,h2,h3,h4,h5{
        color: rgba(255, 255, 255, 0.80);
    }
    footer{
        background-color: #121212 ;
    }
    .form-check{
        color: white !important;
    }
    .banner-wrapper{
        background-image: unset;
        background-color: #121212;
    }
    .card{
        background-color: #272727;
        color: rgba(255, 255, 255, 0.603);
        .card-image{
            opacity: 60%;
        }
    }
    .shadow{
        box-shadow: 0px 3px 8px 5px black;
    }
    form{
        .form-label,.form-control{
            color: rgba(255,255,255,0.60);
        }
        .form-control{
            background-color: #272727 ;
            border-color: #121212;
        }
        button{
            background-color: $b5-purple;
            border-color: $b5-purple;
            outline: $b5-purple;
            &:hover{
                background-color: $b5-dark-purple;
                border-color: $b5-dark-purple;
            outline: $b5-dark-purple;
            }
        }
    }

}

/* サイトのレイアウトに必要なスタイル */
body{
    .banner-wrapper{
        background-image: url("../img/background.png");
        background-size: cover;
        background-position: center;
        min-height: 540px;
    }
    .content{
        .card{
            .card-image{
                height: 150px;
                background: lightgray;
            }
        }
    }
    section{
        min-height: 580px;
    }
    footer{
        min-height: 150px;
    }
}

main.js


    window.onload = () => {
        let bodyTag = document.querySelector("body");
        let swticher = document.querySelector('#darkModaSwticher');
        let isDark = false;
        swticher.addEventListener('change', () => {
            if(!isDark){
                bodyTag.setAttribute('data-theme', 'dark');
                isDark = true;
            }else{
                bodyTag.removeAttribute('data-theme');
                isDark = false
            }
        });
    }


レビュー


review

デモサイト -> bootstrap5-dark-mode-swtich.netlify.app

ではまた!