125 lines
14 KiB
HTML
125 lines
14 KiB
HTML
<!doctype html>
|
|
<html lang="en"><head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
<link rel="shortcut icon" href="https://nonsense.dymc.win/favicon.ico">
|
|
<link id="stylesheet" rel="stylesheet" href="/css/light.css">
|
|
|
|
<link rel="canonical" href="https://nonsense.dymc.win/vanilla-javascript-theme-toggle-for-simpletons/" />
|
|
<title>Vanilla javascript theme toggle for simpletons</title>
|
|
</head>
|
|
<body><header id="banner">
|
|
<nav class="navbar">
|
|
|
|
<a href="https://nonsense.dymc.win/" class="home">🏠</a>
|
|
|
|
<a
|
|
href="/info/"
|
|
title="👋"
|
|
>👋</a
|
|
><a
|
|
href="/search/"
|
|
title="🔎"
|
|
>🔎</a
|
|
>
|
|
|
|
<button id="toggle-button" class="toggle-button" onclick="toggleTheme()">🌚</button>
|
|
</nav>
|
|
</header>
|
|
<main id="content">
|
|
<article>
|
|
<header id="post-header">
|
|
<h2>Vanilla javascript theme toggle for simpletons</h2>
|
|
<div>
|
|
<p>June 26, 2023</p>
|
|
</div>
|
|
</header><p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
|
|
<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
|
|
<h3 id="html">HTML</h3>
|
|
<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
|
|
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
|
|
</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
|
|
<h3 id="css">CSS</h3>
|
|
<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
|
|
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
|
|
</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
|
|
</span></span><span class="line"><span class="cl">
|
|
</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
|
|
</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
|
|
</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
|
|
</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
|
|
</span></span><span class="line"><span class="cl"><span class="p">}</span>
|
|
</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
|
|
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
|
|
</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
|
|
</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
|
|
</span></span><span class="line"><span class="cl"><span class="p">}</span>
|
|
</span></span></code></pre></div><h3 id="js">JS</h3>
|
|
<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
|
|
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
|
|
</span></span><span class="line"><span class="cl">
|
|
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</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="s1">'stylesheet'</span><span class="p">);</span>
|
|
</span></span><span class="line"><span class="cl">
|
|
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
|
|
</span></span><span class="line"><span class="cl">
|
|
</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
|
|
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
|
|
</span></span><span class="line"><span class="cl">
|
|
</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|
</span></span><span class="line"><span class="cl">
|
|
</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
|
|
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
|
|
</span></span><span class="line"><span class="cl">
|
|
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
|
|
</span></span><span class="line"><span class="cl"><span class="p">}</span>
|
|
</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
|
|
<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
|
|
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
|
|
</span></span><span class="line"><span class="cl">
|
|
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</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="s1">'stylesheet'</span><span class="p">);</span>
|
|
</span></span><span class="line"><span class="cl">
|
|
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
|
|
</span></span><span class="line"><span class="cl">
|
|
</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
|
|
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
|
|
</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
|
|
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
|
|
</span></span><span class="line"><span class="cl">
|
|
</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|
</span></span><span class="line"><span class="cl">
|
|
</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
|
|
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
|
|
</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
|
|
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
|
|
</span></span><span class="line"><span class="cl">
|
|
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
|
|
</span></span><span class="line"><span class="cl"><span class="p">}</span>
|
|
</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
|
|
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
</span></span><span class="line"><span class="cl">
|
|
</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
|
|
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
|
|
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</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="s1">'stylesheet'</span><span class="p">);</span>
|
|
</span></span><span class="line"><span class="cl">
|
|
</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
|
|
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
|
|
</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
|
|
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
|
|
</span></span><span class="line"><span class="cl"><span class="p">});</span>
|
|
</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
|
|
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
|
|
</article>
|
|
</main>
|
|
<footer id="footer">
|
|
<small>
|
|
made with <a href="https://gohugo.io">hugo</a>
|
|
</small>
|
|
|
|
<script src="/js/search.js"></script>
|
|
<script src="/js/toggle.js"></script>
|
|
</footer>
|
|
|
|
</body>
|
|
</html>
|