Toggle light and dark themes in Bootstrap - DEV
<div data-article-id="458402" id="article-body" readability="112.219948437"> <p>In this article we will learn how we can easily toggle between light and dark theme.</p> <p>While <a href="https://getbootstrap.com/docs/4.5/getting-started/theming/" style="color: inherit; text-decoration: none;" name="readabilityLink-1">theming in Bootstrap</a><a href="#readabilityFootnoteLink-1" class="readability-DoNotFootnote" style="color: inherit;"><small><sup>[1]</sup></small></a> can be done through it's built-in SASS variables, for this article we are going to use provided css stylesheets.</p> <p><a href="https://bootswatch.com/" style="color: inherit; text-decoration: none;" name="readabilityLink-2">Bootswatch</a><a href="#readabilityFootnoteLink-2" class="readability-DoNotFootnote" style="color: inherit;"><small><sup>[2]</sup></small></a> has some great themes, we're going to use it's <a href="https://bootswatch.com/cyborg/" style="color: inherit; text-decoration: none;" name="readabilityLink-3">Cyborg</a><a href="#readabilityFootnoteLink-3" class="readability-DoNotFootnote" style="color: inherit;"><small><sup>[3]</sup></small></a> theme for darker variant. And for light, we are going to use Bootstrap's default theme.</p> <p>So, let's get started.</p> <h2> <a name="create-project-folder-and-raw-indexhtml-endraw-file" href="#create-project-folder-and-raw-indexhtml-endraw-file" class="anchor"> </a> Create project folder and <code>index.html</code> file </h2> <div class="highlight" readability="7"><pre class="highlight shell"><code><span class="nb">mkdir </span>toggle-bootstrap-theme <span class="nb">cd </span>toggle-bootstrap-theme </code></pre></div> <p>Create the <code>index.html</code> file in it:<br/></p> <div class="highlight" readability="16"><pre class="highlight html"><code><span class="cp"><!DOCTYPE html></span> <span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span> <span class="nt"><head></span> <span class="c"><!-- Required meta tags --></span> <span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span> <span class="nt">/></span> <span class="nt"><meta</span> <span class="na">name=</span><span class="s">"viewport"</span> <span class="na">content=</span><span class="s">"width=device-width, initial-scale=1, shrink-to-fit=no"</span> <span class="nt">/></span> <span class="c"><!-- Bootstrap CSS --></span> <span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">href=</span><span class="s">"https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"</span> <span class="na">integrity=</span><span class="s">"sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z"</span> <span class="na">crossorigin=</span><span class="s">"anonymous"</span> <span class="nt">/></span> <span class="c"><!-- 🚨 Notice this link --></span> <span class="nt"><link</span> <span class="na">id=</span><span class="s">"dark-theme-style"</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="nt">/></span> <span class="nt"><title></span>Toggle Bootstrap Theme<span class="nt"></title></span> <span class="nt"></head></span> <span class="nt"><body></span> <span class="nt"><nav</span> <span class="na">class=</span><span class="s">"navbar navbar-transparent"</span><span class="nt">></span> <span class="c"><!-- 🚨 Notice the toggleTheme() function --></span> <span class="nt"><a</span> <span class="na">href=</span><span class="s">"javascript:void()"</span> <span class="na">class=</span><span class="s">"btn btn-outline-info btn-lg ml-auto font-weight-bold"</span> <span class="na">id=</span><span class="s">"theme-toggler"</span> <span class="na">onclick=</span><span class="s">"toggleTheme()"</span> <span class="nt">></a></span> <span class="nt"></nav></span> <span class="nt"><div</span> <span class="na">class=</span><span class="s">"container-fluid"</span><span class="nt">></span> <span class="nt"><div</span> <span class="na">class=</span><span class="s">"jumbotron"</span><span class="nt">></span> <span class="nt"><h1</span> <span class="na">class=</span><span class="s">"display-4"</span><span class="nt">></span>Hello, world!<span class="nt"></h1></span> <span class="nt"><p</span> <span class="na">class=</span><span class="s">"lead"</span><span class="nt">></span> This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information. <span class="nt"></p></span> <span class="nt"><hr</span> <span class="na">class=</span><span class="s">"my-4"</span> <span class="nt">/></span> <span class="nt"><p></span> It uses utility classes for typography and spacing to space content out within the larger container. <span class="nt"></p></span> <span class="nt"><a</span> <span class="na">class=</span><span class="s">"btn btn-primary btn-lg"</span> <span class="na">href=</span><span class="s">"#"</span> <span class="na">role=</span><span class="s">"button"</span><span class="nt">></span>Learn more<span class="nt"></a></span> <span class="nt"></div></span> <span class="nt"></div></span> <span class="c"><!-- Optional JavaScript --></span> <span class="c"><!-- jQuery first, then Popper.js, then Bootstrap JS --></span> <span class="nt"><script </span><span class="na">src=</span><span class="s">"https://code.jquery.com/jquery-3.5.1.slim.min.js"</span> <span class="na">integrity=</span><span class="s">"sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"</span> <span class="na">crossorigin=</span><span class="s">"anonymous"</span> <span class="nt">></script></span> <span class="nt"><script </span><span class="na">src=</span><span class="s">"https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"</span> <span class="na">integrity=</span><span class="s">"sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN"</span> <span class="na">crossorigin=</span><span class="s">"anonymous"</span> <span class="nt">></script></span> <span class="nt"><script </span><span class="na">src=</span><span class="s">"https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"</span> <span class="na">integrity=</span><span class="s">"sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV"</span> <span class="na">crossorigin=</span><span class="s">"anonymous"</span> <span class="nt">></script></span> <span class="c"><!-- 🚨 Our custom JavaScript --></span> <span class="nt"><script </span><span class="na">src=</span><span class="s">"index.js"</span><span class="nt">></script></span> <span class="nt"></body></span> <span class="nt"></html></span> </code></pre></div> <p>Notice these 2 snippet in above code:</p> <h3> <a name="-raw-ltlinkgt-endraw-to-dynamically-load-stylesheet" href="#-raw-ltlinkgt-endraw-to-dynamically-load-stylesheet" class="anchor"> </a> <code><link></code> to dynamically load stylesheet </h3> <div class="highlight" readability="7"><pre class="highlight html"><code><span class="nt"><link</span> <span class="na">id=</span><span class="s">"dark-theme-style"</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="nt">/></span> </code></pre></div> <p>Here, we will render dark theme stylesheet through JavaScript. Also note that we have kept this after our default stylesheet, so that if any rules is missing in dark one, it will be taken from default.</p> <h3> <a name="-raw-ltagt-endraw-to-toggle-themes" href="#-raw-ltagt-endraw-to-toggle-themes" class="anchor"> </a> <code><a></code> to toggle themes </h3> <div class="highlight" readability="8"><pre class="highlight html"><code><span class="nt"><a</span> <span class="na">href=</span><span class="s">"javascript:void()"</span> <span class="na">class=</span><span class="s">"btn btn-outline-info btn-lg ml-auto font-weight-bold"</span> <span class="na">id=</span><span class="s">"theme-toggler"</span> <span class="na">onclick=</span><span class="s">"toggleTheme()"</span> <span class="nt">></a></span> </code></pre></div> <p>This anchor tag will help user to toggle between light and dark theme. We are going to create function <code>toggleDark</code> in JavaScript. Let's see that.</p> <h2> <a name="create-raw-indexjs-endraw-file" href="#create-raw-indexjs-endraw-file" class="anchor"> </a> Create <code>index.js</code> file </h2> <div class="highlight" readability="15"><pre class="highlight javascript"><code><span class="c1">// you can use app's unique identifier here</span> <span class="kd">const</span> <span class="nx">LOCALSTORAGEKEY</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">toggle-bootstrap-theme</span><span class="dl">"</span><span class="p">;</span> <span class="kd">const</span> <span class="nx">LOCALMETADATA</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="nx">LOCALSTORAGEKEY</span><span class="p">));</span> <span class="c1">// you can change this url as needed</span> <span class="kd">const</span> <span class="nx">DARKTHEMEPATH</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">https://bootswatch.com/4/cyborg/bootstrap.min.css</span><span class="dl">"</span><span class="p">;</span> <span class="kd">const</span> <span class="nx">DARKSTYLELINK</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">dark-theme-style</span><span class="dl">"</span><span class="p">);</span> <span class="kd">const</span> <span class="nx">THEMETOGGLER</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">theme-toggler</span><span class="dl">"</span><span class="p">);</span> <span class="kd">let</span> <span class="nx">isDark</span> <span class="o">=</span> <span class="nx">LOCALMETADATA</span> <span class="o">&&</span> <span class="nx">LOCALMETADATA</span><span class="p">.</span><span class="nx">isDark</span><span class="p">;</span> <span class="c1">// check if user has already selected dark theme earlier</span> <span class="k">if</span> <span class="p">(</span><span class="nx">isDark</span><span class="p">)</span> <span class="p">{</span> <span class="nx">enableDarkTheme</span><span class="p">();</span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="nx">disableDarkTheme</span><span class="p">();</span> <span class="p">}</span> <span class="cm">/* Apart from toggling themes, this will also store user's theme preference in local storage. So when user visits next time, we can load the same theme. */</span> <span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span> <span class="nx">isDark</span> <span class="o">=</span> <span class="o">!</span><span class="nx">isDark</span><span class="p">;</span> <span class="k">if</span> <span class="p">(</span><span class="nx">isDark</span><span class="p">)</span> <span class="p">{</span> <span class="nx">enableDarkTheme</span><span class="p">();</span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="nx">disableDarkTheme</span><span class="p">();</span> <span class="p">}</span> <span class="kd">const</span> <span class="nx">META</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">isDark</span> <span class="p">};</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="nx">LOCALSTORAGEKEY</span><span class="p">,</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">META</span><span class="p">));</span> <span class="p">}</span> <span class="kd">function</span> <span class="nx">enableDarkTheme</span><span class="p">()</span> <span class="p">{</span> <span class="nx">DARKSTYLELINK</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="dl">"</span><span class="s2">href</span><span class="dl">"</span><span class="p">,</span> <span class="nx">DARKTHEMEPATH</span><span class="p">);</span> <span class="nx">THEMETOGGLER</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">🌙 Dark</span><span class="dl">"</span><span class="p">;</span> <span class="p">}</span> <span class="kd">function</span> <span class="nx">disableDarkTheme</span><span class="p">()</span> <span class="p">{</span> <span class="nx">DARKSTYLELINK</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="dl">"</span><span class="s2">href</span><span class="dl">"</span><span class="p">,</span> <span class="dl">""</span><span class="p">);</span> <span class="nx">THEMETOGGLER</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">🌞 Light</span><span class="dl">"</span><span class="p">;</span> <span class="p">}</span> </code></pre></div> <p>I believe that above code is self-explanatory 😉 and no further explanation is required.</p> <h2> <a name="output" href="#output" class="anchor"> </a> Output </h2> <p>After successfully writing all of the above code, you can simply open <code>index.html</code> in browser to see the output:</p> <p><a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XqVp8zPN--/climit%2Cfauto%2Cflprogressive%2Cq66%2Cw880/https://dev-to-uploads.s3.amazonaws.com/i/wz02lai43ksyzymbfd5c.gif" class="article-body-image-wrapper"><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XqVp8zPN--/climit%2Cfauto%2Cflprogressive%2Cq66%2Cw880/https://dev-to-uploads.s3.amazonaws.com/i/wz02lai43ksyzymbfd5c.gif" alt="Toggle Bootstrap Theme output" loading="lazy"/></a></p> <blockquote readability="8"> <p>👉 The http call to dark stylesheet is done only once per session. If user switches back to light theme and then again dark theme, it is loaded from cache. See the Network panel in browser devtools to see this.</p> </blockquote> <h2> <a name="conclusion" href="#conclusion" class="anchor"> </a> Conclusion </h2> <p>We learned how easily we can toggle between light and dark theme with just few lines of JavaScript code.</p> <p>If you're looking for a complete Bootstrap theme generation code base with support of sass, gulp, auto-refresh, etc. checkout my github repo:</p> <div class="ltag-github-readme-tag"> <div class="readme-overview"> <h3> Quickly generate and showcase your bootstrap theme. </h3> </div> <div class="ltag-github-body"> <div id="readme" class="md" data-path="README.md" readability="5.1806722689076"><article class="markdown-body entry-content container-lg" itemprop="text" readability="25.039915966387"><p><a target="blank" rel="noopener noreferrer" href="https://raw.githubusercontent.com/shhdharmen/bootstrap-theme-kit/master/./bootstrap-theme-kit.png"><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WX5v6D7o--/climit%2Cfauto%2Cflprogressive%2Cqauto%2Cw880/https://raw.githubusercontent.com/shhdharmen/bootstrap-theme-kit/master/./bootstrap-theme-kit.png" alt="Bootstrap Theme Kit" loading="lazy"/></a></p> <p>Quickly <g-emoji class="g-emoji" alias="zap" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/26a1.png">⚡</g-emoji> Generate and Showcase <g-emoji class="g-emoji" alias="dart" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f3af.png">🎯</g-emoji> your bootstrap theme <g-emoji class="g-emoji" alias="art" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f3a8.png">🎨</g-emoji>. <a href="https://raw.githubusercontent.com/shhdharmen/bootstrap-theme-kit/master/#getting-started" style="color: inherit; text-decoration: none;" name="readabilityLink-4">Get Started</a><a href="#readabilityFootnoteLink-4" class="readability-DoNotFootnote" style="color: inherit;"><small><sup>[4]</sup></small></a> or <a href="https://shhdharmen.github.io/bootstrap-theme-kit/" rel="nofollow" style="color: inherit; text-decoration: none;" name="readabilityLink-5">See sample theme</a><a href="#readabilityFootnoteLink-5" class="readability-DoNotFootnote" style="color: inherit;"><small><sup>[5]</sup></small></a>.</p> <p><a href="https://github.com/shhdharmen/bootstrap-theme-kit/blob/master/LICENSE"><img src="https://camo.githubusercontent.com/2dfc2c6cd4f9cf7d3057dfb600f8d7edfcb27046/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f736868646861726d656e2f626f6f7473747261702d7468656d652d6b6974" alt="GitHub license" data-canonical-src="https://img.shields.io/github/license/shhdharmen/bootstrap-theme-kit"/></a> <a href="http://commitizen.github.io/cz-cli/" rel="nofollow"><img src="https://camo.githubusercontent.com/6080f52144977b8b2b20e42408379ce68371aafd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f6d6d6974697a656e2d667269656e646c792d627269676874677265656e2e737667" alt="Commitizen friendly" data-canonical-src="https://img.shields.io/badge/commitizen-friendly-brightgreen.svg"/></a></p> <h2> <g-emoji class="g-emoji" alias="rocket" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f680.png">🚀</g-emoji> Getting Started</h2> <h3> <g-emoji class="g-emoji" alias="ballotboxwithcheck" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/2611.png">☑️</g-emoji> Minimum Requirements</h3> <div class="highlight highlight-source-shell" readability="7"><pre>node -v // v10.17.0 git --version // git version 2.x</pre></div> <h3> <g-emoji class="g-emoji" alias="arrowdown" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/2b07.png">⬇️</g-emoji> Steps to Follow</h3> <ol> <li>First, fork this repo.</li> <li>Open terminal and:</li> </ol> <div class="highlight highlight-source-shell" readability="7"><pre>git clone <span class="pl-k"><</span>forked-repo-url<span class="pl-k">></span> <span class="pl-c1">cd</span> bootstrap-theme-kit npm i npm run init npm start</pre></div> <ol start="3"> <li>Browser will open at 3000 port.</li> <li>Start editing your scss/html files and browser will reload.</li> </ol> <h2> <g-emoji class="g-emoji" alias="trophy" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f3c6.png">🏆</g-emoji> Features</h2> </article></div> </div> </div> <p>And yes, always believe in yourself...</p> <p><a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T9EOwn32--/climit%2Cfauto%2Cflprogressive%2Cqauto%2Cw880/https://cdn.hashnode.com/res/hashnode/image/upload/v1600329170083/uxl5sYNv0.jpeg" class="article-body-image-wrapper"><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T9EOwn32--/climit%2Cfauto%2Cflprogressive%2Cqauto%2Cw880/https://cdn.hashnode.com/res/hashnode/image/upload/v1600329170083/uxl5sYNv0.jpeg" alt="silhouette of trees under starry night photo – Free Nature Image on Unsplash" loading="lazy"/></a></p> <p><span>Photo by <a href="https://unsplash.com/@ngdunlap?utmsource=unsplash&utmmedium=referral&utmcontent=creditCopyText" style="color: inherit; text-decoration: none;" name="readabilityLink-6">Nick Dunlap</a> on <a href="https://unsplash.com/?utmsource=unsplash&utmmedium=referral&utmcontent=creditCopyText" style="color: inherit; text-decoration: none;" name="readabilityLink-7">Unsplash</a><a href="#readabilityFootnoteLink-6" class="readability-DoNotFootnote" style="color: inherit;"><small><sup>[6]</sup></small></a><a href="#readabilityFootnoteLink-7" class="readability-DoNotFootnote" style="color: inherit;"><small><sup>[7]</sup></small></a></span></p> </div><div id="readability-footnotes"><h3>References</h3><ol id="readability-footnotes-list"><li><small><sup><a href="#readabilityLink-1" title="Jump to Link in Article">^</a></sup></small> <a href="https://getbootstrap.com/docs/4.5/getting-started/theming/" name="readabilityFootnoteLink-1">theming in Bootstrap</a><small> (getbootstrap.com)</small></li><li><small><sup><a href="#readabilityLink-2" title="Jump to Link in Article">^</a></sup></small> <a href="https://bootswatch.com/" name="readabilityFootnoteLink-2">Bootswatch</a><small> (bootswatch.com)</small></li><li><small><sup><a href="#readabilityLink-3" title="Jump to Link in Article">^</a></sup></small> <a href="https://bootswatch.com/cyborg/" name="readabilityFootnoteLink-3">Cyborg</a><small> (bootswatch.com)</small></li><li><small><sup><a href="#readabilityLink-4" title="Jump to Link in Article">^</a></sup></small> <a href="https://raw.githubusercontent.com/shhdharmen/bootstrap-theme-kit/master/#getting-started" name="readabilityFootnoteLink-4">Get Started</a><small> (raw.githubusercontent.com)</small></li><li><small><sup><a href="#readabilityLink-5" title="Jump to Link in Article">^</a></sup></small> <a href="https://shhdharmen.github.io/bootstrap-theme-kit/" rel="nofollow" name="readabilityFootnoteLink-5">See sample theme</a><small> (shhdharmen.github.io)</small></li><li><small><sup><a href="#readabilityLink-6" title="Jump to Link in Article">^</a></sup></small> <a href="https://unsplash.com/@ngdunlap?utmsource=unsplash&utmmedium=referral&utmcontent=creditCopyText" name="readabilityFootnoteLink-6">Nick Dunlap</a><small> (unsplash.com)</small></li><li><small><sup><a href="#readabilityLink-7" title="Jump to Link in Article">^</a></sup></small> <a href="https://unsplash.com/?utmsource=unsplash&utmmedium=referral&utm_content=creditCopyText" name="readabilityFootnoteLink-7">Unsplash</a><small> (unsplash.com)</small></li></ol></div>