creating_a_theme_switch.html
HTML document, ASCII text, with very long lines (979)
1
<!DOCTYPE html>
2
<html lang="en-us" prefix="og: https://ogp.me/ns# article: http://ogp.me/ns/article# profile: https://ogp.me/ns/profile#">
3
4
<head>
5
6
7
<meta charset="UTF-8" />
8
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
9
<title>Create a Theme Switch - S0G</title>
10
<link rel="stylesheet" href="/src/global.css" />
11
<meta property="og:locale" content="en_US" />
12
<meta property="og:site_name" content="Steve0Greatness" />
13
<meta property="og:image" content="/OG-Image.png" />
14
15
<link rel="stylesheet" href="/src/code-blocks.css" />
16
<link rel="stylesheet" href="/src/blog.css" />
17
<link rel="alternate" href="/blog/creating_a_theme_switch.txt" type="text/plain" title="Post source" />
18
<meta property="og:title" content="Create a Theme Switch" />
19
<meta property="og:type" content="article" />
20
<meta property="article:published_time" content="2021-12-08T00:00:00Z" />
21
<meta property="article:author" content"https://steve0greatness.github.io" />
22
<meta property="article:modified_time" content="2024-02-03T00:00:00Z" />
23
<meta property="profile:first_name" content="Steve0Greatness" />
24
<meta property="profile:username" content="Steve0Greatness" />
25
<meta property="profile:gender" content="male" />
26
<meta property="og:url" content="https://steve0greatness.github.io/blog/creating_a_theme_switch.html" />
27
28
</head>
29
30
<body>
31
<header>
32
<h2><a href="/"><img src="/SteveLogo.webp" height="35" width="215" alt="Steve0Greatness" /></a></h2>
33
<nav>
34
<a href="/blog">Blog</a>
35
<a href="/list/link-tree.html">Link Tree</a>
36
</nav>
37
</header>
38
39
<nav aria-label="breadcrumbs" aria-roledescription="Site breadcrumb">
40
<ol class="breadcrumbs">
41
42
<li>
43
<a href="/">Index</a>
44
</li>
45
46
<li >
47
<a
48
49
href="/blog"
50
>Blog Index</a>
51
</li>
52
53
<li >
54
<a
55
aria-current="location"
56
href="/blog/creating_a_theme_switch.html"
57
>Create a Theme Switch</a>
58
</li>
59
60
61
</ol>
62
</nav>
63
<main>
64
<h1>Create a Theme Switch</h1>
65
<article>
66
<header>
67
<div role="toolbar" class="toolbar">
68
<strong>Share</strong>
69
<a href="https://toot.kytta.dev/?text=Take a look at this article by @S0G@mastodon.social: https://steve0greatness.github.io/blog/creating_a_theme_switch.html" title="Share to Mastodon">
70
<img src="/toot-kytta-dev-icon.png" width="16" height="16" aria-hidden="true" title="Share to Mastodon" />
71
</a>
72
<a href="/blog/creating_a_theme_switch.html" title="Direct link">
73
<img src="/link-icon.png" width="16" height="16" aria-hidden="true" title="Direct link" />
74
</a>
75
<a href="/blog/creating_a_theme_switch.txt" title="Markdown source">
76
<img src="/md-src.png" width="16" height="16" aria-hidden="true" />
77
</a>
78
</div>
79
<div class="time-stamps">
80
<time datetime="2021-12-08T00:00:00-08:00">2021 Dec 08 PST</time>
81
- <span aria-hidden="true" style="font-style:italic">Revision as of: </span> <time datetime="2024-02-03T00:00:00-08:00" aria-label="Revision">2024 Feb 03 PST</time>
82
83
</div>
84
</header>
85
<p>This is a simple tutorial on how to make a simple theme switcher.</p>
86
87
<p>First step is to create the themes you'll want on your site. You may just want a light and dark mode, however, you may also want other themes. As an example: a clown theme that makes the page absurdly colorful, like a GeoCities site in the early 2000s. For these themes, you can use CSS variables set on the <code>html</code> parent tag(all other elements are considered children of <code>html</code>). Variables can be set in CSS using double hyphens followed by a sequence of text that can use numbers(but not at the start), letters(capital or lowercase), underscores, and hyphens; these variables can then be accessed within your text using the <code>var()</code> function with the name of the variable(including the starting hyphens). You can change out the CSS variables using different selectors on the <code>html</code> tag within the CSS, for me: I'm using the <code>[data-theme]</code> attribute; however, you can use classes if you want. Here is the CSS I wrote:</p>
88
89
<div class="codehilite">
90
<pre><span></span><code><span class="nt">html</span><span class="o">[</span><span class="nt">data-theme</span><span class="o">=</span><span class="nt">light</span><span class="o">]</span><span class="w"> </span><span class="p">{</span>
91
<span class="w"> </span><span class="k">background</span><span class="p">:</span><span class="w"> </span><span class="mh">#fff</span><span class="p">;</span>
92
<span class="w"> </span><span class="k">color</span><span class="p">:</span><span class="w"> </span><span class="mh">#000</span><span class="p">;</span>
93
<span class="w"> </span><span class="nv">--buttonBackground</span><span class="p">:</span><span class="w"> </span><span class="mh">#fefefe</span><span class="p">;</span>
94
<span class="w"> </span><span class="nv">--buttonBorder</span><span class="p">:</span><span class="w"> </span><span class="mh">#ccc</span><span class="p">;</span>
95
<span class="w"> </span><span class="nv">--buttonColor</span><span class="p">:</span><span class="w"> </span><span class="mh">#001</span><span class="p">;</span>
96
<span class="p">}</span>
97
<span class="nt">html</span><span class="o">[</span><span class="nt">data-theme</span><span class="o">=</span><span class="nt">dark</span><span class="o">]</span><span class="w"> </span><span class="p">{</span>
98
<span class="w"> </span><span class="k">background</span><span class="p">:</span><span class="w"> </span><span class="mh">#000</span><span class="p">;</span>
99
<span class="w"> </span><span class="k">color</span><span class="p">:</span><span class="w"> </span><span class="mh">#fff</span><span class="p">;</span>
100
<span class="w"> </span><span class="nv">--buttonBackground</span><span class="p">:</span><span class="w"> </span><span class="mh">#101010</span><span class="p">;</span>
101
<span class="w"> </span><span class="nv">--buttonBorder</span><span class="p">:</span><span class="w"> </span><span class="mh">#333</span><span class="p">;</span>
102
<span class="w"> </span><span class="nv">--buttonColor</span><span class="p">:</span><span class="w"> </span><span class="mh">#fff</span><span class="p">;</span>
103
<span class="p">}</span>
104
<span class="nt">html</span><span class="o">[</span><span class="nt">data-theme</span><span class="o">=</span><span class="nt">clown</span><span class="o">]</span><span class="w"> </span><span class="p">{</span>
105
<span class="w"> </span><span class="k">background</span><span class="p">:</span><span class="w"> </span><span class="mh">#f00</span><span class="p">;</span>
106
<span class="w"> </span><span class="k">color</span><span class="p">:</span><span class="w"> </span><span class="mh">#00f</span><span class="p">;</span>
107
<span class="w"> </span><span class="nv">--buttonBackground</span><span class="p">:</span><span class="w"> </span><span class="mh">#050</span><span class="p">;</span>
108
<span class="w"> </span><span class="nv">--buttonBorder</span><span class="p">:</span><span class="w"> </span><span class="mh">#0a0</span><span class="p">;</span>
109
<span class="w"> </span><span class="nv">--buttonColor</span><span class="p">:</span><span class="w"> </span><span class="mh">#0f0</span><span class="p">;</span>
110
<span class="p">}</span>
111
<span class="nt">button</span><span class="w"> </span><span class="p">{</span>
112
<span class="w"> </span><span class="k">background</span><span class="p">:</span><span class="w"> </span><span class="nf">var</span><span class="p">(</span><span class="nv">--buttonBackground</span><span class="p">);</span>
113
<span class="w"> </span><span class="k">border</span><span class="p">:</span><span class="w"> </span><span class="nf">var</span><span class="p">(</span><span class="nv">--buttonBorder</span><span class="p">)</span><span class="w"> </span><span class="kc">solid</span><span class="w"> </span><span class="mi">3</span><span class="kt">px</span><span class="p">;</span>
114
<span class="w"> </span><span class="k">color</span><span class="p">:</span><span class="w"> </span><span class="nf">var</span><span class="p">(</span><span class="nv">--buttonColor</span><span class="p">);</span>
115
<span class="p">}</span>
116
</code></pre>
117
</div>
118
119
<p>Now we need to create a button that we will use to change the <code>[data-theme]</code> attribute. You (probably) already know what buttons are, so I won't go in depth about then. However: you will need to add an <code>[id]</code> to the button, this will come in play shortly.</p>
120
121
<div class="codehilite">
122
<pre><span></span><code><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"theme-switch"</span><span class="p">></span>Switch Theme<span class="p"></</span><span class="nt">button</span><span class="p">></span>
123
</code></pre>
124
</div>
125
126
<p>Now, it is time to write the JavaScript. First, you'll want to make a constant with the themes you filled into your CSS, for me, that was <code>dark</code>, <code>light</code>, and <code>clown</code>. I'll name this <code>themes</code>.</p>
127
128
<div class="codehilite">
129
<pre><span></span><code><span class="kd">const</span><span class="w"> </span><span class="nx">themes</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s2">"light"</span><span class="p">,</span><span class="w"> </span><span class="s2">"dark"</span><span class="p">,</span><span class="w"> </span><span class="s2">"clown"</span><span class="p">];</span>
130
</code></pre>
131
</div>
132
133
<p>We now need to query the <abbr title="Document Object Model">DOM</abbr> for our theme switch button. This can be done in 2 ways: <code>document.querySelector</code> or <code>document.getElementById</code>; personally, I prefer <code>querySelector</code>, as it allows you to write a CSS selector to get an element from the DOM, allowing for shorter, more digestible, code.</p>
134
135
<p>We have to add a click event to the button. This can be done in 2 ways within JavaScript: <code>addEventListener("click", ...)</code> and <code>onclick</code>. I personally like <code>addEventListener</code> more, so I'll use that. Within the <code>addEventListener</code> function, you need to put a function. This function will control the logic of our theme switch. I'll call this function <code>SwitchTheme</code>, to reflect it's functionality.</p>
136
137
<div class="codehilite">
138
<pre><span></span><code><span class="kd">const</span><span class="w"> </span><span class="nx">ThemeSwitchButton</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s2">"#theme-switch"</span><span class="p">);</span>
139
<span class="nx">ThemeSwitchButton</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s2">"click"</span><span class="p">,</span><span class="w"> </span><span class="nx">SwitchTheme</span><span class="p">());</span>
140
<span class="kd">function</span><span class="w"> </span><span class="nx">SwitchTheme</span><span class="p">()</span><span class="w"> </span><span class="p">{}</span>
141
</code></pre>
142
</div>
143
144
<p>Explaining each part of this function as it's written out would take awhile, so instead, I'll add comments to the ends of each line giving a short explanation. Also, for the sake of shortness, I've placed <code>document.documentElement</code> inside the constant <code>HTML</code>, giving us access to the root element in the DOM(<code>html</code>).</p>
145
146
<div class="codehilite">
147
<pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="nx">CurrentTheme</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">themes</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">HTML</span><span class="p">.</span><span class="nx">dataset</span><span class="p">.</span><span class="nx">theme</span><span class="p">);</span><span class="w"> </span><span class="c1">// Gets how far in the current theme is into the "themes" constant.</span>
148
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">CurrentTheme</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="nx">themes</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// Checks if it's at the end of the array,</span>
149
<span class="w"> </span><span class="nx">HTML</span><span class="p">.</span><span class="nx">dataset</span><span class="p">.</span><span class="nx">theme</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">themes</span><span class="p">[</span><span class="mf">0</span><span class="p">];</span><span class="w"> </span><span class="c1">// If so, reset at the start.</span>
150
<span class="w"> </span><span class="k">return</span><span class="p">;</span><span class="w"> </span><span class="c1">// Ends the function here, preventing next bit of code from running.</span>
151
<span class="p">}</span>
152
<span class="nx">HTML</span><span class="p">.</span><span class="nx">dataset</span><span class="p">.</span><span class="nx">theme</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">themes</span><span class="p">[</span><span class="nx">CurrentTheme</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">1</span><span class="p">];</span><span class="w"> </span><span class="c1">// Goes to the next theme.</span>
153
</code></pre>
154
</div>
155
156
<p>Now we have a finished product. Here's the expected output:</p>
157
158
<iframe id="finalProduct" src="/blog-files/theme-change-final.html" style="border:none"></iframe>
159
160
<p><a href="/blog-files/theme-change-final.txt">See Code</a></p>
161
162
</article>
163
</main>
164
<footer>
165
<div class="footer-link-list-holder" role="group">
166
<span aria-hidden="true" id="footer-label-site-details" class="footer-link-list-label">Site Meta</span>
167
<ol class="footer-link-list" aria-labelledby="footer-label-site-details">
168
<li><a href="/list/website-sources-mirrors.html">Source Code and Mirrors</a></li>
169
<li><a href="https://steve0greatness.github.io/extras">Extras</a></li>
170
</ol>
171
</div>
172
<div class="footer-link-list-holder" role="group">
173
<span aria-hidden="true" id="footer-label-social-accounts" class="footer-link-list-label">Social Accounts</span>
174
<ol class="footer-link-list" aria-labelledby="footer-label-social-accounts">
175
<li><a href="https://mastodon.social/@S0G" rel="me">Mastodon</a></li>
176
<li><a href="https://youtube.com/@s0g">YouTube</a></li>
177
<li><a href="/list/link-tree.html">More...</a></li>
178
</ol>
179
</div>
180
</footer>
181
</body>
182
183
</html>