
Bootstrap5 でDark Mode切り替えのサイトを作る
前置き
最近Bootstrap5をずっと触ってます、alpha1ではありますが、バージョン4に比べて柔軟性が上がりました、中でも個人的にとても良かったのはUtility APIとjQueryの排除ですね。 前まではわざわざcssクラスを書かないとカスタマイズがあまり効かないBootstrapでしたが、バージョン5 からUtility APIを使えばSass関数使うだけで自由にレスポンシブ可能なクラスが追加できるので、とても便利です。 もう一つはjQueryですね、プロジェクトでは全く使わないのに、Bootstrapを入れたらついて来るというのがとても嫌でした、今回それも解決されました。
さて本題ですが、今回はBootstrap5を使いながらダークモードに切り替えられる簡単なサイトを作ってみようと思います、もう新しい技術ではないですが、既にjsのライブラリとか出てますが、ライブラリ使わずに考え方だけ欲しい人向けに書き残しておきたいと思います。
環境
node.js及びnpmのインストール (なくても大丈夫)
VScodeの拡張機能live sass compilerをインストール
構築
npm init -y
package.jsonファイルを作成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
ダウンロードしても大丈夫ですトップディレクトリにindex.htmlファイルを作成
ディレクトリ構成
sun.svg
は使いませんので無視してください😅、紛らわしくてすみません。
サイトレイアウト
考え方
bodyタグにdata-themeという属性を付ける
事前にsassで属性セレクトを使ってダークモードの時のスタイルを設定しておく
body[data-theme="dark"]{ background-color:black }
👈こんな感じ属性の切り替えで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">©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
}
});
}
レビュー
デモサイト -> bootstrap5-dark-mode-swtich.netlify.app
ではまた!