PageSourceSearch

https://christianoliff.com/

html christianoliff.com collected 2026-10-02 04:30:16 UTC 34,769 bytes, 482 lines download raw bytes

1<!doctype html><html lang=en-GB class="h-100 overflow-x-hidden" data-bs-theme=dark>
2<script>(function(){var theme=localStorage.getItem("data-bs-theme");theme&&document.documentElement.setAttribute("data-bs-theme",theme)})()</script>
2<meta charset=utf-8>
3<meta name=viewport content="width=device-width">
4<title>Christian Oliff</title>
5<link rel=monetization href=https://ilp.gatehub.net/959499052/eur>
6<link rel=stylesheet href=/css/style.min.css?v0.166.0>
7<link rel=preload href=/fonts/roboto-v47-latin-500.woff2 as=font type=font/woff2 crossorigin>
8<link rel=preload href=/fonts/roboto-v47-latin-regular.woff2 as=font type=font/woff2 crossorigin><link rel=preload as=image href=/img/header/header-factory.svg fetchpriority=high><link rel="alternate icon" href=/favicon.ico type=image/x-icon sizes=any>
9<link rel=icon href=/favicon.svg type=image/svg+xml>
10<script type=module async src=/js/invoker.min.js></script>
vendor: 1 bytes, line 10
10
11<script type=speculationrules>
12{
13  "prerender": [{
14    "where": {
15      "href_matches": "/*"
16    },
17    "eagerness": "moderate"
18  }]
19}
20</script>
vendor: 1 bytes, line 20
20
21<script src=/js/scroll-to-top.min.js?v0.166.0 defer></script>
vendor: 1 bytes, line 21
21
22<script src=/js/button-sound.min.js?v0.166.0 defer></script>
vendor: 1 bytes, line 22
22
23<script src=/js/code-copy.min.js?v0.166.0 defer></script>
23
24<meta name=description content="Online Adventures of a Front-End Web Developer">
25<meta property="og:url" content="https://christianoliff.com/">
26<meta property="og:site_name" content="Christian Oliff">
27<meta property="og:title" content="Christian Oliff">
28<meta property="og:description" content="Online Adventures of a Front-End Web Developer">
29<meta property="og:locale" content="en_GB">
30<meta property="og:type" content="website">
31<meta property="og:image" content="https://christianoliff.com/img/header/header-factory.png">
32<meta property="og:updated_time" content="2026-09-23T11:20:47+00:00">
33<meta name=fediverse:creator content="@[email protected]">
34<meta name=theme-color content="#04B9EE"><link rel=canonical href="https://christianoliff.com/?pt=378206&ct=christianoliffcom&mt=8">
35<link rel=alternate type=application/rss+xml href=https://christianoliff.com/feed.xml title="Christian Oliff">
36<link rel=stylesheet href=https://cdn.jsdelivr.net/npm/[email protected]/css/bootstrap-forced-colors.min.css media="screen and (forced-colors: active)">
37<link rel=webmention href=https://webmention.io/christianoliff.com/webmention>
38<link rel=pingback href=https://webmention.io/christianoliff.com/xmlrpc>
39<meta name=monetization content="$ilp.uphold.com/Epqzn3YGr2MB">
40<meta name=color-scheme content="dark light">
41<meta name=generator content="Hugo 0.166.0">
42<script defer src=https://eu.umami.is/script.js data-website-id=c032a7d1-8357-44f5-aa1e-9424c2d29705></script>
42
43<body class="d-flex flex-column min-vh-100 overflow-x-hidden" id=listjs-body data-url=/ data-bs-no-jquery><div class="skippy overflow-hidden visually-hidden">
44<div class=container>
45<a class="sr-only sr-only-focusable nav-item mt-3 mx-0 mx-sm-1" href=#main>Skip to
46main content</a>
47</div>
48</div>
49<header class="container-fluid container-header px-0" style=background-color:#04b9ee;background-image:url(/img/header/header-factory.svg)>
50<div class="container-fluid px-0">
51<div class=container-navbar><nav class="navbar navbar-expand pt-0 mb-n2 navbar-dark" id=mainNav>
52<div class="container flex-row">
53<a class=navbar-brand href=/> // Christian Oliff </a>
54<ul class="navbar-nav ms-auto">
55<li class=nav-item>
56<button type=button class="nav-link border-0" commandfor=modalSettings command=show-modal aria-label=info><svg width="16" height="16" viewBox="0 0 512 512"><path fill="currentColor" d="M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196.0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627.0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627.0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627.0 12 5.373 12 12v1e2h12c6.627.0 12 5.373 12 12v24z"/></svg></button>
57</ul>
58</div>
59</nav>
60</div>
61<div class="bg-angle-white px-0 mt-0">
62<script src=/js/bootstrap.bundle.min.js fetchpriority=low></script>
62
63</div>
64</div>
65</header>
66<main class=flex-grow-1><div id=main class="mt-n5 pt-1 pt-sm-2">
67<div class=container-fluid>
68<div class="container rounded pb-5 bg-body pt-2"><div class="container-xl mb-5"><h1 class="blog-posts-heading mb-4">Latest blog posts</h1><div class="row row-cols-1 row-cols-sm-2 mb-0"><div class=my-3>
69<article class="card card-blog-brief h-100 border-dark shadow-lg bg-black">
70<div class="card-header top-rounded border-0 ratio" style=background-color:#eee;background-image:url(/img/header/2026/bootstrap-icons-css.png);--bs-aspect-ratio:42%>
71<div><img src=/img/header/2026/bootstrap-icons-css.png height=0 class=d-none loading=lazy alt>
72</div>
73</div>
74<div class="card-body border-0 pb-0">
75<h2 class="card-title text-white px-2 ms-n1 h6 name">Bootstrap Icons as CSS variables</h2>
76<p class="px-2 ms-n1">
77<a href=/blog/bootstrap-icons-css/ class="stretched-link text-decoration-none small">Use Bootstrap Icons as CSS custom properties for easy theming and inline use</a>
78</div>
79</article>
80</div><div class=my-3>
81<article class="card card-blog-brief h-100 border-dark shadow-lg bg-black">
82<div class="card-header top-rounded border-0 ratio" style=background-color:#906b37;background-image:url(/img/header/2026/header-web-developer-tools-plus-ios-app.webp);--bs-aspect-ratio:42%>
83<div><img src=/img/header/2026/header-web-developer-tools-plus-ios-app.webp height=0 class=d-none loading=lazy alt>
84</div>
85</div>
86<div class="card-body border-0 pb-0">
87<h2 class="card-title text-white px-2 ms-n1 h6 name">Web Developer Tools+ iOS App</h2>
88<p class="px-2 ms-n1">
89<a href=/blog/web-developer-tools-plus-ios-app/ class="stretched-link text-decoration-none small">An iOS Safari extension for testing and debugging websites on the go</a>
90</div>
91</article>
92</div></div>
93<div class="row row-cols-1 row-cols-sm-2 row-cols-lg-3"><div class=my-3>
94<article class="card card-blog-brief h-100 border-dark shadow-lg bg-black">
95<div class="card-header top-rounded border-0 ratio" style=background-color:#212529;background-image:url(/img/header/2025/header-bootstrap-css-breakpoint-indicator.png);--bs-aspect-ratio:42%>
96<div><img src=/img/header/2025/header-bootstrap-css-breakpoint-indicator.png height=0 class=d-none loading=lazy alt>
97</div>
98</div>
99<div class="card-body border-0 pb-0">
100<h2 class="card-title text-white px-2 ms-n1 h6 name">Bootstrap 5 CSS Breakpoint Indicator</h2>
101<p class="px-2 ms-n1">
102<a href=/blog/bootstrap-5-css-breakpoint-indicator/ class="stretched-link text-decoration-none small">A simple CSS snippet that displays the current Bootstrap breakpoint in your browser viewport.</a>
103</div>
104</article>
105</div><div class=my-3>
106<article class="card card-blog-brief h-100 border-dark shadow-lg bg-black">
107<div class="card-header top-rounded border-0 ratio" style=background-color:#181b1d;background-image:url(/img/header/2025/header-bootstrap-modal-dialog.png);--bs-aspect-ratio:42%>
108<div><img src=/img/header/2025/header-bootstrap-modal-dialog.png height=0 class=d-none loading=lazy alt>
109</div>
110</div>
111<div class="card-body border-0 pb-0">
112<h2 class="card-title text-white px-2 ms-n1 h6 name">Building a Bootstrap Modal with the dialog HTML element</h2>
113<p class="px-2 ms-n1">
114<a href=/blog/bootstrap-modal-with-dialog/ class="stretched-link text-decoration-none small">Using with Invoker Commands - No JavaScript required</a>
115</div>
116</article>
117</div><div class=my-3>
118<article class="card card-blog-brief h-100 border-dark shadow-lg bg-black">
119<div class="card-header top-rounded border-0 ratio" style=background-color:#ddd;background-image:url(/img/header/2025/header-image-size-info-browser-extension.png);--bs-aspect-ratio:42%>
120<div><img src=/img/header/2025/header-image-size-info-browser-extension.png height=0 class=d-none loading=lazy alt>
121</div>
122</div>
123<div class="card-body border-0 pb-0">
124<h2 class="card-title text-white px-2 ms-n1 h6 name">Image Size Info Browser Extension</h2>
125<p class="px-2 ms-n1">
126<a href=/blog/image-size-info-browser-extension/ class="stretched-link text-decoration-none small">I made a browser extension that shows image size information in the context menu.</a>
127</div>
128</article>
129</div></div>
130<div class="row row-cols-1 row-cols-sm-2 row-cols-lg-4"><div class=my-3>
131<article class="card card-blog-brief h-100 border-dark shadow-lg bg-black">
132<div class="card-header top-rounded border-0 ratio" style=background-color:#ddd;background-image:url(/img/header/2023/header-bootstrap-accordion-with-detail
132s-summary.svg);--bs-aspect-ratio:42%>
133<div><img src=/img/header/2023/header-bootstrap-accordion-with-details-summary.svg height=0 class=d-none loading=lazy alt>
134</div>
135</div>
136<div class="card-body border-0 pb-0">
137<h2 class="card-title text-white px-2 ms-n1 h6 name">Building a Bootstrap Accordion with the details/summary HTML tags in 2025</h2>
138<p class="px-2 ms-n1">
139<a href=/blog/building-a-bootstrap-accordion-with-the-details-summary-html-tags-2025/ class="stretched-link text-decoration-none small">A collapsible accordion using `details` HTML tag and Bootstrap 5 CSS with open/close transitions</a>
140</div>
141</article>
142</div><div class=my-3>
143<article class="card card-blog-brief h-100 border-dark shadow-lg bg-black">
144<div class="card-header top-rounded border-0 ratio" style=background-color:#253218;background-image:url(/img/header/2025/header-using-speculation-rules-to-improve-performance.svg);--bs-aspect-ratio:42%>
145<div><img src=/img/header/2025/header-using-speculation-rules-to-improve-performance.svg height=0 class=d-none loading=lazy alt>
146</div>
147</div>
148<div class="card-body border-0 pb-0">
149<h2 class="card-title text-white px-2 ms-n1 h6 name">Using the Speculation Rules API to Improve Performance</h2>
150<p class="px-2 ms-n1">
151<a href=/blog/using-speculation-rules-to-improve-performance/ class="stretched-link text-decoration-none small">Prerender pages on hover using the HTML speculation rules API</a>
152</div>
153</article>
154</div><div class=my-3>
155<article class="card card-blog-brief h-100 border-dark shadow-lg bg-black">
156<div class="card-header top-rounded border-0 ratio" style=background-color:#19191a;background-image:url(/img/header/2025/header-safari-wishlist-2025.svg);--bs-aspect-ratio:42%>
157<div><img src=/img/header/2025/header-safari-wishlist-2025.svg height=0 class=d-none loading=lazy alt>
158</div>
159</div>
160<div class="card-body border-0 pb-0">
161<h2 class="card-title text-white px-2 ms-n1 h6 name">Safari Wishlist (2025)</h2>
162<p class="px-2 ms-n1">
163<a href=/blog/safari-wishlist-2025/ class="stretched-link text-decoration-none small">My top 10 wishes for Safari in 2025.</a>
164</div>
165</article>
166</div><div class=my-3>
167<article class="card card-blog-brief h-100 border-dark shadow-lg bg-black">
168<div class="card-header top-rounded border-0 ratio" style=background-color:#e5ebf0;background-image:url(/img/header/2025/header-bootstrap-javascript-snippets.svg);--bs-aspect-ratio:42%>
169<div><img src=/img/header/2025/header-bootstrap-javascript-snippets.svg height=0 class=d-none loading=lazy alt>
170</div>
171</div>
172<div class="card-body border-0 pb-0">
173<h2 class="card-title text-white px-2 ms-n1 h6 name">Bootstrap JavaScript Snippets</h2>
174<p class="px-2 ms-n1">
175<a href=/blog/bootstrap-javascript-snippets/ class="stretched-link text-decoration-none small">Helpful little code snippets for web developers to enhance usability and accessibility.</a>
176</div>
177</article>
178</div></div><div class="text-center mt-3">
179<a href=/blog/ class="h6 text-light">
180View All
181</a>
182</div></div>
183</div>
184</div>
185</div></main><footer class="container-fluid pt-2">
186<div class=container>
187<div class="row py-2">
188<div class=col-12>
189<a href=https://github.com/coliff target=_blank rel=me class="me-4 link-g"><svg width="16" height="16" class="me-1 mt-n1" viewBox="0 0 496 512"><path fill="currentColor" d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6.0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6.0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3.0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1.0-6.2-.3-40.4-.3-61.4.0.0-70 15-84.7-29.8.0.0-11.4-29.1-27.8-36.6.0.0-22.9-15.7 1.6-15.4.0.0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5.0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9.0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4.0 33.7-.3 75.4-.3 83.6.0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6.0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9.0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>GitHub</a>
190<br class="d-block d-sm-none">
191<a href=https://www.linkedin.com/in/christianoliff/ target=_blank rel=me class="me-4 link-l">
191<svg width="16" height="16" class="me-1 mt-n1" viewBox="0 0 448 512"><path fill="currentColor" d="M416 32H31.9C14.3 32 0 46.5.0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6.0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3zM135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3.0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2.0 38.5 17.3 38.5 38.5.0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6.0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2.0 79.7 44.3 79.7 101.9V416z"/></svg>LinkedIn</a>
192<a href=https://mastodon.social/@christianoliff target=_blank rel=me class="me-4 link-m"><svg width="16" height="16" class="me-1 mt-n1" viewBox="0 0 448 512"><path fill="currentColor" d="M433 179.11c0-97.2-63.71-125.7-63.71-125.7-62.52-28.7-228.56-28.4-290.48.0.0.0-63.72 28.5-63.72 125.7.0 115.7-6.6 259.4 105.63 289.1 40.51 10.7 75.32 13 103.33 11.4 50.81-2.8 79.32-18.1 79.32-18.1l-1.7-36.9s-36.31 11.4-77.12 10.1c-40.41-1.4-83-4.4-89.63-54a102.54 102.54.0 01-.9-13.9c85.63 20.9 158.65 9.1 178.75 6.7 56.12-6.7 105-41.3 111.23-72.9 9.8-49.8 9-121.5 9-121.5zm-75.12 125.2h-46.63v-114.2c0-49.7-64-51.6-64 6.9v62.5h-46.33V197c0-58.5-64-56.6-64-6.9v114.2H90.19c0-122.1-5.2-147.9 18.41-175 25.9-28.9 79.82-30.8 103.83 6.1l11.6 19.5 11.6-19.5c24.11-37.1 78.12-34.8 103.83-6.1 23.71 27.3 18.4 53 18.4 175z"/></svg>Mastodon</a>
193<a href=https://bsky.app/profile/christianoliff.com target=_blank rel=me class="me-4 link-b"><svg width="16" height="16" class="me-1 mt-n1" viewBox="0 0 600 530"><path fill="currentColor" d="m135.72 44.03C202.216 93.951 273.74 195.17 3e2 249.49c26.262-54.316 97.782-155.54 164.28-205.46C512.26 8.009 590-19.862 590 68.825c0 17.712-10.155 148.79-16.111 170.07-20.703 73.984-96.144 92.854-163.25 81.433 117.3 19.964 147.14 86.092 82.697 152.22-122.39 125.59-175.91-31.511-189.63-71.766-2.514-7.3797-3.6904-10.832-3.7077-7.8964-.0174-2.9357-1.1937.51669-3.7077 7.8964-13.714 40.255-67.233 197.36-189.63 71.766-64.444-66.128-34.605-132.26 82.697-152.22-67.108 11.421-142.55-7.4491-163.25-81.433-5.9562-21.282-16.111-152.36-16.111-170.07.0-88.687 77.742-60.816 125.72-24.795z"/></svg>
194Bluesky</a>
195<a href=/feed.xml class="me-4 link-r"><svg width="16" height="16" class="me-1 mt-n1" viewBox="0 0 448 512"><path fill="currentColor" d="M4e2 32H48C21.49 32 0 53.49.0 80v352c0 26.51 21.49 48 48 48h352c26.51.0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zM112 416c-26.51.0-48-21.49-48-48s21.49-48 48-48 48 21.49 48 48-21.49 48-48 48zm157.533.0h-34.335c-6.011.0-11.051-4.636-11.442-10.634-5.214-80.05-69.243-143.92-149.123-149.123-5.997-.39-10.633-5.431-10.633-11.441v-34.335c0-6.535 5.468-11.777 11.994-11.425 110.546 5.974 198.997 94.536 204.964 204.964.352 6.526-4.89 11.994-11.425 11.994zm103.027.0h-34.334c-6.161.0-11.175-4.882-11.427-11.038-5.598-136.535-115.204-246.161-251.76-251.76C68.882 152.949 64 147.935 64 141.774V107.44c0-6.454 5.338-11.664 11.787-11.432 167.83 6.025 302.21 141.191 308.205 308.205.232 6.449-4.978 11.787-11.432 11.787z"/></svg>RSS Feed</a>
196</div>
197</div>
198<div class="row py-2">
199<div class=col-12>
200<p class="small opacity-50">
201&copy; 2026 Christian Oliff.<br class="d-block d-sm-none">
202<span>Powered by
203<a href=https://getbootstrap.com target=_blank rel=noopener class=opacity-75>Bootstrap</a> /
204<a href=https://gohugo.io target=_blank rel=noopener class=opacity-75>Hugo</a> /
205<a href=https://github.com/ target=_blank rel=noopener class=opacity-75>GitHub</a> /
206<a href=https://www.cloudflare.com target=_blank rel=noopener class=opacity-75>Cloudflare</a> /
207<button type=button data-bs-toggle=modal data-bs-target=#modalCoffee class="opacity-75 btn-text ext-link bg-transparent border-0 p-1">Coffee</button>
208</span>
209</div>
210</div>
211</div>
212</footer>
213<dialog id=modalSettings class="position-relative border-0 bg-transparent" closedby=any>
214<div class="modal d-flex position-static pt-5 mt-3">
215<div class="modal-dialog modal-dialog-centered rounded w-100 shadow-lg">
216<div class="modal-content modal-settings position-relative mt-2 shadow rounded">
217<button type=button class="btn btn-close position-absolute top-0 end-0 m-2 modal-settings-close-fallback d-none" aria-label="Close settings" title=Close></button>
218<div class="modal-header border-0 text-center mx-auto mt-n4">
219<h2 class="modal-title mx-auto text-center mt-n4">
220<img src=/img/bio-photo.jpg srcset=/img/bio-photo.svg alt="Christian Oliff profile photo" height=122 width=122 class="mx-auto text-center rounded-circle border-white border p-1 mt-n4 bg-white d-block" loading=lazy>
221</h2>
222</div>
223<div class="modal-body text-center p-0 rounded-bottom">
224<h4 class="text-muted mt-0 mb-4">
225christianoliff.com
226</h4>
227<ul class="nav nav-tabs border-bottom justify-content-center" id=modalSettingsTabs role=tablist>
228<li class=nav-item role=presentation>
229<button type=button class="nav-link filter-grayscale py-1 small text-uppercase" id=modal-settings-tab data-bs-toggle=tab data-bs-target=#modal-settings-pane role=tab aria-controls=modal-settings-pane aria-selected=false>
230Settings
231</button>
232<li class=nav-item role=presentation>
233<button type=button class="nav-link active filter-grayscale py-1 small text-uppercase" id=modal-info-tab data-bs-toggle=tab data-bs-target=#modal-info-pane role=tab aria-controls=modal-info-pane aria-selected=true>
234Credits
235</button>
236<li class=nav-item role=presentation>
237<button type=button class="nav-link filter-grayscale py-1 small text-uppercase" id=modal-system-tab data-bs-toggle=tab data-bs-target=#modal-system-pane role=tab aria-controls=modal-system-pane aria-selected=false>
238System Info
239</button>
240</ul>
241<div class="tab-content text-start p-2 rounded-bottom" id=modalSettingsTabContent>
242<div class="tab-pane fade text-start px-2" id=modal-settings-pane role=tabpanel aria-labelledby=modal-settings-tab>
243<div class="d-flex flex-column gap-1">
244<div class="form-check form-switch my-2">
245<input class=form-check-input id=settingDarkMode type=checkbox role=switch checked switch>
246<label class=form-check-label for=settingDarkMode>Dark mode</label>
247</div>
248<div class="form-check form-switch my-1">
249<input class=form-check-input id=settingUISounds type=checkbox role=switch switch>
250<label class=form-check-label for=settingUISounds>UI Sounds</label>
251</div>
252<div class="text-center opacity-50">
253<hr class=my-2>
254</div>
255<div class="form-check form-switch my-2">
256<input class=form-check-input id=settingPrefersContrast type=checkbox role=switch switch>
257<label class=form-check-label for=settingPrefersContrast>Increase Contrast<br>
258<small class="text-muted mt-0 pt-0">Increase color contrast between backgrounds.</small></label>
259</div>
260<div class="form-check form-switch my-1">
261<input class=form-check-input id=settingReduceMotion type=checkbox role=switch switch>
262<label class=form-check-label for=settingReduceMotion>Reduce Motion</label>
263</div>
264<div class="form-check form-switch my-1">
265<input class=form-check-input id=settingReduceTransparency type=checkbox role=switch switch>
266<label class=form-check-label for=settingReduceTransparency>Reduce transparency</label>
267</div>
268</div>
269</div>
270<div class="tab-pane fade show active" id=modal-info-pane role=tabpanel aria-labelledby=modal-info-tab>
271<div class="opacity-75 my-3 text-center">
272<h5 class="text-muted small">Built by Christian Oliff with:</h5>
273<div class=container>
274<div class="row g-1 mb-3">
275<div class="col-4 d-flex flex-column align-items-center">
276<svg viewBox="0 0 24 24" width="32" height="32" class="mx-auto"><path fill="currentColor" d="M11.77 11.24H9.956V8.202h2.152c1.17.0 1.834.522 1.834 1.466.0 1.008-.773 1.572-2.174 1.572zm.324 1.206H9.957v3.348h2.231c1.459.0 2.232-.585 2.232-1.685s-.795-1.663-2.326-1.663zM24 11.39v1.218c-1.128.108-1.817.944-2.226 2.268-.407 1.319-.463 2.937-.42 4.186.045 1.3-.968 2.5-2.337 2.5H4.985c-1.37.0-2.383-1.2-2.337-2.5.043-1.249-.013-2.867-.42-4.186-.41-1.324-1.1-2.16-2.228-2.268V11.39c1.128-.108 1.819-.944 2.227-2.268.408-1.319.464-2.937.42-4.186-.045-1.3.968-2.5 2.338-2.5h14.032c1.37.0 2.382 1.2 2.337 2.5-.043 1.249.013 2.867.42 4.186.409 1.324 1.098 2.16 2.226 2.268zm-7.927 2.817c0-1.354-.953-2.333-2.368-2.488v-.057c1.04-.169 1.856-1.135 1.856-2.213.0-1.537-1.213-2.538-3.062-2.538h-4.16v10.172h4.181c2.218.0 3.553-1.086 3.553-2.876z"/></svg>
277<span class="small text-muted">Bootstrap</span>
278</div>
279<div class="col-4 d-flex flex-column align-items-center">
280<svg viewBox="0 0 500 500" width="32" height="32" class="mx-auto"><path fill="currentColor" d="M249.8 12l-61.3 175.4-186.3.6 150.9 111.6L99 479.5l152.5-107.9L408 486.1 350.6 299 5e2 187.4l-185.7.5L249.8 12"/></svg>
281<span class="small text-muted">H5BP</span>
282</div>
283<div class="col-4 d-flex flex-column align-items-center">
284<svg viewBox="0 0 448 512" width="32" height="32" class="mx-auto"><path fill="currentColor" d="M397.8 32H50.2C22.7 32 0 54.7.0 82.2v347.6C0 457.3 22.7 480 50.2 480h347.6c27.5.0 50.2-22.7 50.2-50.2V82.2c0-27.5-22.7-50.2-50.2-50.2zm-45.4 284.3c0 4.2-3.6 6-7.8 7.8-16.7 7.2-34.6 13.7-53.8 13.7-26.9.0-39.4-16.7-71.7-16.7-23.3.0-47.8 8.4-67.5 17.3-1.2.6-2.4.6-3.6 1.2V385c0 1.8.0 3.6-.6 4.8v1.2c-2.4 8.4-10.2 14.3-19.1 14.3-11.3.0-20.3-9-20.3-20.3V166.4c-7.8-6-13.1-15.5-13.1-26.3.0-18.5 14.9-33.5 33.5-33.5 18.5.0 33.5 14.9 33.5 33.5.0 10.8-4.8 20.3-13.1 26.3v18.5c1.8-.6 3.6-1.2 5.4-2.4 18.5-7.8 40.6-14.3 61.5-14.3 22.7.0 40.6 6 60.9 13.7 4.2 1.8 8.4 2.4 13.1 2.4 22.7.0 47.8-16.1 53.8-16.1 4.8.0 9 3.6 9 7.8v140.3z"/></svg>
285<span class="small text-muted">Font Awesome</span>
286</div>
287</div>
288<div class="row g-1 mb-3">
289<div class="col-4 d-flex flex-column align-items-center">
290<svg viewBox="0 0 24 24" width="32" height="32" class="mx-auto"><path fill="currentColor" d="M11.754.0A3.998 3.998.0 009.705.596L3.33 4.532A4.252 4.252.0 001.313 8.147v8.03c0 1.473.79 2.838 2.067 3.574l6.486 3.733a3.88 3.88.0 003.835.018l7.043-3.966a3.817 3.817.0 001.943-3.323V7.752a3.57 3.57.0 00-1.774-3.084L13.817.541a3.998 3.998.0 00-2.063-.54zm.022 1.674c.413-.006.828.1 1.2.315l7.095 4.127c.584.34.941.96.94 1.635v8.462c0 .774-.414 1.484-1.089 1.864l-7.042 3.966a2.199 2.199.0 01-2.179-.01l-6.485-3.734a2.447 2.447.0 01-1.228-2.123v-8.03c0-.893.461-1.72 1.221-2.19l6.376-3.935a2.323 2.323.0 011.19-.347zm-4.7 3.844V18.37h2.69v-5.62h4.46v5.62h2.696V5.518h-2.696v4.681h-4.46V5.518z"/></svg>
291<span class="small text-muted">Hugo</span>
292</div>
293<div class="col-4 d-flex flex-column align-items-center">
294<svg role="img" viewBox="0 0 24 24" width="32" height="32" class="mx-auto"><path fill="currentColor" d="M16.5088 16.8447c.1475-.5068.0908-.9707-.1553-1.3154-.2246-.3164-.6045-.499-1.0615-.5205l-8.6592-.1123a.1559.1559.0 01-.1333-.0713c-.0283-.042-.0351-.0986-.021-.1553.0278-.084.1123-.1484.2036-.1562l8.7359-.1123c1.0351-.0489 2.1601-.8868 2.5537-1.9136l.499-1.3013c.0215-.0561.0293-.1128.0147-.168-.5625-2.5463-2.835-4.4453-5.5499-4.4453-2.5039.0-4.6284 1.6177-5.3876 3.8614-.4927-.3658-1.1187-.5625-1.794-.499-1.2026.119-2.1665 1.083-2.2861 2.2856-.0283.31-.0069.6128.0635.894C1.5683 13.171.0 14.7754.0 16.752c0 .1748.0142.3515.0352.5273.0141.083.0844.1475.1689.1475h15.9814c.0909.0.1758-.0645.2032-.1553l.12-.4268zm2.7568-5.5634c-.0771.0-.1611.0-.2383.0112-.0566.0-.1054.0415-.127.0976l-.3378 1.1744c-.1475.5068-.0918.9707.1543 1.3164.2256.3164.6055.498 1.0625.5195l1.8437.1133c.0557.0.1055.0263.1329.0703.0283.043.0351.1074.0214.1562-.0283.084-.1132.1485-.204.1553l-1.921.1123c-1.041.0488-2.1582.8867-2.5527 1.914l-.1406.3585c-.0283.0713.0215.1416.0986.1416h6.5977c.0771.0.1474-.0489.169-.126.1122-.4082.1757-.837.1757-1.2803.0-2.6025-2.125-4.727-4.7344-4.727"/></svg>
295<span class="small text-muted">Cloudflare</span>
296</div>
297<div class="col-4 d-flex flex-column align-items-center">
298<svg width="32" height="32" class="mx-auto" viewBox="0 0 496 512"><path fill="currentColor" d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6.0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6.0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3.0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1.0-6.2-.3-40.4-.3-61.4.0.0-70 15-84.7-29.8.0.0-11.4-29.1-27.8-36.6.0.0-22.9-15.7 1.6-15.4.0.0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5.0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9.0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4.0 33.7-.3 75.4-.3 83.6.0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6.0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9.0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
299<span class="small text-muted">GitHub</span>
300</div>
301</div>
302<div class="row g-1">
303<div class="col-4 d-flex flex-column align-items-center">
304<svg width="32" height="32" class="mx-auto" viewBox="0 0 512 512"><path fill="currentColor" d="M431.45 177.65 437.33 160h0L480 32H80A80 80 0 000 112V216a8 8 0 008 8H24a8 8 0 008-8V112A48 48 0 0180 64h26.67l32 96h0l6.05 18.16C95.41 217.9 64 277.69 64 344.62c0 51.47 18.62 84.77 49.64 117.71A57.18 57.18.0 00155.17 480H420.84a57.08 57.08.0 0041.45-17.6c31-32.95 49.69-66.24 49.71-117.72C512 278.37 481.37 217.83 431.45 177.65zM140.4 64H435.6l-32 96H172.4zm38.15 128h219.7c21 16.92 54.68 42.08 72.5 96H105.39c18.11-54 52.82-79.61 73.16-96zM439 440.45A24.92 24.92.0 01420.84 448H155.17a25 25 0 01-18.23-7.62C107.1 408.71 96 382.75 96 344.62A178.3 178.3.0 0197.9 320H478.13A180.47 180.47.0 01480 344.67c0 38.12-11.12 64.08-41 95.78z"/></svg>
305<span class="small text-muted">Coffee</span>
306</div>
307<div class="col-4 d-flex flex-column align-items-center">
308<svg role="img" viewBox="0 0 24 24" width="32" height="32" class="mx-auto"><path fill="currentColor" d="M6.49 19.04h-.23L5.13 17.9v-.23l1.73-1.71h1.2l.15.15v1.2L6.5 19.04zM5.13 6.31V6.1l1.13-1.13h.23L8.2 6.68v1.2l-.15.15h-1.2L5.13 6.31zm9.96 9.09h-1.65l-.14-.13v-3.83c0-.68-.27-1.2-1.1-1.23-.42.0-.9.0-1.43.02l-.07.08v4.96l-.14.14H8.9l-.13-.14V8.73l.13-.14h3.7a2.6 2.6.0 012.61 2.6v4.08l-.13.14zm-8.37-2.44H.14L0 12.82v-1.64l.14-.14h6.58l.14.14v1.64l-.14.14zm17.14.0h-6.58l-.14-.14v-1.64l.14-.14h6.58l.14.14v1.64l-.14.14zM11.05 6.55V1.64l.14-.14h1.65l.14.14v4.9l-.14.14h-1.65l-.14-.13zm0 15.81v-4.9l.14-.14h1.65l.14.13v4.91l-.14.14h-1.65l-.14-.14z"/></svg>
309<span class="small text-muted">Netlify</span>
310</div>
311<div class="col-4 d-flex flex-column align-items-center">
312<svg role="img" viewBox="0 0 24 24" width="32" height="32" class="mx-auto"><path fill="currentColor" d="M23.15 2.587 18.21.21A1.494 1.494.0 0016.505.5l-9.46 8.63-4.12-3.128a.999.999.0 00-1.276.057L.327 7.261A1 1 0 00.326 8.74L3.899 12 .326 15.26a1 1 0 00.001 1.479L1.65 17.94a.999.999.0 001.276.057l4.12-3.128 9.46 8.63a1.492 1.492.0 001.704.29l4.942-2.377A1.5 1.5.0 0024 20.06V3.939a1.5 1.5.0 00-.85-1.352zm-5.146 14.861L10.826 12l7.178-5.448v10.896z"/></svg>
313<span class="small text-muted">VS Code</span>
314</div>
315</div>
316</div>
317</div>
318<div class="my-2 text-center py-2">
319<a href=/uses/ class="btn btn-sm btn-outline-secondary mx-2">Stuff I Use</a>
320<a href=/open-source/ class="btn btn-sm btn-outline-secondary mx-2">Open source</a>
321<a href=/contact/ class="btn btn-sm btn-outline-secondary mx-2">Contact Me</a>
322</div>
323<h6 class="small opacity-25 text-center">
324Last updated: 2026-09-23</h6>
325</div>
326<div class="tab-pane fade text-start px-2 overflow-y-auto" id=modal-system-pane role=tabpanel aria-labelledby=modal-system-tab>
327<div class="accordion mt-2" id=systemInfoAccordion>
328<details class="accordion-item border-bottom-0" name=systemInfoAccordion>
329<summary class="accordion-button rounded-top py-1 px-2">
330<span class="accordion-h eader user-select-none">Browser Details</span>
331</summary>
332<div class="accordion-body border-bottom p-0">
333<table class="table table-sm table-borderless small mb-0 border-0 table-striped bg-transparent" aria-label="Browser details">
334<tbody>
335<tr id=rowSystemBrowser>
336<th class="text-muted px-2" scope=row>Browser
337<td class=small id=systemBrowser>–
338<tr>
339<th class="text-muted px-2" scope=row>User agent
340<td class="small text-break" id=systemUserAgent>–
341<tr>
342<th class="text-muted px-2" scope=row>Platform
343<td class=small id=systemPlatform>–
344<tr>
345<th class="text-muted px-2" scope=row>Timezone
346<td class=small id=systemTimezone>–
347</table>
348</div>
349</details>
350<details class="accordion-item border-bottom-0" name=systemInfoAccordion>
351<summary class="accordion-button py-1 px-2">
352<span class="accordion-header user-select-none">Display</span>
353</summary>
354<div class="accordion-body border-bottom p-0">
355<table class="table table-sm table-borderless small mb-0 border-0 table-striped bg-transparent" aria-label=Display>
356<tbody>
357<tr>
358<th class="text-muted px-2" scope=row>Screen
359<td class=small id=systemScreen>–
360<tr>
361<th class="text-muted px-2" scope=row>Viewport
362<td class=small id=systemViewport>–
363<tr>
364<th class="text-muted px-2" scope=row>Pixel density
365<td class=small id=systemPixelDensity>–
366<tr>
367<th class="text-muted px-2" scope=row>Color depth
368<td class=small id=systemColorDepth>–
369<tr>
370<th class="text-muted px-2" scope=row>Orientation
371<td class=small id=systemOrientation>–
372<tr>
373<th class="text-muted px-2" scope=row>Color gamut
374<td class=small id=systemColorGamut>–
375<tr>
376<th class="text-muted px-2" scope=row>Dynamic range
377<td class=small id=systemDynamicRange>–
378</table>
379</div>
380</details>
381<details class="accordion-item border-bottom-0" name=systemInfoAccordion>
382<summary class="accordion-button py-1 px-2">
383<span class="accordion-header user-select-none">User/System Prefs</span>
384</summary>
385<div class="accordion-body border-bottom p-0">
386<table class="table table-sm table-borderless small mb-0 border-0 table-striped bg-transparent" aria-label="User and system preferences">
387<tbody>
388<tr>
389<th class="text-muted px-2" scope=row>Cookies enabled
390<td class=small id=systemCookiesEnabled>–
391<tr>
392<th class="text-muted px-2" scope=row>Locale
393<td class=small id=systemLocale>–
394<tr>
395<th class="text-muted px-2" scope=row>Preferred languages
396<td class=small id=systemPreferredLanguages>–
397<tr>
398<th class="text-muted px-2" scope=row>Color scheme
399<td class=small id=systemColorScheme>–
400<tr>
401<th class="text-muted px-2" scope=row>Prefers contrast
402<td class=small id=systemPrefersContrast>–
403<tr>
404<th class="text-muted px-2" scope=row>Reduced motion
405<td class=small id=systemReducedMotion>–
406</table>
407</div>
408</details>
409<details class=accordion-item name=systemInfoAccordion id=networkAccordion>
410<summary class="accordion-button py-1 px-2">
411<span class="accordion-header user-select-none">Network</span>
412</summary>
413<div class="accordion-body p-0">
414<table class="table table-sm table-borderless small mb-0 border-0 table-striped bg-transparent" aria-label=Network>
415<tbody>
416<tr id=rowSystemIP>
417<th class="text-muted px-2" scope=row>IP address
418<td class=small id=systemIP>–
419<tr id=rowSystemIPVersion>
420<th class="text-muted px-2" scope=row>IP version
421<td class=small id=systemIPVersion>–
422<tr id=rowSystemISP>
423<th class="text-muted px-2" scope=row>ISP
424<td class=small id=systemISP>–
425<tr id=rowSystemLocation>
426<th class="text-muted px-2" scope=row>Location
427<td class=small id=systemLocation>–
428<tr id=rowSystemConnectionSpeed>
429<th class="text-muted px-2" scope=row>Connection speed
430<td class=small id=systemConnectionSpeed>–
431<tr id=rowSystemDownlink>
432<th class="text-muted px-2" scope=row>Downlink
433<td class=small id=systemDownlink>–
434<tr id=rowSystemRTT>
435<th class="text-muted px-2" scope=row>RTT
436<td class=small id=systemRTT>–
437<tr id=rowSystemDataSaver>
438<th class="text-muted px-2" scope=row>Data saver
439<td class=small id=systemDataSaver>–
440<tr>
441<th class="text-muted px-2" scope=row>Security
442<td class=small id=systemSecurity>–
443<tr id=rowSystemConnectionType hidden>
444<th class="text-muted px-2" scope=row>Connection type
445<td class=small id=systemConnectionType>–
446</table>
447</div>
448</details>
449</div>
450</div>
451</div>
452</div>
453</div>
454</div>
455</div>
456</dialog>
457<script src=/js/modal-settings.js defer fetchpriority=low></script>
vendor: 1 bytes, line 457
457
458<script>var tooltipTriggerList=[].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')),tooltipList=tooltipTriggerList.map(function(tooltipTriggerEl){return new bootstrap.Tooltip(tooltipTriggerEl)})</script>
458
459<div class="modal fade" tabindex=-1 id=modalCoffee aria-hidden=true>
460<div class="modal-dialog modal-dialog-centered">
461<div class="modal-content modal-coffee shadow-lg bg-dark">
462<div class="modal-header border-0">
463<button type=button class="btn-close text-white" data-bs-dismiss=modal aria-label=Close>
464</button>
465</div>
466<div class="modal-body border-0">
467<br>
468</div>
469</div>
470</div>
471</div>
472<button type=button aria-label="scroll to top" class="btn-to-top bg-dark text-white border-0 rounded position-fixed shadow"></button>
472<script type=application/ld+json>
473{
474  "@context": "https://schema.org",
475  "@type": "WebSite",
476  "name": "Christian Oliff",
477  "url": "https:\/\/christianoliff.com\/",
478  "inLanguage":"en-GB",
479  "isFamilyFriendly": "true",
480  "description": "Online Adventures of a front-end web developer"
481}
482</script>
vendor: 1 bytes, line 482
482

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.