<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:webfeeds="http://webfeeds.org/rss/1.0">
<channel>
<title>Christian Oliff</title>
<link>https://christianoliff.com/</link>
<icon>https://christianoliff.com/icon.png</icon>
<image>
<url>https://christianoliff.com/icon.png</url>
<title>christian oliff</title>
<link>https://christianoliff.com/</link>
</image>
<description>Recent content on Christian Oliff</description>
<webfeeds:icon>https://christianoliff.com//icon.png</webfeeds:icon>
<webfeeds:accentColor>00FF00</webfeeds:accentColor>
<webfeeds:cover image="https://christianoliff.com//img/header/header-factory.png"/>
<webfeeds:logo>https://christianoliff.com//icon.png</webfeeds:logo>
<language>en-GB</language>
<lastBuildDate>Thu, 26 Mar 2026 01:00:00 +0000</lastBuildDate><atom:link href="https://christianoliff.com/feed.xml" rel="self" type="application/rss+xml"/>
<item>
<title>Bootstrap Icons as CSS variables</title>
<link>https://christianoliff.com/blog/bootstrap-icons-css/</link>
<pubDate>Thu, 26 Mar 2026 01:00:00 +0000</pubDate>
<guid>https://christianoliff.com/blog/bootstrap-icons-css/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2026/bootstrap-icons-css.png" alt=""/>&lt;/p>&lt;p&gt;Using icon fonts in HTML markup is still very popular, despite their many drawbacks. Using them means even if you only use a single icon, you still need to load the font file and the CSS for that entire icon set which can be a (relatively) significant performance overhead. Many sites are loading icon fonts from third-party CDNs too which can be blocked by users content blockers.&lt;/p&gt;
&lt;p&gt;In fact, CSS Tricks did an &lt;a href="https://css-tricks.com/inline-svg-vs-icon-fonts-cagematch/" target="_blank" rel="noopener"&gt;Inline SVG vs Icon Fonts Cagematch&lt;/a&gt; article 12 years ago (!) which concluded that inline SVGs are a better choice for icons, and since then the benefits of avoiding icon fonts have only grown.&lt;/p&gt;
&lt;p&gt;I can see the appeal of using icon fonts, though, if you&amp;rsquo;re using Bootstrap Icons for example.. just use markup like:&lt;/p&gt;
&lt;p&gt;&lt;i class="bi bi-heart"&gt;&lt;/i&gt;&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;bi bi-heart&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;There&amp;rsquo;s a better way though! Instead of using icon fonts, we can set all the icons we need as CSS variables and then map them to a CSS class - so we can use them in a similar way to the webfonts but without the extra file downloads and the other drawbacks.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve released &lt;a href="https://github.com/coliff/bootstrap-icons-css/" target="_blank" rel="noopener"&gt;Bootstrap Icons as CSS variables&lt;/a&gt;, a small project that exposes &lt;a href="https://icons.getbootstrap.com/" target="_blank" rel="noopener"&gt;Bootstrap Icons&lt;/a&gt; as CSS custom properties.&lt;/p&gt;
&lt;p&gt;So you have access to the icon as a CSS variable like this:&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;--bi-hearts&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;data:image/svg+xml;utf8,&amp;lt;svg xmlns=\&amp;#34;http://www.w3.org/2000/svg\&amp;#34; fill=\&amp;#34;currentColor\&amp;#34; viewBox=\&amp;#34;0 0 16 16\&amp;#34;&amp;gt;&amp;lt;path fill-rule=\&amp;#34;evenodd\&amp;#34; d=\&amp;#34;M4.931.481c1.627-1.671 5.692 1.254 0 5.015-5.692-3.76-1.626-6.686 0-5.015m6.84 1.794c1.084-1.114 3.795.836 0 3.343-3.795-2.507-1.084-4.457 0-3.343M7.84 7.642c2.71-2.786 9.486 2.09 0 8.358-9.487-6.268-2.71-11.144 0-8.358\&amp;#34;/&amp;gt;&amp;lt;/svg&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;and a class to reference it:&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;bi-heart&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;mask-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;heart&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;So your HTML markup is identical to using icon fonts:&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;bi-heart&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;You can size the icon with CSS like so:&lt;/p&gt;
&lt;p&gt;&lt;i class="bi-heart" style="height: 2rem; width: 2rem;"&gt;&lt;/i&gt;&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;bi-heart&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;height: 2rem; width: 2rem;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The package includes the generated CSS - with both CSS variables and class names referencing the CSS variables as SVG masks.&lt;/p&gt;
&lt;div class="d-block w-100"&gt;
&lt;div
class="alert alert-info small bg-body bg-opacity-50 bd-blur "
role="alert" style="border-left-width: 0.5rem;"&gt;
&lt;strong&gt;Browser compatibility:&lt;/strong&gt; CSS &lt;code&gt;mask-image&lt;/code&gt; is supported unprefixed in all modern browsers (Chrome 120, Safari 15.4, Firefox 53 — &lt;a href="https://caniuse.com/?search=mask-image" target="_blank" rel="noopener"&gt;caniuse&lt;/a&gt;). To widen support further (Safari 4.0+, Opera), you can use &lt;a href="https://github.com/postcss/autoprefixer" target="_blank" rel="noopener"&gt;Autoprefixer&lt;/a&gt; to automatically add &lt;code&gt;-webkit-mask-image&lt;/code&gt; prefix (alongside &lt;code&gt;mask-image&lt;/code&gt;). Because this uses CSS variables, the same variables are referenced from &lt;code&gt;:root&lt;/code&gt; without increasing filesize much. Neat!
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The stylesheet is approx 1.3 MB (~230 KB gzipped) and includes all 2078 icons. You can reduce file size and improve performance by only including the CSS (or variables) for the icons you need.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Demo &amp;amp; examples: &lt;a href="https://coliff.github.io/bootstrap-icons-css/" target="_blank" rel="noopener"&gt;https://coliff.github.io/bootstrap-icons-css/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;GitHub repository: &lt;a href="https://github.com/coliff/bootstrap-icons-css/" target="_blank" rel="noopener"&gt;https://github.com/coliff/bootstrap-icons-css/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;npm package: &lt;a href="https://www.npmjs.com/package/bootstrap-icons-css" target="_blank" rel="noopener"&gt;https://www.npmjs.com/package/bootstrap-icons-css&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;style&gt;
.btn {
display: none !important;
}
&lt;/style&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2026/bootstrap-icons-css.png"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2026/bootstrap-icons-css.png"/>
</item>
<item>
<title>Web Developer Tools+ iOS App</title>
<link>https://christianoliff.com/blog/web-developer-tools-plus-ios-app/</link>
<pubDate>Tue, 03 Mar 2026 09:01:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/web-developer-tools-plus-ios-app/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2026/header-web-developer-tools-plus-ios-app.jpg" alt=""/>&lt;/p>&lt;p&gt;As an iPad Pro owning front-end developer, I&amp;rsquo;ve often been a bit frustrated at the lack of developer tools for testing and debugging websites on the go. So I created Web DevTools+, a free Safari extension for iOS and iPadOS.&lt;/p&gt;
&lt;div class="d-flex justify-content-center"&gt;
&lt;div id="hero"
class="carousel slide carousel-indicators-below carousel-dark rounded-5"
data-bs-ride="carousel"
data-bs-interval="6000"&gt;
&lt;div class="carousel-inner mx-auto"&gt;
&lt;div class="carousel-item active bg-black rounded-5 border overflow-hidden"&gt;
&lt;img src="https://christianoliff.com/img/2026/web-devtools-plus-ios-screenshot-1.webp" class="d-block object-fit-cover mx-auto" alt="Web DevTools&amp;#43; screenshot 1" width="320" height="688" style="max-width: 100%; width: 320px; height: 688px;"&gt;&lt;/div&gt;
&lt;div class="carousel-item bg-black rounded-5 border overflow-hidden"&gt;
&lt;img src="https://christianoliff.com/img/2026/web-devtools-plus-ios-screenshot-2.webp" class="d-block object-fit-cover mx-auto" alt="Web DevTools&amp;#43; screenshot 2" width="320" height="688" style="max-width: 100%; width: 320px; height: 688px;"&gt;&lt;/div&gt;
&lt;div class="carousel-item bg-black rounded-5 border overflow-hidden"&gt;
&lt;img src="https://christianoliff.com/img/2026/web-devtools-plus-ios-screenshot-3.webp" class="d-block object-fit-cover mx-auto" alt="Web DevTools&amp;#43; screenshot 3" width="320" height="688" style="max-width: 100%; width: 320px; height: 688px;"&gt;&lt;/div&gt;
&lt;div class="carousel-item bg-black rounded-5 border overflow-hidden"&gt;
&lt;img src="https://christianoliff.com/img/2026/web-devtools-plus-ios-screenshot-4.webp" class="d-block object-fit-cover mx-auto" alt="Web DevTools&amp;#43; screenshot 4" width="320" height="688" style="max-width: 100%; width: 320px; height: 688px;"&gt;&lt;/div&gt;
&lt;div class="carousel-item bg-black rounded-5 border overflow-hidden"&gt;
&lt;img src="https://christianoliff.com/img/2026/web-devtools-plus-ios-screenshot-5.webp" class="d-block object-fit-cover mx-auto" alt="Web DevTools&amp;#43; screenshot 5" width="320" height="688" style="max-width: 100%; width: 320px; height: 688px;"&gt;&lt;/div&gt;
&lt;div class="carousel-item bg-black rounded-5 border overflow-hidden"&gt;
&lt;img src="https://christianoliff.com/img/2026/web-devtools-plus-ios-screenshot-6.webp" class="d-block object-fit-cover mx-auto" alt="Web DevTools&amp;#43; screenshot 6" width="320" height="688" style="max-width: 100%; width: 320px; height: 688px;"&gt;&lt;/div&gt;
&lt;div class="carousel-item bg-black rounded-5 border overflow-hidden"&gt;
&lt;img src="https://christianoliff.com/img/2026/web-devtools-plus-ios-screenshot-7.webp" class="d-block object-fit-cover mx-auto" alt="Web DevTools&amp;#43; screenshot 7" width="320" height="688" style="max-width: 100%; width: 320px; height: 688px;"&gt;&lt;/div&gt;
&lt;div class="carousel-item bg-black rounded-5 border overflow-hidden"&gt;
&lt;img src="https://christianoliff.com/img/2026/web-devtools-plus-ios-screenshot-8.webp" class="d-block object-fit-cover mx-auto" alt="Web DevTools&amp;#43; screenshot 8" width="320" height="688" style="max-width: 100%; width: 320px; height: 688px;"&gt;&lt;/div&gt;
&lt;div class="carousel-item bg-black rounded-5 border overflow-hidden"&gt;
&lt;img src="https://christianoliff.com/img/2026/web-devtools-plus-ios-screenshot-9.webp" class="d-block object-fit-cover mx-auto" alt="Web DevTools&amp;#43; screenshot 9" width="320" height="688" style="max-width: 100%; width: 320px; height: 688px;"&gt;&lt;/div&gt;
&lt;div class="carousel-item bg-black rounded-5 border overflow-hidden"&gt;
&lt;img src="https://christianoliff.com/img/2026/web-devtools-plus-ios-screenshot-10.webp" class="d-block object-fit-cover mx-auto" alt="Web DevTools&amp;#43; screenshot 10" width="320" height="688" style="max-width: 100%; width: 320px; height: 688px;"&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div class="carousel-indicators position-static mt-3 mb-0"&gt;&lt;button type="button"
class="bg-white active"
data-bs-target="#hero"
data-bs-slide-to="0"
aria-current="true"
aria-label="Slide 1"&gt;&lt;/button&gt;&lt;button type="button"
class="bg-white "
data-bs-target="#hero"
data-bs-slide-to="1"
aria-label="Slide 2"&gt;&lt;/button&gt;&lt;button type="button"
class="bg-white "
data-bs-target="#hero"
data-bs-slide-to="2"
aria-label="Slide 3"&gt;&lt;/button&gt;&lt;button type="button"
class="bg-white "
data-bs-target="#hero"
data-bs-slide-to="3"
aria-label="Slide 4"&gt;&lt;/button&gt;&lt;button type="button"
class="bg-white "
data-bs-target="#hero"
data-bs-slide-to="4"
aria-label="Slide 5"&gt;&lt;/button&gt;&lt;button type="button"
class="bg-white "
data-bs-target="#hero"
data-bs-slide-to="5"
aria-label="Slide 6"&gt;&lt;/button&gt;&lt;button type="button"
class="bg-white "
data-bs-target="#hero"
data-bs-slide-to="6"
aria-label="Slide 7"&gt;&lt;/button&gt;&lt;button type="button"
class="bg-white "
data-bs-target="#hero"
data-bs-slide-to="7"
aria-label="Slide 8"&gt;&lt;/button&gt;&lt;button type="button"
class="bg-white "
data-bs-target="#hero"
data-bs-slide-to="8"
aria-label="Slide 9"&gt;&lt;/button&gt;&lt;button type="button"
class="bg-white "
data-bs-target="#hero"
data-bs-slide-to="9"
aria-label="Slide 10"&gt;&lt;/button&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="features" class="mt-5"&gt;Features
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#features"
aria-label="Link to this section: Features"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Elements inspector with ability to edit, automatically highlights currently selected section and syntax-highlighted code.&lt;/li&gt;
&lt;li&gt;CSS Quick tools and CSS overview&lt;/li&gt;
&lt;li&gt;Emulate vision deficiencies (such as color blindness, blurred vision)&lt;/li&gt;
&lt;li&gt;Emulate CSS media features (prefers-contrast, prefers color-scheme etc)&lt;/li&gt;
&lt;li&gt;Network inspector with sorting and filters, source viewer, HTTP headers tables and more.&lt;/li&gt;
&lt;li&gt;Detailed SEO and Meta tag views with Open Graph previews, Web Manifest breakdowns and robots.txt file details.&lt;/li&gt;
&lt;li&gt;Storage panel with options to view or delete cookies, localStorage and Session storage.&lt;/li&gt;
&lt;li&gt;Accessibility audits, info and debug tools (ARIA inspect and img alt inspect).&lt;/li&gt;
&lt;li&gt;Detailed Device Info panel with UserAgent, display and screen resolution, network speeds, connection type, ISP and more.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &amp;lsquo;More Tools&amp;rsquo; tab is useful as it gives one-tap quick audits from 8 popular, free services (Lighthouse, HTTP Observatory, Wave Web Accessibility etc). No need to login, it&amp;rsquo;ll open a new tab with your audit right there!&lt;/p&gt;
&lt;h2 id="roadmap" class="mt-5"&gt;Roadmap
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#roadmap"
aria-label="Link to this section: Roadmap"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;I&amp;rsquo;m looking to add a Console tab (currently in Settings &amp;gt; Labs tab), an Audits tab and optional themes.&lt;/p&gt;
&lt;p&gt;Web DevTools+ is free with no adverts, tracking or subscriptions.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://apps.apple.com/app/apple-store/id6759253731?pt=378206&amp;amp;ct=christianoliffcom&amp;amp;mt=8" target="_blank" rel="noopener"&gt;https://apps.apple.com/app/apple-store/id6759253731?pt=378206&amp;ct=christianoliffcom&amp;mt=8&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Happy to hear any feedback, suggestions/feature requests (Mastodon and Bluesky links below)&lt;/p&gt;
&lt;style&gt;
header {
background-position: top !important;
}
.carousel-item img {
max-height: 684px !important;
}
main img {
max-width: 100%;
}
&lt;/style&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2026/header-web-developer-tools-plus-ios-app.jpg"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2026/header-web-developer-tools-plus-ios-app.jpg"/>
</item>
<item>
<title>Bootstrap 5 CSS Breakpoint Indicator</title>
<link>https://christianoliff.com/blog/bootstrap-5-css-breakpoint-indicator/</link>
<pubDate>Wed, 17 Dec 2025 02:01:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/bootstrap-5-css-breakpoint-indicator/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2025/header-bootstrap-css-breakpoint-indicator.png" alt=""/>&lt;/p>&lt;p&gt;When working on Bootstrap projects I often find myself wanting to quickly see the current CSS breakpoint. I created a simple CSS snippet that shows the current Bootstrap CSS breakpoint in the browser&amp;rsquo;s viewport.&lt;/p&gt;
&lt;p&gt;It appears at all times in the bottom left corner of the viewport and as it&amp;rsquo;s small, partially transparent and blurred it doesn&amp;rsquo;t distract from the main content.&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;aspect-ratio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;backdrop-filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;blur&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="kt"&gt;rem&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#fff&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;XS&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;system-ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;sans-serif&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="kt"&gt;rem&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pointer-events&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;none&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;fixed&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;center&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9999&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;/* SM ≥576px */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;media&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;width&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nt"&gt;576px&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;SM&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;/* MD ≥768px */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;media&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;width&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nt"&gt;768px&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;MD&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;/* LG ≥992px */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;media&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;width&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nt"&gt;992px&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;LG&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;/* XL ≥1200px */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;media&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;width&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nt"&gt;1200px&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;XL&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;/* XXL ≥1400px */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;media&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;width&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nt"&gt;1400px&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;XXL&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id="demo" class="mt-5"&gt;Demo
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#demo"
aria-label="Link to this section: Demo"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;You can see a demo on this page or view an isolate &lt;a href="https://code.christianoliff.com/bootstrap-5-css-breakpoint-debugger/" target="_blank" rel="noopener"&gt;demo of the Bootstrap 5 CSS Breakpoint Debugger&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Tip: You can set the indicator to be hidden when using/interacting with the site with:&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;style&gt;
body::after {
aspect-ratio: 1 / 1 !important;
backdrop-filter: blur(99px) !important;
background-color: rgb(0 0 0 / 0.8) !important;
border-radius: 8px !important;
bottom: 0.25rem !important;
color: #fff !important;
content: "XS";
font-family: system-ui, sans-serif !important;
font-size: 12px !important;
left: 0.25rem !important;
min-width: 28px !important;
opacity: 0.9 !important;
padding: 4px !important;
pointer-events: none !important;
position: fixed !important;
text-align: center !important;
z-index: 9999 !important;
}
/* SM ≥576px */
@media (width &gt;= 576px) {
body::after {
content: "SM";
}
}
/* MD ≥768px */
@media (width &gt;= 768px) {
body::after {
content: "MD";
}
}
/* LG ≥992px */
@media (width &gt;= 992px) {
body::after {
content: "LG";
}
}
/* XL ≥1200px */
@media (width &gt;= 1200px) {
body::after {
content: "XL";
}
}
/* XXL ≥1400px */
@media (width &gt;= 1400px) {
body::after {
content: "XXL";
}
}
&lt;/style&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2025/header-bootstrap-css-breakpoint-indicator.png"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2025/header-bootstrap-css-breakpoint-indicator.png"/>
</item>
<item>
<title>Building a Bootstrap Modal with the dialog HTML element</title>
<link>https://christianoliff.com/blog/bootstrap-modal-with-dialog/</link>
<pubDate>Sun, 14 Dec 2025 02:01:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/bootstrap-modal-with-dialog/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2025/header-bootstrap-modal-dialog.png" alt=""/>&lt;/p>&lt;p&gt;Continuing my series of posts on building Bootstrap components using just CSS and native HTML elements, this post demonstrates how to create a Bootstrap modal dialog using the &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; HTML element.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element has been supported by &lt;a href="https://caniuse.com/dialog" target="_blank" rel="noopener"&gt;all major browsers&lt;/a&gt; for a while now and can be used with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog#invoker_commands" target="_blank" rel="noopener"&gt;Invoker Commands&lt;/a&gt; and is a great way to create a modal dialog without the need of JavaScript.&lt;/p&gt;
&lt;p&gt;You can create a Bootstrap modal using the &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element with just a tiny bit of custom CSS.&lt;/p&gt;
&lt;div class="bd-example-snippet bd-code-snippet mb-2 border border-rounded"&gt;&lt;div class="bd-example p-4 m-0 border-0"&gt;
&lt;button class="btn bg-primary btn-primary" type="button" id="btnDialog" commandfor="dialog"
command="show-modal" closedby="any"&gt;
Open modal
&lt;/button&gt;
&lt;dialog id="dialog" class="position-relative border-1" closedby="any"&gt;
&lt;div class="modal d-flex position-static"&gt;
&lt;div class="modal-dialog w-100 m-0"&gt;
&lt;div class="modal-content bg-body"&gt;
&lt;div class="modal-header"&gt;
&lt;h1 class="modal-title fs-5 mt-0"&gt;Modal title&lt;/h1&gt;
&lt;form method="dialog" class="ms-auto me-1"&gt;
&lt;button type="submit" class="btn-close"&gt;
&lt;span class="visually-hidden"&gt;Close&lt;/span&gt;
&lt;/button&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;div class="modal-body py-2"&gt;
&lt;p&gt;Modal body text goes here.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="modal-footer"&gt;
&lt;button type="button" class="btn btn-primary"&gt;Save changes&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/dialog&gt;
&lt;style&gt;
dialog {
background-clip: padding-box;
background-color: var(--bs-body-bg);
border-radius: var(--bs-border-radius-lg);
border: 1px solid var(--bs-border-color);
box-shadow: var(--bs-box-shadow-sm);
color: var(--bs-body-color);
max-width: 100%;
min-width: 420px;
overflow-x: hidden;
overflow-y: auto;
padding: var(--bs-modal-padding-y) var(--bs-modal-padding-x);
z-index: var(--bs-modal-zindex);
&amp;::backdrop {
background-color: rgba(0,0,0,.75);
animation: .3s fade-in;
}
}
&lt;/style&gt;
&lt;/div&gt;&lt;div class="d-flex align-items-center highlight-toolbar ps-3 pe-2 py-1 border-0 border-top border-bottom"&gt;
&lt;small class="font-monospace text-body-secondary text-uppercase d-none"&gt;html&lt;/small&gt;
&lt;div class="d-flex ms-auto d-none"&gt;
&lt;button type="button" class="btn-edit text-nowrap" title="Try it on StackBlitz" data-bs-toggle="tooltip"
data-bs-placement="top" aria-label="Try it on StackBlitz"&gt;
&lt;svg viewBox="0 0 28 28" aria-hidden="true" class="text-white-50" height="1em" fill="currentColor"&gt;
&lt;path d="M12.747 16.273h-7.46L18.925 1.5l-3.671 10.227h7.46L9.075 26.5l3.671-10.227z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;/button&gt;
&lt;button type="button" class="btn-clipboard mt-0 me-0" title="Copy to clipboard" data-bs-toggle="tooltip"
data-bs-placement="top" aria-label="Copy to clipboard"&gt;
&lt;svg height="1em" viewBox="0 0 384 512" fill="currentColor"&gt;
&lt;path
d="M192 32c-22.3 0-41.2 15.3-46.5 36c-1.8 7.1-8.2 12-15.5 12H112c-8.8 0-16 7.2-16 16v32h96 96V96c0-8.8-7.2-16-16-16H254c-7.3 0-13.7-4.9-15.5-12c-5.3-20.7-24.1-36-46.5-36zM118.7 48C131 19.8 159.2 0 192 0s61 19.8 73.3 48H272c20.9 0 38.7 13.4 45.3 32H320c35.3 0 64 28.7 64 64V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V144c0-35.3 28.7-64 64-64h2.7C73.3 61.4 91.1 48 112 48h6.7zM320 128c0 17.7-14.3 32-32 32H192 96c-17.7 0-32-14.3-32-32V112c-17.7 0-32 14.3-32 32V448c0 17.7 14.3 32 32 32H320c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32v16zM192 64a16 16 0 1 1 0 32 16 16 0 1 1 0-32z" /&gt;
&lt;/svg&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;btn bg-primary btn-primary&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;button&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;btnDialog&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;commandfor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;dialog&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;show-modal&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;closedby&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;any&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Open modal
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;dialog&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;dialog&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;position-relative border-1&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;closedby&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;any&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;modal d-flex position-static&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;modal-dialog w-100 m-0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;modal-content bg-body&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;modal-header&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;modal-title fs-5 mt-0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Modal title&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;dialog&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ms-auto me-1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;submit&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;btn-close&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;visually-hidden&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Close&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;modal-body py-2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Modal body text goes here.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;modal-footer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;button&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;btn btn-primary&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Save changes&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;dialog&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;background-clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;padding-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt; &lt;span class="kc"&gt;solid&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kc"&gt;color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;shadow&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kc"&gt;color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="kt"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;420&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;overflow-x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;overflow-y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;modal&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;padding&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;modal&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;padding&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;modal&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;zindex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;&amp;amp;::backdrop&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;.75&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;.3&lt;/span&gt;&lt;span class="kt"&gt;s&lt;/span&gt; &lt;span class="n"&gt;fade-in&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;script src="https://christianoliff.com/js/clipboard.min.js"&gt;&lt;/script&gt;
&lt;script&gt;
document.querySelectorAll('.btn-edit').forEach(btn =&gt; {
btn.addEventListener('click', event =&gt; {
const htmlSnippet = event.target.closest('.bd-code-snippet').querySelector('.bd-example').innerHTML
const classes = Array.from(event.target.closest('.bd-code-snippet').querySelector('.bd-example').classList).join(' ')
const jsSnippet = event.target.closest('.bd-code-snippet').querySelector('.btn-edit').getAttribute('data-sb-js-snippet')
StackBlitzSDK.openBootstrapSnippet(htmlSnippet, jsSnippet, classes)
})
})
StackBlitzSDK.openBootstrapSnippet = (htmlSnippet, jsSnippet, classes) =&gt; {
const markup = `&lt;!doctype html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
&lt;meta charset="utf-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;
&lt;link href=" " rel="stylesheet"&gt;
&lt;title&gt;Example&lt;/title&gt;
&lt;${'script'} src=" "&gt;&lt;/${'script'}&gt;
&lt;/head&gt;
&lt;body class="p-3 m-0 border-0 ${classes}"&gt;
\x3C!-- Example Code --&gt;
${htmlSnippet.replace(/^/gm, ' ')}
\x3C!-- End Example Code --&gt;
&lt;/body&gt;
&lt;/html&gt;`
const jsSnippetContent = jsSnippet ? '' : null
const project = {
files: {
'index.html': markup,
'index.js': jsSnippetContent
},
title: 'Example',
description: `example from ${window.location.href}`,
template: jsSnippet ? 'javascript' : 'html',
tags: ['bootstrap']
}
StackBlitzSDK.openProject(project, { openFile: 'index.html' })
}
&lt;/script&gt;
&lt;h2 id="demo" class="mt-5"&gt;Demo
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#demo"
aria-label="Link to this section: Demo"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;You can also view &lt;a href="https://code.christianoliff.com/bootstrap-modal-no-js/" target="_blank" rel="noopener"&gt;an external demo&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="considerations" class="mt-5"&gt;Considerations
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#considerations"
aria-label="Link to this section: Considerations"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Invoker commands are now supported in all modern browsers. In order to support older browsers, you can add the &lt;a href="https://github.com/keithamus/invokers-polyfill" target="_blank" rel="noopener"&gt;invokers polyfill&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The above example allows the user to dismiss the modal by clicking outside of it or pressing the Escape key. If you want to prevent this behavior, you can remove the &lt;code&gt;closedby=&amp;quot;any&amp;quot;&lt;/code&gt; attribute from the &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element.&lt;/li&gt;
&lt;li&gt;The dialog element fades in when opened using the &lt;code&gt;::backdrop&lt;/code&gt; pseudo-element and Bootstrap&amp;rsquo;s own fade-in animation, but when dismissing the dialog it doesn&amp;rsquo;t fade out.&lt;/li&gt;
&lt;li&gt;Bootstrap 6 will likely rename the modal component to dialog and use the &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element and there&amp;rsquo;s an open &lt;a href="https://github.com/twbs/bootstrap/pull/41917" target="_blank" rel="noopener"&gt;PR on GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2025/header-bootstrap-modal-dialog.png"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2025/header-bootstrap-modal-dialog.png"/>
</item>
<item>
<title>Image Size Info Browser Extension</title>
<link>https://christianoliff.com/blog/image-size-info-browser-extension/</link>
<pubDate>Thu, 11 Dec 2025 02:01:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/image-size-info-browser-extension/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2025/header-image-size-info-browser-extension.png" alt=""/>&lt;/p>&lt;p&gt;I used to regularly use a simple browser extension that showed image size information, you just right-clicked on any image and it would display a simple dialog with the image dimensions, file size, and full URL. It was useful for web development and design work, for example to know if an image was being scaled or if the file-size was too large.&lt;/p&gt;
&lt;p&gt;Unfortunately, the extension was removed from the extension store. I couldn&amp;rsquo;t find a suitable replacement that met my needs, so I created my own.&lt;/p&gt;
&lt;p&gt;
&lt;img src="https://christianoliff.com/img/2025/image-size-info-browser-extension-screenshot.png" alt="Image Size Info Browser Extension" decoding="async" loading="lazy"
width=1280 height="800"
&gt;
&lt;/p&gt;
&lt;p&gt;It displays the image&amp;rsquo;s URL (with a button to open it in a new tab), actual dimensions, displayed/rendered dimensions, file size, and date-modified. It works in both Chrome and Edge browsers.&lt;/p&gt;
&lt;p&gt;I didn&amp;rsquo;t publish it to the Firefox Extension store because I used a service worker to fetch the image headers, which isn&amp;rsquo;t supported in Firefox extensions, and there are already other extensions that provide similar functionality.&lt;/p&gt;
&lt;p&gt;I may add additional features in the future such as MIME type detection and alt text display. If you have any suggestions or feature requests, feel free to let me know.&lt;/p&gt;
&lt;h2 id="download" class="mt-5"&gt;Download
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#download"
aria-label="Link to this section: Download"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="https://microsoftedge.microsoft.com/addons/detail/image-info/ffndadamfjponalmaapceoapiejkibhe" target="_blank" rel="noopener"&gt;Edge Add-on&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chromewebstore.google.com/detail/image-size-info/ogeoebhoddicihocmalpnoapccpalngh?authuser=0" target="_blank" rel="noopener"&gt;Chrome Web Store&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;style&gt;
main img {
max-width: 100%;
padding: 30px;
}
&lt;/style&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2025/header-image-size-info-browser-extension.png"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2025/header-image-size-info-browser-extension.png"/>
</item>
<item>
<title>Building a Bootstrap Accordion with the details/summary HTML tags in 2025</title>
<link>https://christianoliff.com/blog/building-a-bootstrap-accordion-with-the-details-summary-html-tags-2025/</link>
<pubDate>Thu, 21 Aug 2025 01:01:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/building-a-bootstrap-accordion-with-the-details-summary-html-tags-2025/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2023/header-bootstrap-accordion-with-details-summary.jpg" alt=""/>&lt;/p>&lt;style&gt;
details.accordion-item:not([open]) .accordion-button {
background-color: var(--bs-accordion-bg);
}
details.accordion-item:not([open]):last-of-type .accordion-button {
border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius);
}
details.accordion-item:not([open]) .accordion-button::after {
background-image: var(--bs-accordion-btn-active-icon);
transform: unset;
}
details.accordion-item[open] .accordion-button::after {
background-image: var(--bs-accordion-btn-icon);
transform: var(--bs-accordion-btn-icon-transform);
}
details.accordion-item .accordion-header {
-webkit-user-select: none;
user-select: none;
}
/* Hide the default disclosure triangle on Safari */
summary.accordion-button::-webkit-details-marker {
display: none;
}
@media (prefers-reduced-motion: no-preference) {
details.accordion-item {
interpolate-size: allow-keywords;
}
}
details.accordion-item::details-content {
block-size: 0;
overflow-y: clip;
transition: content-visibility 0.2s allow-discrete, block-size 0.2s;
}
details.accordion-item[open]::details-content {
block-size: auto;
}
&lt;/style&gt;
&lt;p&gt;A few years ago &lt;a href="https://christianoliff.com/blog/building-a-bootstrap-accordion-with-the-details-summary-html-tags/" &gt;I wrote a short post&lt;/a&gt; about building a Bootstrap accordion using the &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;summary&amp;gt;&lt;/code&gt; HTML tags. The idea was to create a collapsible accordion without needing any JavaScript, relying solely on CSS for styling and the native functionality of the &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; element.&lt;/p&gt;
&lt;p&gt;At the time it wasn&amp;rsquo;t possible to animate the opening and closing of the accordion (with CSS), but thanks to the relatively new &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::details-content" target="_blank" rel="noopener"&gt;&lt;code&gt;::details-content&lt;/code&gt;&lt;/a&gt; CSS pseudo-element with transitions we can do that now. So I&amp;rsquo;m revisiting that solution with an update with no need for JavaScript at all.&lt;/p&gt;
&lt;p&gt;Note that the transition for now are only in Chrome/Edge, but I think support for Firefox and Safari is planned. If you&amp;rsquo;d prefer a more consistent experience across browsers, you might consider using the JavaScript-based solution in my original post.&lt;/p&gt;
&lt;div class="accordion border-bottom-0 my-5 pb-5"&gt;
&lt;details class="accordion-item border-bottom-0"&gt;
&lt;summary class="accordion-button rounded-top"&gt;
&lt;div class="accordion-header user-select-none"&gt;
Accordion Title 1
&lt;/div&gt;
&lt;/summary&gt;
&lt;div class="accordion-body border-bottom"&gt;
&lt;p&gt;
Last Friday night, yeah I think we broke the law, always say we're gonna stop. And on my 18th Birthday we got matching tattoos. All to me, give it all to me. Don't be a chicken boy, stop acting like a bitch. Suiting up for my crowning battle. Respect.
&lt;/p&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;details class="accordion-item border-bottom-0"&gt;
&lt;summary class="accordion-button"&gt;
&lt;div class="accordion-header user-select-none"&gt;
Accordion Title 2
&lt;/div&gt;
&lt;/summary&gt;
&lt;div class="accordion-body border-bottom"&gt;
&lt;p&gt;
Why don't you let me stop by? We freak in my jeep, Snoop Doggy Dogg on the stereo. Got a motel and built a fort out of sheets. It’s in the palm of your hand now baby. I was gonna hit it and quit it. Trying to connect the dots, don't know what to tell my boss.
&lt;/p&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;details class="accordion-item"&gt;
&lt;summary class="accordion-button"&gt;
&lt;div class="accordion-header user-select-none"&gt;
Accordion Title 3
&lt;/div&gt;
&lt;/summary&gt;
&lt;div class="accordion-body"&gt;
&lt;p&gt;
I know you get me so I let my walls come down, down. A perfect storm, perfect storm. Yes, we make angels cry, raining down on earth from up above. Do you ever feel like a plastic bag. The girl's a freak, she drive a jeep in Laguna Beach.
&lt;/p&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;h3 id="html" class="mt-5"&gt;HTML
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#html"
aria-label="Link to this section: HTML"&gt;&lt;/a&gt;
&lt;/h3&gt;&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion border-bottom-0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-item border-bottom-0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-button rounded-top&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-header user-select-none&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Accordion Title 1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-body border-bottom&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;....&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-item border-bottom-0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-button&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-header user-select-none&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Accordion Title 2&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-body border-bottom&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;....&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-item&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-button&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-header user-select-none&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Accordion Title 3&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-body&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;....&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id="custom-css" class="mt-5"&gt;Custom CSS
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#custom-css"
aria-label="Link to this section: Custom CSS"&gt;&lt;/a&gt;
&lt;/h3&gt;&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;not&lt;/span&gt;&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="nt"&gt;open&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;accordion&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;not&lt;/span&gt;&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="nt"&gt;open&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;last-of-type&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;border-bottom-right-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;accordion&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;border-bottom-left-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;accordion&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;not&lt;/span&gt;&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="nt"&gt;open&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-button&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;accordion&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;btn&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kc"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;unset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-item&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;open&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-button&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;accordion&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;btn&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kc"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;accordion&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;btn&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kc"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;/* Hide the default disclosure triangle on Safari */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-button&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;-webkit-details-marker&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;media&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;prefers-reduced-motion&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;no-preference&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;interpolate-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;allow-keywords&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-item&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;details-content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;block-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;overflow-y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;content&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;visibility&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="kt"&gt;s&lt;/span&gt; &lt;span class="n"&gt;allow-discrete&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;block&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;size&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="kt"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-item&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;open&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;details-content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;block-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="https://code.christianoliff.com/bootstrap-accordion-no-js/" target="_blank" rel="noopener"&gt;View demo &amp;amp; code&lt;/a&gt;&lt;/p&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2023/header-bootstrap-accordion-with-details-summary.jpg"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2023/header-bootstrap-accordion-with-details-summary.jpg"/>
</item>
<item>
<title>Using the Speculation Rules API to Improve Performance</title>
<link>https://christianoliff.com/blog/using-speculation-rules-to-improve-performance/</link>
<pubDate>Fri, 18 Jul 2025 09:01:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/using-speculation-rules-to-improve-performance/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2025/header-using-speculation-rules-to-improve-performance.png" alt=""/>&lt;/p>&lt;p&gt;If you have a multi-page site and want to improve performance when navigating between pages, I recommend using &lt;a href="https://developer.chrome.com/docs/web-platform/prerender-pages" target="_blank" rel="noopener"&gt;speculation rules&lt;/a&gt; to prefetch and render pages on hovering over a link. This can substantially reduce load times and improve the user experience.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve added it to this site and switching between pages is now even faster. Here&amp;rsquo;s how you can implement it - just stick this script in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; of your HTML and you&amp;rsquo;re good to go!&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;speculationrules&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;prerender&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;where&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;href_matches&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/*&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;eagerness&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;moderate&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The eagerness - moderate setting means that this performs speculations if you hold the pointer over a link for 200 milliseconds (or on the pointerdown event if that is sooner, and on mobile where there is no hover event).&lt;/p&gt;
&lt;p&gt;Speculation Rules are currently only available in Chrome/Edge and other Chromium-based browsers, so it doesn&amp;rsquo;t work in Safari or Firefox, however you can conditionally load the &lt;a href="https://instant.page/" target="_blank" rel="noopener"&gt;instant.page&lt;/a&gt; script. It&amp;rsquo;s only about 1 KB and provides similar functionality across all other browsers.&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Fallback to instant.page for browsers that don&amp;#39;t support speculation rules
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HTMLScriptElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;supports&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;HTMLScriptElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;supports&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;speculationrules&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;script&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;module&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;https://instant.page/5.2.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetchPriority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;low&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Unfortunately, ad blockers can interfere with speculation rules (the setting to disable preloading is checked by default on uBlock Origin and Privacy Badger), so users with ad blockers may not benefit from this feature.&lt;/p&gt;
&lt;h2 id="links" class="mt-5"&gt;Links
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#links"
aria-label="Link to this section: Links"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.chrome.com/docs/web-platform/prerender-pages" target="_blank" rel="noopener"&gt;Speculation Rules on Chrome Developers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Speculation_Rules_API" target="_blank" rel="noopener"&gt;Speculation Rules on MDN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://caniuse.com/mdn-html_elements_script_type_speculationrules" target="_blank" rel="noopener"&gt;Speculation Rules on CanIUse&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2025/header-using-speculation-rules-to-improve-performance.png"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2025/header-using-speculation-rules-to-improve-performance.png"/>
</item>
<item>
<title>Safari Wishlist (2025)</title>
<link>https://christianoliff.com/blog/safari-wishlist-2025/</link>
<pubDate>Fri, 11 Jul 2025 03:51:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/safari-wishlist-2025/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2025/header-safari-wishlist-2025.png" alt=""/>&lt;/p>&lt;p&gt;The Safari browser has come a long way in recent years, but there are still a few CSS/HTML features that I&amp;rsquo;d like to see added that would make it even better for web developers and users alike. I&amp;rsquo;ve previously shared my wishlists for Safari in &lt;a href="https://christianoliff.com/blog/safari-ios14-wishlist/" &gt;Summer 2020&lt;/a&gt;, and again in &lt;a href="https://christianoliff.com/blog/safari-for-ios-16-wishlist/" &gt;Summer 2022&lt;/a&gt;, and I&amp;rsquo;m happy to look back and see that many of my wishes have since been added to Safari. Now that we&amp;rsquo;re deep into 2025, it&amp;rsquo;s time to revisit and update that list!&lt;/p&gt;
&lt;h2 id="1-support-for-open--close-transitions-with-details" class="mt-5"&gt;1. Support for Open &amp;amp; Close Transitions with &amp;lt;details&amp;gt;
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#1-support-for-open--close-transitions-with-details"
aria-label="Link to this section: 1. Support for Open &amp;amp; Close Transitions with &amp;lt;details&amp;gt;"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Adam Argyle &lt;a href="https://nerdy.dev/open-and-close-transitions-for-the-details-element" target="_blank" rel="noopener"&gt;explains and demonstrates this best&lt;/a&gt; and I&amp;rsquo;d love to see Safari support the &lt;code&gt;open&lt;/code&gt; and &lt;code&gt;close&lt;/code&gt; transitions for the &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; element. This would allow developers to create smooth animations when expanding or collapsing details sections, enhancing the user experience - all without the need for JavaScript.&lt;/p&gt;
&lt;h2 id="2-support-for-invoker-commands" class="mt-5"&gt;2. Support for Invoker Commands
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#2-support-for-invoker-commands"
aria-label="Link to this section: 2. Support for Invoker Commands"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;The HTML &lt;code&gt;commandfor&lt;/code&gt;/&lt;code&gt;command&lt;/code&gt; attributes, &lt;a href="https://open-ui.org/components/invokers.explainer/" target="_blank" rel="noopener"&gt;as proposed by the Open UI group&lt;/a&gt; is already supported in Chrome/Edge, but not Safari. This would allow developers to create custom commands for elements, such as a button that opens a modal without the need for JavaScript. For now though, at least we have an awesome &lt;a href="https://github.com/keithamus/invokers-polyfill" target="_blank" rel="noopener"&gt;invokers-polyfill&lt;/a&gt; courtesy of Keith Cirkel which works great with Safari and Firefox.&lt;/p&gt;
&lt;p&gt;Note: The HTML &lt;code&gt;commandfor&lt;/code&gt;/&lt;code&gt;command&lt;/code&gt; attributes is testable via Developer Feature Flags in Safari though it didn&amp;rsquo;t seem to work for me.&lt;/p&gt;
&lt;h2 id="3-support-for-the-prefers-reduced-transparency-media-query" class="mt-5"&gt;3. Support for the &lt;code&gt;prefers-reduced-transparency&lt;/code&gt; Media Query
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#3-support-for-the-prefers-reduced-transparency-media-query"
aria-label="Link to this section: 3. Support for the prefers-reduced-transparency Media Query"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-transparency" target="_blank" rel="noopener"&gt;prefers-reduced-transparency&lt;/a&gt; CSS media feature is used to detect if the user has requested the web content uses less transparency.&lt;/p&gt;
&lt;p&gt;This would be very useful for creating a more accessible experience for users who may have difficulty with transparency effects. A pull requests for this feature had been &lt;a href="https://github.com/WebKit/webKit/pull/11560" target="_blank" rel="noopener"&gt;submitted to WebKit&lt;/a&gt; but has unfortunately been closed &lt;a href="https://github.com/WebKit/standards-positions/issues/145" target="_blank" rel="noopener"&gt;due to a potential fingerprinting risk&lt;/a&gt;. I really hope this can be revisited in the future!&lt;/p&gt;
&lt;h2 id="4-customizable-select-support" class="mt-5"&gt;4. Customizable Select Support
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#4-customizable-select-support"
aria-label="Link to this section: 4. Customizable Select Support"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Chrome 135 added &lt;code&gt;appearance: base-select&lt;/code&gt; to the &lt;code&gt;select&lt;/code&gt; element, which allows customizing the appearance of the select element with custom styles and HTML opening all kinds of possibilities. MDN has a &lt;a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select" target="_blank" rel="noopener"&gt;great guide on how to use it&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="5-textarea-field-sizing-css" class="mt-5"&gt;5. Textarea field-sizing CSS
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#5-textarea-field-sizing-css"
aria-label="Link to this section: 5. Textarea field-sizing CSS"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;The field-sizing CSS property allows form controls such as &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt; to be sized based on their content. Learn more at &lt;a href="https://web-platform-dx.github.io/web-features-explorer/features/field-sizing/" target="_blank" rel="noopener"&gt;Web Platform Features Explorer&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="6-css-anchor-positioning" class="mt-5"&gt;6. CSS Anchor Positioning
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#6-css-anchor-positioning"
aria-label="Link to this section: 6. CSS Anchor Positioning"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Anchor positioning was added to Chrome, Chrome Android, and Edge in Chromium 125. This makes it possible to position elements relative to an anchor element, which is a great way to create more flexible and accessible interfaces. It&amp;rsquo;s great to hear that it&amp;rsquo;s coming to Safari in iOS 26, but for now we can make do with this &lt;a href="https://github.com/oddbird/css-anchor-positioning?tab=readme-ov-file#css-anchor-positioning-polyfill" target="_blank" rel="noopener"&gt;awesome polyfill&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="7-scroll-driven-animations" class="mt-5"&gt;7. Scroll-driven Animations
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#7-scroll-driven-animations"
aria-label="Link to this section: 7. Scroll-driven Animations"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;I love the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-driven_animations" target="_blank" rel="noopener"&gt;scroll-driven animations&lt;/a&gt; in Chrome - you can really enhance interfaces without the need for a JavaScript library, and I&amp;rsquo;m happy to hear that they&amp;rsquo;re coming to Safari in iOS 26 this fall!&lt;/p&gt;
&lt;h2 id="8-low-data-mode-javascript-api" class="mt-5"&gt;8. Low-data Mode JavaScript API
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#8-low-data-mode-javascript-api"
aria-label="Link to this section: 8. Low-data Mode JavaScript API"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;A &amp;lsquo;Low Data Mode&amp;rsquo; has been available in iOS Network Settings for a few years now. Setting this will disable automatic app updates, background iCloud syncing and lower the video/audio streaming quality in some apps. It&amp;rsquo;d be great if this setting was available to web developers via a JavaScript API.&lt;/p&gt;
&lt;p&gt;I requested this feature via &lt;a href="https://github.com/feedback-assistant/reports/issues/90" target="_blank" rel="noopener"&gt;Feedback Assistant&lt;/a&gt; - &lt;a href="https://github.com/feedback-assistant/reports" target="_blank" rel="noopener"&gt;you can too&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="9-support-for-the-prefers-reduced-data-media-query" class="mt-5"&gt;9. Support for the &lt;code&gt;prefers-reduced-data&lt;/code&gt; Media Query
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#9-support-for-the-prefers-reduced-data-media-query"
aria-label="Link to this section: 9. Support for the prefers-reduced-data Media Query"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Related to the request above, the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-data" target="_blank" rel="noopener"&gt;prefers-reduced-data&lt;/a&gt; CSS media feature is used to detect if the user has requested the web content uses less data.&lt;/p&gt;
&lt;p&gt;This would be very useful to use smaller file-size or no background images, or default to fallback fonts instead of downloading heavy custom fonts.&lt;/p&gt;
&lt;h2 id="10-view-source-mode--safari-web-inspector" class="mt-5"&gt;10. View Source Mode / Safari Web Inspector
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#10-view-source-mode--safari-web-inspector"
aria-label="Link to this section: 10. View Source Mode / Safari Web Inspector"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;There are a few simple &lt;a href="https://andadinosaur.com/launch-web-inspector-for-ios#web-inspector-support" target="_blank" rel="noopener"&gt;&amp;lsquo;view source&amp;rsquo; third-party apps in the App Store&lt;/a&gt; for this, but it&amp;rsquo;d be really nice to see a more feature-rich native option for debugging sites with iPadOS. Ideally it should have a JavaScript console, network page resources and element inspector tabs. As an iPad Pro-owning web developer I&amp;rsquo;d like to be able to do more work/website testing on my iPad without needing to use my laptop/desktop.&lt;/p&gt;
&lt;p&gt;
&lt;img src="https://christianoliff.com/img/2025/web-inspector-app-for-ipad.webp" alt="Web Inspector App for iPad" decoding="async" loading="lazy"
width=2778 height="1940"
&gt;
&lt;small class="d-block text-muted ms-1"&gt;&lt;i&gt;Web Inspector App for iPad (iOS 26 Developer Beta)&lt;/i&gt;&lt;/small&gt;&lt;/p&gt;
&lt;style&gt;
main img {
border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
max-width: 80%;
margin-left: auto;
margin-right: auto;
}
&lt;/style&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2025/header-safari-wishlist-2025.png"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2025/header-safari-wishlist-2025.png"/>
</item>
<item>
<title>Bootstrap JavaScript Snippets</title>
<link>https://christianoliff.com/blog/bootstrap-javascript-snippets/</link>
<pubDate>Mon, 26 May 2025 02:41:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/bootstrap-javascript-snippets/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2025/header-bootstrap-javascript-snippets.png" alt=""/>&lt;/p>&lt;p&gt;When working on building websites with Bootstrap I often find myself copying and re-using a bunch of useful little JavaScript snippets to enhance functionality and I thought I&amp;rsquo;d make a quick blog post to share a few of my most used ones. They are all for Bootstrap 5, but could easily be adapted for earlier versions.&lt;/p&gt;
&lt;h2 id="open-modal-via-url-fragment" class="mt-5"&gt;Open Modal via URL Fragment
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#open-modal-via-url-fragment"
aria-label="Link to this section: Open Modal via URL Fragment"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;It can sometimes be useful to have a shareable URL which, automatically opens a modal on page load. e.g. &lt;a href="https://christianoliff.com/blog/bootstrap-javascript-snippets/#exampleModal" target="_blank" rel="noopener"&gt;Test&lt;/a&gt;. This can be achieved with this little script.&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;DOMContentLoaded&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;#exampleModal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modalElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;exampleModal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modalElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Modal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modalElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;modal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;show&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;script&gt;
document.addEventListener("DOMContentLoaded", function() {
if (window.location.hash === "#exampleModal") {
const modalElement = document.getElementById("exampleModal");
if (modalElement) {
const modal = new bootstrap.Modal(modalElement);
modal.show();
}
}
});
&lt;/script&gt;
&lt;h2 id="open-accordion-via-url-fragment" class="mt-5"&gt;Open Accordion via URL Fragment
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#open-accordion-via-url-fragment"
aria-label="Link to this section: Open Accordion via URL Fragment"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;It can sometimes be useful to have a shareable URL which, automatically opens an accordion section on page load, perhaps to show a specific section of content.&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;DOMContentLoaded&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buttonElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; .accordion-button&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buttonElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;buttonElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id="prevent-modal-from-playing-video-when-closed" class="mt-5"&gt;Prevent Modal from Playing Video When Closed
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#prevent-modal-from-playing-video-when-closed"
aria-label="Link to this section: Prevent Modal from Playing Video When Closed"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;If you have a modal with a video in it, you may want to prevent the video from continuing to play when the modal is closed. This can be done by resetting the &lt;code&gt;src&lt;/code&gt; attribute of the &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; when the modal is hidden.&lt;/p&gt;
&lt;p&gt;You can test this by clicking the button below which will open a modal with a YouTube video in it. When you close the modal, the video will stop playing.&lt;/p&gt;
&lt;!-- Button trigger modal --&gt;
&lt;button type="button" class="btn btn-primary btn-sm mb-3" data-bs-toggle="modal" data-bs-target="#exampleModal"&gt;
Launch demo modal
&lt;/button&gt;
&lt;!-- Modal --&gt;
&lt;div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"&gt;
&lt;div class="modal-dialog modal-dialog-centered"&gt;
&lt;div class="modal-content"&gt;
&lt;div class="modal-header border-0"&gt;
&lt;h1 class="modal-title fs-5" id="exampleModalLabel"&gt;Modal title&lt;/h1&gt;
&lt;button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"&gt;&lt;/button&gt;
&lt;/div&gt;
&lt;div class="modal-body" style="min-height: 300px;"&gt;
&lt;div class="ratio ratio-16x9" style="position: static !important;"&gt;
&lt;iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/ZC9Ko7mpNeY?si=mKtrmOGJhWvsbQh_&amp;amp;controls=0" class="w-100" aria-label="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" loading="lazy" referrerpolicy="strict-origin-when-cross-origin"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;DOMContentLoaded&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;hidden.bs.modal&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iframes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;iframe&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;iframes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;iframe&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentSrc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;iframe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;iframe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;iframe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentSrc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;script&gt;
document.addEventListener("DOMContentLoaded", function () {
document.addEventListener("hidden.bs.modal", function (event) {
const iframes = event.target.querySelectorAll("iframe");
iframes.forEach(function (iframe) {
const currentSrc = iframe.src;
iframe.src = "";
setTimeout(function() {
iframe.src = currentSrc;
}, 100);
});
});
});
&lt;/script&gt;
&lt;h2 id="dismiss-tooltips-on-escape" class="mt-5"&gt;Dismiss Tooltips on Escape
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#dismiss-tooltips-on-escape"
aria-label="Link to this section: Dismiss Tooltips on Escape"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;I hope this feature is added to Bootstrap itself (&lt;a href="https://github.com/twbs/bootstrap/issues/39692" target="_blank" rel="noopener"&gt;I opened an issue!&lt;/a&gt;) as it&amp;rsquo;s &lt;a href="https://www.w3.org/WAI/WCAG21/Understanding/content-on-hover-or-focus.html#:~:text=Provide%20a%20mechanism%20to%20easily%20dismiss%20the%20additional%20content%2C%20such%20as%20by%20pressing%20Escape" target="_blank" rel="noopener"&gt;needed for full WCAG21 compliance&lt;/a&gt;. You can test this by hovering over the share link button below this article which will display a tooltip and then pressing the &lt;kbd&gt;Esc&lt;/kbd&gt; key.&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;keyup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Escape&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tooltipTriggerList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;[data-bs-toggle=&amp;#34;tooltip&amp;#34;]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;tooltipTriggerList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tooltipTriggerEl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;tooltip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Tooltip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tooltipTriggerEl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tooltip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;tooltip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hide&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2025/header-bootstrap-javascript-snippets.png"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2025/header-bootstrap-javascript-snippets.png"/>
</item>
<item>
<title>Bootstrap switches with on-off labels</title>
<link>https://christianoliff.com/blog/on-off-labels-for-bootstrap-switches/</link>
<pubDate>Fri, 21 Feb 2025 06:03:00 +0000</pubDate>
<guid>https://christianoliff.com/blog/on-off-labels-for-bootstrap-switches/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2025/header-bootstrap-switch.png" alt=""/>&lt;/p>&lt;p&gt;Apple&amp;rsquo;s iOS, iPadOS and macOS all feature an accessibility option to add labels to switches. This can be helpful for users who may not be able to distinguish between the on and off states of a switch via color alone.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s easy to add this feature to Bootstrap switches using a little CSS. Here&amp;rsquo;s how you can do it.&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;form-switch&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;form-check-input&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="kt"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.4&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;form-switch&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;form-check-input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;⼁&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;form-switch&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;form-check-input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;checked&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#bfbfbf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;○&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;style&gt;
.form-switch .form-check-input::after {
font-size: 0.5rem;
position: absolute;
margin-top: 1.4px;
}
.form-switch .form-check-input:checked::after {
color: #fff;
content: "⼁";
margin-left: 5px;
}
.form-switch .form-check-input:not(:checked)::after {
color: #bfbfbf;
content: "○";
margin-left: 22px;
}
&lt;/style&gt;
&lt;h2 id="demo" class="mt-5"&gt;Demo
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#demo"
aria-label="Link to this section: Demo"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;div class="form-check form-switch mb-2"&gt;
&lt;input
class="form-check-input"
type="checkbox"
role="switch"
id="SwitchCheckDefaultSwitch"
switch
/&gt;
&lt;label class="form-check-label" for="SwitchCheckDefaultSwitch"
&gt;Default switch checkbox input&lt;/label
&gt;
&lt;/div&gt;
&lt;div class="form-check form-switch mb-2"&gt;
&lt;input
class="form-check-input"
type="checkbox"
role="switch"
id="SwitchCheckCheckedSwitch"
switch
checked
/&gt;
&lt;label class="form-check-label" for="SwitchCheckCheckedSwitch"
&gt;Checked switch checkbox input&lt;/label
&gt;
&lt;/div&gt;
&lt;div class="form-check form-switch mb-2"&gt;
&lt;input
class="form-check-input"
type="checkbox"
role="switch"
id="SwitchCheckDisabledSwitch"
switch
disabled
/&gt;
&lt;label class="form-check-label" for="SwitchCheckDisabledSwitch"
&gt;Disabled switch checkbox input&lt;/label
&gt;
&lt;/div&gt;
&lt;div class="form-check form-switch mb-2"&gt;
&lt;input
class="form-check-input"
type="checkbox"
role="switch"
id="SwitchCheckCheckedDisabledSwitch"
switch
checked
disabled
/&gt;
&lt;label class="form-check-label" for="SwitchCheckCheckedDisabledSwitch"
&gt;Disabled checked switch checkbox input&lt;/label&gt;
&lt;/div&gt;
&lt;h2 id="codepen-demo" class="mt-5"&gt;Codepen Demo
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#codepen-demo"
aria-label="Link to this section: Codepen Demo"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;You can also view the &lt;a href="https://stackblitz.com/edit/bootstrap-switch-on-off-label" target="_blank" rel="noopener"&gt;demo on Stackblitz&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="notes-and-observations" class="mt-5"&gt;Notes and Observations
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#notes-and-observations"
aria-label="Link to this section: Notes and Observations"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;The CSS above works in both light and dark mode.&lt;/li&gt;
&lt;li&gt;I add the &lt;a href="https://webkit.org/blog/15054/an-html-switch-control/" target="_blank" rel="noopener"&gt;&lt;code&gt;switch&lt;/code&gt;&lt;/a&gt; attribute to the input element to give the switches haptic feedback on iPhones.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;::after&lt;/code&gt; pseudo-element is used to add the labels.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;content&lt;/code&gt; property is used to add the labels.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;margin-left&lt;/code&gt; and &lt;code&gt;margin-top&lt;/code&gt; properties are used to position the labels.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;font-size&lt;/code&gt; and &lt;code&gt;color&lt;/code&gt; properties are used to style the labels.&lt;/li&gt;
&lt;/ul&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2025/header-bootstrap-switch.png"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2025/header-bootstrap-switch.png"/>
</item>
<item>
<title>Using Safari's native switch input with Bootstrap</title>
<link>https://christianoliff.com/blog/using-safaris-native-switch-with-bootstrap/</link>
<pubDate>Wed, 12 Feb 2025 00:01:39 +0000</pubDate>
<guid>https://christianoliff.com/blog/using-safaris-native-switch-with-bootstrap/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2025/header-bootstrap-switch.png" alt=""/>&lt;/p>&lt;p&gt;Safari introduced a native &lt;a href="https://webkit.org/blog/15054/an-html-switch-control/" target="_blank" rel="noopener"&gt;HTML switch element in version 17.4&lt;/a&gt; which is easy to use just by adding the &lt;code&gt;switch&lt;/code&gt; attribute to a checkbox input.&lt;/p&gt;
&lt;p&gt;This is a great feature that allows developers to create a switch without the need for JavaScript or CSS and I hope that other browsers adopt this too. For now you can use a native switch in Safari with fallback styling for other browsers using Bootstrap.&lt;/p&gt;
&lt;h2 id="css" class="mt-5"&gt;CSS
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#css"
aria-label="Link to this section: CSS"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;This &lt;code&gt;@supports&lt;/code&gt; selector is used to target Safari 17.4 and later. It will turn off some of Bootstrap&amp;rsquo;s custom switch styles and use the native switch styles in Safari. If you want to use Bootstrap&amp;rsquo;s custom switch styles in Safari you can simply omit the CSS below.&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;supports&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;-webkit-hyphens&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;none&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;and&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;word-spacing&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;1&lt;/span&gt;&lt;span class="o"&gt;%)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;form-switch&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;form-check-input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;checkbox&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;][&lt;/span&gt;&lt;span class="nt"&gt;switch&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;accent-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#0d6efd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;/* Sets the accent color of the switch to same color as what Bootstrap uses */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;/* Removes the background color used by Bootstrap&amp;#39;s custom switch */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;/* Removes the background image used by Bootstrap&amp;#39;s custom switch */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;/* Removes the border used by Bootstrap&amp;#39;s custom switch */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;/* Prevent the disabled state from having additional opacity applied */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kp"&gt;-webkit-&lt;/span&gt;&lt;span class="k"&gt;appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;/* Resets the appearance to auto. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;/* There&amp;#39;s no need to define the prefix-less version since this is Safari-only */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;style&gt;
@supports (-webkit-hyphens: none) and (word-spacing: 1%) {
.form-switch .form-check-input[type="checkbox"][switch] {
accent-color: #0d6efd;
background-color: transparent;
background-image: none;
border: 0;
opacity: inherit;
-webkit-appearance: auto;
}
.alert-info {
display: none !important;
}
}
main ul li {
margin-bottom: 0.5rem;
}
main code.small {
font-size: 0.9rem;
}
main small {
opacity: 0.75;
letter-spacing: -13px;
}
main span.c {
opacity: 0.5;
letter-spacing: -0.2px;
}
&lt;/style&gt;
&lt;h2 id="with-switch-attribute" class="mt-5"&gt;With &lt;code&gt;switch&lt;/code&gt; attribute
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#with-switch-attribute"
aria-label="Link to this section: With switch attribute"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;div class="alert alert-info" role="alert"&gt;
&lt;p class="mb-0" style="margin-bottom: 0;"&gt;
The &lt;code&gt;switch&lt;/code&gt; attribute is not supported on your browser so the examples below will show the fallback styles provided by Bootstrap. To test you must use Safari 17.4 or later.
&lt;/p&gt;
&lt;/div&gt;
&lt;div class="form-check form-switch mb-2"&gt;
&lt;input
class="form-check-input"
type="checkbox"
role="switch"
id="SwitchCheckDefaultSwitch"
switch
/&gt;
&lt;label class="form-check-label" for="SwitchCheckDefaultSwitch"
&gt;Default switch checkbox input &lt;code class="d-block small opacity-75 ms-1"&gt;&amp;lt;input type='checkbox' class='form-check-label' switch&amp;gt;&lt;/code&gt;&lt;/label
&gt;
&lt;/div&gt;
&lt;div class="form-check form-switch mb-2"&gt;
&lt;input
class="form-check-input"
type="checkbox"
role="switch"
id="SwitchCheckCheckedSwitch"
switch
checked
/&gt;
&lt;label class="form-check-label" for="SwitchCheckCheckedSwitch"
&gt;Checked switch checkbox input &lt;code class="d-block small opacity-75 ms-1"&gt;&amp;lt;input type='checkbox' class='form-check-label' switch checked&amp;gt;&lt;/code&gt;&lt;/label
&gt;
&lt;/div&gt;
&lt;div class="form-check form-switch mb-2"&gt;
&lt;input
class="form-check-input"
type="checkbox"
role="switch"
id="SwitchCheckDisabledSwitch"
switch
disabled
/&gt;
&lt;label class="form-check-label" for="SwitchCheckDisabledSwitch"
&gt;Disabled switch checkbox input &lt;/label
&gt;&lt;code class="d-block small opacity-75 ms-1"&gt;&amp;lt;input type='checkbox' class='form-check-label' switch disabled&amp;gt;&lt;/code&gt;
&lt;/div&gt;
&lt;div class="form-check form-switch mb-2"&gt;
&lt;input
class="form-check-input"
type="checkbox"
role="switch"
id="SwitchCheckCheckedDisabledSwitch"
switch
checked
disabled
/&gt;
&lt;label class="form-check-label" for="SwitchCheckCheckedDisabledSwitch"
&gt;Disabled checked switch checkbox input &lt;/label
&gt;&lt;code class="d-block small opacity-75 ms-1"&gt;&amp;lt;input type='checkbox' class='form-check-label' switch disabled checked&amp;gt;&lt;/code&gt;
&lt;/div&gt;
&lt;h2 id="without-switch-attribute" class="mt-5"&gt;Without &lt;code&gt;switch&lt;/code&gt; attribute
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#without-switch-attribute"
aria-label="Link to this section: Without switch attribute"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Examples showing Bootstrap&amp;rsquo;s switch styles without the &lt;code&gt;switch&lt;/code&gt; attribute.&lt;/p&gt;
&lt;div class="form-check form-switch mb-2"&gt;
&lt;input
class="form-check-input"
type="checkbox"
role="switch"
id="SwitchCheckDefault"
/&gt;
&lt;label class="form-check-label" for="SwitchCheckDefault"
&gt;Default switch checkbox input &lt;/label
&gt;&lt;code class="d-block small opacity-75"&gt;&amp;lt;input type='checkbox' class='form-check-label'&amp;gt;&lt;/code&gt;
&lt;/div&gt;
&lt;div class="form-check form-switch mb-2"&gt;
&lt;input
class="form-check-input"
type="checkbox"
role="switch"
id="SwitchCheckChecked"
checked
/&gt;
&lt;label class="form-check-label" for="SwitchCheckChecked"
&gt;Checked switch checkbox input &lt;/label
&gt;&lt;code class="d-block small opacity-75"&gt;&amp;lt;input type='checkbox' class='form-check-label' checked&amp;gt;&lt;/code&gt;
&lt;/div&gt;
&lt;div class="form-check form-switch mb-2"&gt;
&lt;input
class="form-check-input"
type="checkbox"
role="switch"
id="SwitchCheckDisabled"
disabled
/&gt;
&lt;label class="form-check-label" for="SwitchCheckDisabled"
&gt;Disabled switch checkbox input &lt;/label
&gt;&lt;code class="d-block small opacity-75"&gt;&amp;lt;input type='checkbox' class='form-check-label' disabled&amp;gt;&lt;/code&gt;
&lt;/div&gt;
&lt;div class="form-check form-switch mb-2"&gt;
&lt;input
class="form-check-input"
type="checkbox"
role="switch"
id="SwitchCheckCheckedDisabled"
checked
disabled
/&gt;
&lt;label class="form-check-label" for="SwitchCheckCheckedDisabled"
&gt;Disabled checked switch checkbox input &lt;/label
&gt;&lt;code class="d-block small opacity-75"&gt;&amp;lt;input type='checkbox' class='form-check-label' disabled checked&amp;gt;&lt;/code&gt;
&lt;/div&gt;
&lt;h2 id="codepen-demo" class="mt-5"&gt;Codepen Demo
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#codepen-demo"
aria-label="Link to this section: Codepen Demo"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;You can also view the &lt;a href="https://codepen.io/coliff/pen/raNNaEq" target="_blank" rel="noopener"&gt;demo on Codepen&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="notes-and-observations" class="mt-5"&gt;Notes and Observations
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#notes-and-observations"
aria-label="Link to this section: Notes and Observations"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;accent-color&lt;/code&gt; property can be used to change the color of the switch in Safari. By default it appears green on macOS and blue on iOS. In my example I set it to the same color as what Bootstrap uses for the switch for consistency.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;role=&amp;quot;switch&amp;quot;&lt;/code&gt; attribute is used to indicate that the input is a switch. This is not necessary but it is a good practice to use it. On Safari it is not necessary to use it if the input has the &lt;code&gt;switch&lt;/code&gt; attribute.&lt;/li&gt;
&lt;li&gt;On Safari macOS the native switch appears pixelated when zoomed in. On iOS and iPadOS it appears fine.&lt;/li&gt;
&lt;li&gt;In the future you&amp;rsquo;ll be able to style the thumb and range (using the &lt;code&gt;::thumb&lt;/code&gt; and &lt;code&gt;::track&lt;/code&gt; selectors) of the switch which allows you to style the switch more than just changing the color. I didn&amp;rsquo;t go into that in this article but you can read more about it in the &lt;a href="https://webkit.org/blog/15054/an-html-switch-control/" target="_blank" rel="noopener"&gt;WebKit blog post&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Using Safari&amp;rsquo;s native switch has the advantage of being optimized for the &amp;lsquo;prefers contrast&amp;rsquo; setting (which uses a darker color for the off state) in iOS and macOS and also for the &amp;lsquo;Differentiate without color&amp;rsquo; setting (which adds on and off glyphs).&lt;/li&gt;
&lt;li&gt;Using Safari&amp;rsquo;s native switch gives haptic feedback when toggling the switch on iOS. For that reason, even if you don&amp;rsquo;t want to use Safari&amp;rsquo;s native switch styling you can use the &lt;code&gt;switch&lt;/code&gt; attribute and don&amp;rsquo;t use the custom CSS above so it uses Bootstrap styling but still gets the haptic feedback as a progressive enhamcement.&lt;/li&gt;
&lt;/ul&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2025/header-bootstrap-switch.png"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2025/header-bootstrap-switch.png"/>
</item>
<item>
<title>Bootstrap Forced Colors CSS for Windows High Contrast Themes</title>
<link>https://christianoliff.com/blog/bootstrap-forced-colors-css/</link>
<pubDate>Fri, 05 Jul 2024 00:11:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/bootstrap-forced-colors-css/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2024/header-bootstrap-forced-colors.png" alt=""/>&lt;/p>&lt;p&gt;Windows has supported High Contrast Themes in Windows since Windows 10. These customizable themes can be useful for users with visual impairments or for users who prefer high contrast colors. When a Contrast theme is activated is enables the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/forced-colors" target="_blank" rel="noopener"&gt;forced-colors media query&lt;/a&gt; in browsers (at the time of writing, Edge, Chrome and Firefox).&lt;/p&gt;
&lt;p&gt;Unfortunately, forced colors mode can cause issues with websites that are not designed to work with high contrast colors. Using Bootstrap v5 has a number of issues with missing borders and elements (This &lt;a href="https://github.com/twbs/bootstrap/issues/35941#issuecomment-1200029297" target="_blank" rel="noopener"&gt;GitHub issue&lt;/a&gt; covers some of them) so I&amp;rsquo;ve created a stylesheet by using the &lt;code&gt;forced-colors: active&lt;/code&gt; media query which you can simply add to your site to &amp;lsquo;auto-fix&amp;rsquo; everything and adds enhancements to make Bootstrap 5 much more accessible in Firefox, Chrome, Edge on Windows.&lt;/p&gt;
&lt;h2 id="quick-start" class="mt-5"&gt;Quick start
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#quick-start"
aria-label="Link to this section: Quick start"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Download the &lt;a href="https://github.com/coliff/bootstrap-forced-colors-css/releases/latest" target="_blank" rel="noopener"&gt;latest release&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Clone the repository &lt;code&gt;git clone https://github.com/coliff/bootstrap-forced-colors-css.git&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Install with &lt;a href="https://www.npmjs.com/package/bootstrap-forced-colors-css" target="_blank" rel="noopener"&gt;npm&lt;/a&gt; &lt;code&gt;npm install bootstrap-forced-colors-css&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Install with &lt;a href="https://classic.yarnpkg.com/en/package/bootstrap-forced-colors-css" target="_blank" rel="noopener"&gt;yarn&lt;/a&gt; &lt;code&gt;yarn add bootstrap-forced-colors-css&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Install with &lt;a href="https://packagist.org/packages/coliff/bootstrap-forced-colors-css" target="_blank" rel="noopener"&gt;Composer&lt;/a&gt; &lt;code&gt;composer require coliff/bootstrap-forced-colors-css&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="usage" class="mt-5"&gt;Usage
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#usage"
aria-label="Link to this section: Usage"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Add this in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; which will load the CSS using a media query as follow:&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/css/bootstrap-forced-colors.min.css&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;media&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;screen and (forced-colors: active)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The CSS can be loaded via a CDN:&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://cdn.jsdelivr.net/npm/bootstrap-forced-colors-css/css/bootstrap-forced-colors.min.css&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;media&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;screen and (forced-colors: active)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Or you can import the CSS into your own CSS file:&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-scss" data-lang="scss"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="n"&gt;bootstrap-forced-colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;css&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id="faqs" class="mt-5"&gt;FAQS
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#faqs"
aria-label="Link to this section: FAQS"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;h3 id="what-does-this-fiximprove" class="mt-5"&gt;What does this fix/improve?
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#what-does-this-fiximprove"
aria-label="Link to this section: What does this fix/improve?"&gt;&lt;/a&gt;
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#accordion" target="_blank" rel="noopener"&gt;Accordion&lt;/a&gt; buttons have improved contrast in dark mode&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#badge" target="_blank" rel="noopener"&gt;Badges&lt;/a&gt; within buttons have a 1px border to improve contrast&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#buttons" target="_blank" rel="noopener"&gt;Buttons&lt;/a&gt; have improved focus state contrast (2px visible outline rather than 1px)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#buttons" target="_blank" rel="noopener"&gt;Disabled buttons&lt;/a&gt; display the correct color using the &lt;code&gt;GrayText&lt;/code&gt; name&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#carousel" target="_blank" rel="noopener"&gt;Carousel&lt;/a&gt; indicators have background-color issue resolved&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#toasts" target="_blank" rel="noopener"&gt;Close button&lt;/a&gt; has improved contrast by reducing the opacity&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#dropdowns" target="_blank" rel="noopener"&gt;Dropdown&lt;/a&gt; toggle arrows appear correctly (as triangles and not rectangles)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#list-group" target="_blank" rel="noopener"&gt;List Group&lt;/a&gt; disabled items display the correct color using the &lt;code&gt;GrayText&lt;/code&gt; name&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#modal" target="_blank" rel="noopener"&gt;Modal&lt;/a&gt; backdrop opacity changed from 0.5 to 0.8&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#navbar" target="_blank" rel="noopener"&gt;Navbar&lt;/a&gt; Menu (hamburger) toggle icons display correctly&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#navs" target="_blank" rel="noopener"&gt;Navs&lt;/a&gt; Improves active and focus state contrast&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#pagination" target="_blank" rel="noopener"&gt;Pagination&lt;/a&gt;: Active page link has outline to indicate active page&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#pagination" target="_blank" rel="noopener"&gt;Pagination&lt;/a&gt;: Disabled page link display the correct color using the &lt;code&gt;GrayText&lt;/code&gt; name&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#placeholder" target="_blank" rel="noopener"&gt;Placeholder&lt;/a&gt;: Fix for invisible placeholder boxes&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#popovers" target="_blank" rel="noopener"&gt;Popovers&lt;/a&gt;: Fixes invisible arrow issue&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#progress" target="_blank" rel="noopener"&gt;Progress&lt;/a&gt;: Is no longer invisible&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#progress" target="_blank" rel="noopener"&gt;Progress&lt;/a&gt;: Improved stacked progress bar contrast&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#spinners" target="_blank" rel="noopener"&gt;Spinners&lt;/a&gt;: Fixes animation&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#tables" target="_blank" rel="noopener"&gt;Tables&lt;/a&gt;: Have a 1px outline to improve contrast&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#toasts" target="_blank" rel="noopener"&gt;Toasts&lt;/a&gt;: Fixes invisible close/dismiss button&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#tooltips" target="_blank" rel="noopener"&gt;Tooltips&lt;/a&gt;: Fix for arrows appearing as rectangles&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#tooltips" target="_blank" rel="noopener"&gt;Tooltips&lt;/a&gt;: Add 1px border to tooltips content&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#navbar" target="_blank" rel="noopener"&gt;Vertical Rule&lt;/a&gt;: Fixes invisible vertical rule&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/#navbar" target="_blank" rel="noopener"&gt;Horizontal Rule&lt;/a&gt;: Improves contrast by changing opacity from 0.25 to 0.5&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="demo" class="mt-5"&gt;Demo
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#demo"
aria-label="Link to this section: Demo"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;See this in action at: &lt;a href="https://coliff.github.io/bootstrap-forced-colors-css/tests/" target="_blank" rel="noopener"&gt;https://coliff.github.io/bootstrap-forced-colors-css/tests/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="testing" class="mt-5"&gt;Testing
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#testing"
aria-label="Link to this section: Testing"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Currently, only Windows 10 &amp;amp; 11 with Edge, Firefox, and Chrome support forced colors mode. To test, you can enable forced colors mode in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Windows 10: Go to &lt;code&gt;Settings &amp;gt; Ease of Access &amp;gt; High contrast&lt;/code&gt; and select a theme.&lt;/li&gt;
&lt;/ul&gt;
&lt;details&gt;
&lt;summary&gt;Windows 11: Go to &lt;code&gt;Settings &gt; Accessibility &gt; Contrast themes&lt;/code&gt; and select a theme&lt;/summary&gt;
&lt;p&gt;
&lt;img src="https://christianoliff.com/img/2024/windows-11-contrast-theme.png" alt="Windows 11 Contrast Theme Select screen" decoding="async" loading="lazy"
width=1132 height="755"
&gt;
&lt;/p&gt;
&lt;/details&gt;&lt;br&gt;
&lt;p&gt;You can also use the &lt;a href="https://developer.chrome.com/docs/devtools/rendering/emulate-css#emulate_css_media_feature_forced-colors" target="_blank" rel="noopener"&gt;Forced Colors Mode Emulation&lt;/a&gt; in Edge and Chrome on all platforms.&lt;/p&gt;
&lt;div class="d-block w-100"&gt;
&lt;div
class="alert alert-info opacity-75 text-white "
role="alert" style="border-left-width: 0.5rem;"&gt;
Note: Forced Colors Mode emulation supports emulating light and dark themes by toggling the &lt;code&gt;prefers-color-scheme&lt;/code&gt; between light and dark in the Dev Tools. Switching Bootstrap&amp;rsquo;s light/dark mode theme toggle will have no noticeable effect. &lt;strong&gt;The color scheme is set by the user at the OS level&lt;/strong&gt;.&lt;br&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note that &lt;a href="https://caniuse.com/mdn-css_at-rules_media_forced-colors" target="_blank" rel="noopener"&gt;CanIUse lists Safari as supporting forced colors mode&lt;/a&gt;, however, macOS itself doesn&amp;rsquo;t have a Forced Colors / High Contrast mode which means it&amp;rsquo;s not possible to test this with Safari at all.&lt;/p&gt;
&lt;h3 id="interesting-links-about-windows-high-contrast-mode" class="mt-5"&gt;Interesting links about Windows High Contrast Mode
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#interesting-links-about-windows-high-contrast-mode"
aria-label="Link to this section: Interesting links about Windows High Contrast Mode"&gt;&lt;/a&gt;
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.smashingmagazine.com/2022/03/windows-high-contrast-colors-mode-css-custom-properties/" target="_blank" rel="noopener"&gt;Smashing Magazine article&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://caniuse.com/mdn-css_at-rules_media_forced-colors" target="_blank" rel="noopener"&gt;CanIUse Support&lt;/a&gt; (Only Windows supports forced colors mode)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://adrianroselli.com/2021/02/whcm-and-system-colors.html" target="_blank" rel="noopener"&gt;WHCM and System Colors&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;style&gt;
main article img {
max-width: 740px;
}
&lt;/style&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2024/header-bootstrap-forced-colors.png"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2024/header-bootstrap-forced-colors.png"/>
</item>
<item>
<title>Building a Bootstrap Dropdown with the details HTML disclosure element</title>
<link>https://christianoliff.com/blog/bootstrap-dropdown-with-details-summary/</link>
<pubDate>Wed, 10 Apr 2024 00:00:00 +0000</pubDate>
<guid>https://christianoliff.com/blog/bootstrap-dropdown-with-details-summary/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2024/header-bootstrap-5-dropdown.jpg" alt=""/>&lt;/p>&lt;p&gt;Following on from &lt;a href="https://christianoliff.com/blog/building-a-bootstrap-accordion-with-the-details/summary-html-tags/" &gt;building a Bootstrap accordion&lt;/a&gt; using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details" target="_blank" rel="noopener"&gt;&lt;code&gt;details&lt;/code&gt;&lt;/a&gt; HTML tag, I thought I&amp;rsquo;d try to build a Bootstrap dropdown using the same &lt;code&gt;details&lt;/code&gt; HTML tag.&lt;/p&gt;
&lt;details class="dropdown mb-5"&gt;
&lt;summary class="btn btn-primary dropdown-toggle"&gt;
Open dropdown
&lt;/summary&gt;
&lt;div&gt;
&lt;ul class="dropdown-menu" style="display: revert;"&gt;
&lt;li&gt;&lt;a class="dropdown-item" href="#"&gt;Action&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="dropdown-item" href="#"&gt;Another action&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="dropdown-item" href="#"&gt;Something else here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;h2 id="html" class="mt-5"&gt;HTML
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#html"
aria-label="Link to this section: HTML"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;dropdown mb-5&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;btn btn-primary dropdown-toggle&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Open dropdown
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;dropdown-menu&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;display: revert;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;dropdown-item&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;#&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Action&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;dropdown-item&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;#&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Another action&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;dropdown-item&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;#&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Something else here&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Overall it was easy and quick to get together but it unfortunately brings with it a few minor usability issues.&lt;/p&gt;
&lt;p&gt;Unlike a &lt;a href="https://getbootstrap.com/docs/5.3/components/dropdowns/#single-button" target="_blank" rel="noopener"&gt;standard Bootstrap downdown&lt;/a&gt; component, clicking outside of the dropdown won&amp;rsquo;t collapse the dropdown and the &lt;kbd&gt;Esc&lt;/kbd&gt; key won&amp;rsquo;t collapse it either. Having said that, a standard details/summary element won&amp;rsquo;t do either of those anyway and the collapse dropdown can still be controlled with a keyboard using the &lt;kbd&gt;Enter&lt;/kbd&gt; or &lt;kbd&gt;Space&lt;/kbd&gt; key.&lt;/p&gt;
&lt;script&gt;
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape') {
let detailsElements = document.querySelectorAll('details[open]');
detailsElements.forEach((details) =&gt; {
details.removeAttribute('open');
});
}
});
&lt;/script&gt;
&lt;h2 id="javascript-optional" class="mt-5"&gt;JavaScript (Optional)
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#javascript-optional"
aria-label="Link to this section: JavaScript (Optional)"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;You could add a tiny script to close the menu when the &lt;kbd&gt;Esc&lt;/kbd&gt; key is pressed:&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;keydown&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Escape&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;detailsElements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;details[open]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;detailsElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;open&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;/script&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id="accessibility" class="mt-5"&gt;Accessibility
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#accessibility"
aria-label="Link to this section: Accessibility"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;The dropdown is fully accessible and can be controlled with a keyboard. The dropdown can be opened and closed with the &lt;kbd&gt;Enter&lt;/kbd&gt; or &lt;kbd&gt;Space&lt;/kbd&gt; key and the dropdown items can be navigated with the &lt;kbd&gt;tab&lt;/kbd&gt; key. It is announced as a dropdown by screen readers and the dropdown items are announced as a list.&lt;/p&gt;
&lt;h2 id="summary" class="mt-5"&gt;Summary
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#summary"
aria-label="Link to this section: Summary"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;I thought this was an intertesting experiment and I hope you find it useful. It&amp;rsquo;s neat how much you can achieve with just HTML and CSS!&lt;/p&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2024/header-bootstrap-5-dropdown.jpg"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2024/header-bootstrap-5-dropdown.jpg"/>
</item>
<item>
<title>Bootstrap 5 Migrate Tool</title>
<link>https://christianoliff.com/blog/bootstrap-5-migrate-tool/</link>
<pubDate>Mon, 25 Mar 2024 01:21:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/bootstrap-5-migrate-tool/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2024/header-bootstrap-5-migrate-tool.jpg" alt=""/>&lt;/p>&lt;p&gt;Migrating a website project from Bootstrap 4 to Bootstrap 5 involves renaming a lot of classes which can be a tedious task. To help with this, I created a command-line tool that will do all the renaming for you across all pages in your project. It&amp;rsquo;s a comprehensive script which not only renames all the relevant classes, but also updates any deprecated elements and attributes to relevant classes and more.&lt;/p&gt;
&lt;h2 id="features" class="mt-5"&gt;Features
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#features"
aria-label="Link to this section: Features"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Replaces all Bootstrap 4 class names with the renamed Bootstrap 5 class names&lt;/li&gt;
&lt;li&gt;Replaces deprecated components (such as &lt;code&gt;.jumbotron&lt;/code&gt; and &lt;code&gt;.media&lt;/code&gt;) with utility classes&lt;/li&gt;
&lt;li&gt;Renames all the data attributes (such as &lt;code&gt;data-toggle&lt;/code&gt; and &lt;code&gt;data-target&lt;/code&gt;) to the new names&lt;/li&gt;
&lt;li&gt;Updates all Bootstrap v4 CDN links (cloudflare.com, jsdelivr.net, stackpath.bootstrapcdn.com and unpkg.com) to latest version of Bootstrap v5&lt;/li&gt;
&lt;li&gt;Options to overwrite the existing files in place or save the migrated files to a different folder&lt;/li&gt;
&lt;li&gt;Can convert not only HTML files but also ASP, CSHTML, EJS, ERB, HBS, JSP, PHP, VUE, and other template files&lt;/li&gt;
&lt;li&gt;Provides a summary of the changes made&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="how-to-use-the-tool" class="mt-5"&gt;How to use the tool
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#how-to-use-the-tool"
aria-label="Link to this section: How to use the tool"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Clone the repo and then run the following command:&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Copy your HTML templates to the &lt;code&gt;src&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;Then run the following command to start the migration:&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npx gulp migrate&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The migrated HTML templates will overwrite the files in place by default. If you want to keep the original files, you can use the &lt;code&gt;--dest&lt;/code&gt; flag to specify a destination folder. See the &lt;a href="#options" &gt;Options&lt;/a&gt; section for more details.&lt;/p&gt;
&lt;p&gt;Read the official Bootstrap 5 migration guide here: &lt;a href="https://getbootstrap.com/docs/5.3/migration/" target="_blank" rel="noopener"&gt;https://getbootstrap.com/docs/5.3/migration/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="options" class="mt-5"&gt;Options
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#options"
aria-label="Link to this section: Options"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Options that may be set via CLI flags.
For example: &lt;code&gt;npx gulp migrate --src &amp;quot;./src-dir&amp;quot; --overwrite --verbose&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src: './src'&lt;/code&gt; - string that will be passed to the gulp {@link src} function&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dest: ./&lt;/code&gt;- string that will be passed to the gulp {@link dest} function&lt;/li&gt;
&lt;li&gt;&lt;code&gt;overwrite: true&lt;/code&gt; - overwrite the existing files in place. &lt;strong&gt;Cannot be used with &amp;ndash;dest flag&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;verbose: true&lt;/code&gt;- print the path of each generated / modified file to the console&lt;/li&gt;
&lt;li&gt;&lt;code&gt;defaultFileGlob: '**/*.{asp,aspx,cshtml,ejs,erb,hbs,html,htm,jsp,php,twig,vue}'&lt;/code&gt; - default glob for files to search in. Default: Search all folder and files recursively&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="demo" class="mt-5"&gt;Demo
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#demo"
aria-label="Link to this section: Demo"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Input (created using Bootstrap 4):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-5-migrate-tool/src/index.html" target="_blank" rel="noopener"&gt;Bootstrap 4 HTML template&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And here&amp;rsquo;s the same page after running the migration tool:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/bootstrap-5-migrate-tool/dest/src/index.html" target="_blank" rel="noopener"&gt;Bootstrap 5 HTML template&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="contribute" class="mt-5"&gt;Contribute
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#contribute"
aria-label="Link to this section: Contribute"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;This tool is open-source and available on GitHub: &lt;a href="https://github.com/coliff/bootstrap-5-migrate-tool" target="_blank" rel="noopener"&gt;Bootstrap 5 Migrate Tool&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Contributions are welcome! If you find any issues or have suggestions for improvements, please open an issue or a pull request.&lt;/p&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2024/header-bootstrap-5-migrate-tool.jpg"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2024/header-bootstrap-5-migrate-tool.jpg"/>
</item>
<item>
<title>Markdown Render Hooks in Hugo</title>
<link>https://christianoliff.com/blog/markdown-render-hooks-in-hugo/</link>
<pubDate>Thu, 21 Sep 2023 02:04:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/markdown-render-hooks-in-hugo/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2023/markdown-render-hooks-in-hugo.jpg" alt=""/>&lt;/p>&lt;p&gt;Hugos&amp;rsquo;s Markdown Render Hooks allow custom templates to override Markdown rendering functionality. Render hooks are easy to setup and use and can make your site more useful and allow your Markdown content files to be simpler by passing on functionality to the render hooks rather than relying on custom code in your Markdown files.&lt;/p&gt;
&lt;p&gt;The hook kinds currently supported are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;heading&lt;/li&gt;
&lt;li&gt;image&lt;/li&gt;
&lt;li&gt;link&lt;/li&gt;
&lt;li&gt;codeblock&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="headings" class="mt-5"&gt;Headings
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#headings"
aria-label="Link to this section: Headings"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;If your site has many subheadings then it&amp;rsquo;s useful to be able to add an anchor link to each heading so that users can easily link to a specific heading, like I have done on this site. This can be setup with a custom template for the &lt;code&gt;heading&lt;/code&gt; hook kind.&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h&lt;/span&gt;&lt;span class="err"&gt;{{&lt;/span&gt; &lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Level&lt;/span&gt; &lt;span class="err"&gt;}}&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{{ .Anchor | safeURL }}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;{{ .Text | safeHTML }}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;header-link&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;#{{ .Anchor | safeURL }}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;aria-label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Link to this section: {{ with .Text}}{{ . }}{{ end }}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;/h{{ .Level }}&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This will add an anchor link to each heading that links to the heading&amp;rsquo;s anchor. The Aria label is also set to the heading&amp;rsquo;s text.&lt;/p&gt;
&lt;h2 id="links" class="mt-5"&gt;Links
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#links"
aria-label="Link to this section: Links"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;!-- Hugo converts Markdown to HTML using the Goldmark Markdown renderer which is fast, accurate, and well-maintained. It adheres to the CommonMark specification, and consistently follows a well-defined set of rules. --&gt;
&lt;p&gt;A Markdown link has three components: link text, a link destination, and optionally a link title.&lt;/p&gt;
&lt;p&gt;Most sites have links and it&amp;rsquo;s a common practise to have external links open in a new tab. By using the Markdown render hook template below all links beginning with &lt;code&gt;http&lt;/code&gt; will automatically have the &lt;code&gt;target=&amp;quot;_blank&amp;quot;&lt;/code&gt; attribute. You could add an external link icon within this block if you wanted.&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{{ .Destination | safeURL }}&amp;#34;&lt;/span&gt; &lt;span class="err"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;with&lt;/span&gt; &lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Title&lt;/span&gt;&lt;span class="err"&gt;}}&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{{- . -}}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;}}{{&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt; &lt;span class="na"&gt;strings&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HasPrefix&lt;/span&gt; &lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Destination&lt;/span&gt; &lt;span class="err"&gt;&amp;#34;&lt;/span&gt;&lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="err"&gt;&amp;#34;&lt;/span&gt; &lt;span class="err"&gt;}}&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;_blank&amp;#34;&lt;/span&gt; &lt;span class="err"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;}}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {{- .Text | safeHTML -}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;One quick note: I sometimes see users add &lt;code&gt;rel=&amp;quot;noreferrer&amp;quot;&lt;/code&gt; to external links that they control, I don&amp;rsquo;t recommend that as it can make analytics data less accurate. Also, it used to be advised to add &lt;code&gt;rel=&amp;quot;noopener&amp;quot;&lt;/code&gt; to external links but the security issue for this was fixed in all major browsers years ago so this is no longer necessary.&lt;/p&gt;
&lt;h2 id="images" class="mt-5"&gt;Images
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#images"
aria-label="Link to this section: Images"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;This is perhaps the most useful render hook of all. By default, rendering an image in Markdown via Hugo will not set the size or add any classes so large images can appear wider than the viewport.&lt;/p&gt;
&lt;p&gt;With this render hook images have their height and width added (if the images are in the static directory) and lazy loading parameters added.&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{{ .Destination | safeURL }}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{{- .Text -}}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;with&lt;/span&gt; &lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Title&lt;/span&gt; &lt;span class="err"&gt;}}&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{{- . -}}&amp;#34;&lt;/span&gt; &lt;span class="err"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt; &lt;span class="na"&gt;strings&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HasPrefix&lt;/span&gt; &lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Destination&lt;/span&gt; &lt;span class="err"&gt;&amp;#34;&lt;/span&gt;&lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="err"&gt;&amp;#34;&lt;/span&gt; &lt;span class="err"&gt;}}&lt;/span&gt; &lt;span class="err"&gt;{{&lt;/span&gt;&lt;span class="na"&gt;else&lt;/span&gt;&lt;span class="err"&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;with&lt;/span&gt; &lt;span class="na"&gt;imageConfig&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt; &lt;span class="na"&gt;printf&lt;/span&gt; &lt;span class="err"&gt;&amp;#34;&lt;/span&gt;&lt;span class="na"&gt;static&lt;/span&gt;&lt;span class="err"&gt;/%&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="err"&gt;&amp;#34;&lt;/span&gt; &lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Destination&lt;/span&gt; &lt;span class="err"&gt;)&lt;/span&gt; &lt;span class="err"&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt; &lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Width&lt;/span&gt; &lt;span class="err"&gt;}}&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{{ .Height }}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;decoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;async&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;lazy&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id="code-blocks" class="mt-5"&gt;Code Blocks
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#code-blocks"
aria-label="Link to this section: Code Blocks"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Codeblocks are the latest addition to Hugo&amp;rsquo;s render hook capabilities and were introduced with Hugo v0.93.0. Codeblocks are a little different to the other hooks as they are available as single template (&lt;code&gt;render-codeblock.html&lt;/code&gt;) but also as templates selected based on the language of the code block (e.g. &lt;code&gt;render-codeblock-html.html&lt;/code&gt; or &lt;code&gt;render-codeblock-python.html&lt;/code&gt;).&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ```html {class=&amp;#34;html-code&amp;#34; id=&amp;#34;my-codeblock&amp;#34; lineNos=inline tabWidth=4}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;button&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;btn&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello, world!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ```&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;A fenced code block consists of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A leading code fence&lt;/li&gt;
&lt;li&gt;An optional info string&lt;/li&gt;
&lt;li&gt;A code sample&lt;/li&gt;
&lt;li&gt;A trailing code fence&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So the code block above has an info string of &lt;code&gt;html {class=&amp;quot;html-code&amp;quot; id=&amp;quot;my-codeblock&amp;quot; lineNos=inline tabWidth=4}&lt;/code&gt;. This info string is passed to the render hook template as a &lt;code&gt;CodeFence&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;Some ideas for code block render hooks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add a copy button to each code block to allow your users to easily copy and paste the code.&lt;/li&gt;
&lt;li&gt;Add an open in CodePen or open in StackBlitz button to allow users to quickly try out the code.&lt;/li&gt;
&lt;li&gt;Add a small label of the language used in the example&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- https://gohugo.io/templates/render-hooks/ --&gt;
&lt;h2 id="further-reading" class="mt-5"&gt;Further reading
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#further-reading"
aria-label="Link to this section: Further reading"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;This was a quick introduction to Markdown render hooks with some examples which I hope inspire you to add to your projects.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s so much more you can do though - Hugo contributor Joe Mooring has written up a
fantastic, &lt;a href="https://www.veriphor.com/articles/link-and-image-render-hooks/" target="_blank" rel="noopener"&gt;in-depth guide to render hooks over on his website&lt;/a&gt; so I recommend you take a look.&lt;/p&gt;
&lt;p&gt;Happy coding!&lt;/p&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2023/markdown-render-hooks-in-hugo.jpg"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2023/markdown-render-hooks-in-hugo.jpg"/>
</item>
<item>
<title>HTMLHint VS Code Extension</title>
<link>https://christianoliff.com/blog/htmlhint-vscode-extension/</link>
<pubDate>Wed, 06 Sep 2023 01:01:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/htmlhint-vscode-extension/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2023/header-htmlhint-vscode-extension.jpg" alt=""/>&lt;/p>&lt;p&gt;Last year I published the official &lt;a href="https://marketplace.visualstudio.com/items?itemName=HTMLHint.vscode-htmlhint" target="_blank" rel="noopener"&gt;HTMLHint extension for VS Code&lt;/a&gt; after Microsoft deprecated their version. Thanks to the fine folks over at Microsoft in assisting with the migration to the HTMLHint org on GitHub!&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve since made several updates to the extension, including optimizations and fixes. The extension is now up to date with the latest &lt;a href="https://htmlhint.com" target="_blank" rel="noopener"&gt;HTMLHint&lt;/a&gt; version and it&amp;rsquo;s now possible to use with file-types other than HTML (for example Markdown, PHP etc.)&lt;/p&gt;
&lt;p&gt;
&lt;img src="https://christianoliff.com/img/2023/htmlhint-extension.png" alt="HTMLHint Extension" decoding="async" loading="lazy"
width=1533 height="800"
&gt;
&lt;/p&gt;
&lt;p&gt;The extension on the Visual Studio Marketplace at the time of writing has now had more than 200,000 downloads and I recently published it to the OpenVSX registry too, so you can install it from there if you&amp;rsquo;re a VSCodium user.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=HTMLHint.vscode-htmlhint" target="_blank" rel="noopener"&gt;Download at Visual Studio Marketplace&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://open-vsx.org/extension/HTMLHint/vscode-htmlhint" target="_blank" rel="noopener"&gt;Download at OpenVSX Registry&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There&amp;rsquo;s a few open issues which we need help with, so if you&amp;rsquo;re interested in contributing to the extension, please check out the &lt;a href="https://github.com/htmlhint/vscode-htmlhint" target="_blank" rel="noopener"&gt;GitHub repo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Happy HTML hinting!&lt;/p&gt;
&lt;style&gt;
article img[src$=".png"] {
max-width: 580px;
border: 1px solid #333;
margin-left: auto;
margin-right: auto;
}
&lt;/style&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2023/header-htmlhint-vscode-extension.jpg"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2023/header-htmlhint-vscode-extension.jpg"/>
</item>
<item>
<title>Popover CSS Inspector for Bootstrap 5</title>
<link>https://christianoliff.com/blog/popover-css-inspector/</link>
<pubDate>Fri, 25 Aug 2023 09:01:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/popover-css-inspector/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2023/header-popover-css-inspector.png" alt=""/>&lt;/p>&lt;p&gt;I recently spent a while looking for a CSS inspector JavaScript library that would function in a way similar to DevTools elements inspector that would show the CSS rules applied to a component. I couldn&amp;rsquo;t find one that worked the way I wanted, so I decided to build one myself.&lt;/p&gt;
&lt;p&gt;I wanted to make it so it&amp;rsquo;d be easy to use, look nice and be customizable with the ability to turn certain CSS properties on or off. I decided to base the inspector on Bootstrap 5&amp;rsquo;s popover component as it&amp;rsquo;s a nice looking component that&amp;rsquo;s easy to customize.&lt;/p&gt;
&lt;div class="row py-4 py-sm-0"&gt;
&lt;div class="col-12 py-5 py-sm-3"&gt;
&lt;div class="py-5 bg-secondary bg-opacity-10 bd-blur rounded"&gt;
&lt;div class="py-5 ps-sm-5 ms-md-5 rounded"&gt;
&lt;button type="button"
class="btn btn-warning pe-none"
data-bs-custom-class="popover-css-inspector"
data-bs-toggle="popover"
data-bs-placement="right"
data-css-inspector-hide="user-select"
data-css-inspector-show="b-width font-weight"
data-bs-container=".col-12"&gt;
Button
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;style&gt;
.popover-body {
border-radius: .5rem;
}
&lt;/style&gt;
&lt;p&gt;The compiled JavaScript is only 3KB minified and gzipped and every CSS property can be turned on or off by adding the &lt;code&gt;data-css-inspector-hide&lt;/code&gt; or &lt;code&gt;data-css-inspector-show&lt;/code&gt; attributes to the popover trigger element.&lt;/p&gt;
&lt;p&gt;The inspector can be used on any element, not just Bootstrap components. The inspector is also responsive and will reposition itself if it goes off the screen and is also fully customizable with CSS variables.&lt;/p&gt;
&lt;p&gt;Using it is as simple as adding the &lt;code&gt;data-bs-custom-class=&amp;quot;popover-css-inspector&amp;quot;&lt;/code&gt; attribute to the popover trigger element and loading the JavaScript:&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/js/popover-css-inspector.min.js&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;defer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Check it out, I hope you find it useful!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://coliff.github.io/popover-css-inspector/" target="_blank" rel="noopener"&gt;Demo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/coliff/popover-css-inspector/" target="_blank" rel="noopener"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/popover-css-inspector" target="_blank" rel="noopener"&gt;npm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2023/header-popover-css-inspector.png"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2023/header-popover-css-inspector.png"/>
</item>
<item>
<title>Building a Bootstrap Accordion with the details/summary HTML tags</title>
<link>https://christianoliff.com/blog/building-a-bootstrap-accordion-with-the-details-summary-html-tags/</link>
<pubDate>Wed, 28 Jun 2023 09:01:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/building-a-bootstrap-accordion-with-the-details-summary-html-tags/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/2023/header-bootstrap-accordion-with-details-summary.jpg" alt=""/>&lt;/p>&lt;style&gt;
details.accordion-item:not([open]) .accordion-button {
background-color: var(--bs-accordion-bg);
}
details.accordion-item:not([open]):last-of-type .accordion-button {
border-bottom-right-radius: var(--bs-accordion-border-radius);
border-bottom-left-radius: var(--bs-accordion-border-radius);
}
details.accordion-item:not([open]) .accordion-button::after {
background-image: var(--bs-accordion-btn-active-icon);
transform: unset;
}
details.accordion-item[open] .accordion-button::after {
background-image: var(--bs-accordion-btn-icon);
transform: var(--bs-accordion-btn-icon-transform);
}
summary.accordion-button::-webkit-details-marker {
display: none;
}
&lt;/style&gt;
&lt;p&gt;I recently had to build an accordion for a small single-page project. As I was using Bootstrap 5 for the CSS I wanted to see if I could apply the accordion styling to the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details" target="_blank" rel="noopener"&gt;&lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt;&lt;/a&gt; HTML5 tag without needing to use Bootstrap JavaScript. Here&amp;rsquo;s the solution I came up with.&lt;/p&gt;
&lt;div class="accordion border-bottom-0 my-5 pb-5"&gt;
&lt;details class="accordion-item border-bottom-0"&gt;
&lt;summary class="accordion-button rounded-top"&gt;
&lt;div class="accordion-header user-select-none"&gt;
Accordion Title 1
&lt;/div&gt;
&lt;/summary&gt;
&lt;div class="accordion-body border-bottom"&gt;
&lt;p&gt;
Last Friday night, yeah I think we broke the law, always say we're gonna stop. And on my 18th Birthday we got matching tattoos. All to me, give it all to me. Don't be a chicken boy, stop acting like a bitch. Suiting up for my crowning battle. Respect.
&lt;/p&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;details class="accordion-item border-bottom-0"&gt;
&lt;summary class="accordion-button"&gt;
&lt;div class="accordion-header user-select-none"&gt;
Accordion Title 2
&lt;/div&gt;
&lt;/summary&gt;
&lt;div class="accordion-body border-bottom"&gt;
&lt;p&gt;
Why don't you let me stop by? We freak in my jeep, Snoop Doggy Dogg on the stereo. Got a motel and built a fort out of sheets. It’s in the palm of your hand now baby. I was tryna hit it and quit it. Trying to connect the dots, don't know what to tell my boss.
&lt;/p&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;details class="accordion-item"&gt;
&lt;summary class="accordion-button"&gt;
&lt;div class="accordion-header user-select-none"&gt;
Accordion Title 3
&lt;/div&gt;
&lt;/summary&gt;
&lt;div class="accordion-body"&gt;
&lt;p&gt;
I know you get me so I let my walls come down, down. A perfect storm, perfect storm. Yes, we make angels cry, raining down on earth from up above. Do you ever feel like a plastic bag. The girl's a freak, she drive a jeep in Laguna Beach.
&lt;/p&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;h3 id="html" class="mt-5"&gt;HTML
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#html"
aria-label="Link to this section: HTML"&gt;&lt;/a&gt;
&lt;/h3&gt;&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion border-bottom-0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-item border-bottom-0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-button rounded-top&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-header user-select-none&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Accordion Title 1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-body border-bottom&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;....&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-item border-bottom-0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-button&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-header user-select-none&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Accordion Title 2&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-body border-bottom&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;....&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-item&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-button&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-header user-select-none&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Accordion Title 3&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;accordion-body&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;....&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id="custom-css" class="mt-5"&gt;Custom CSS
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#custom-css"
aria-label="Link to this section: Custom CSS"&gt;&lt;/a&gt;
&lt;/h3&gt;&lt;p&gt;To animate the chevron rotating we need to add a few CSS rules.&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;not&lt;/span&gt;&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="nt"&gt;open&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;accordion&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;not&lt;/span&gt;&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="nt"&gt;open&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;last-of-type&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;border-bottom-right-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;accordion&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;border-bottom-left-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;accordion&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;not&lt;/span&gt;&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="nt"&gt;open&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-button&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;accordion&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;btn&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kc"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;unset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-item&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;open&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-button&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;accordion&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;btn&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kc"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;accordion&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;btn&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kc"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;/* Hide the default disclosure triangle on Safari */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;accordion-button&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;-webkit-details-marker&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id="animating-the-collapse-with-the-web-animation-api" class="mt-5"&gt;Animating the Collapse with the Web Animation API
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#animating-the-collapse-with-the-web-animation-api"
aria-label="Link to this section: Animating the Collapse with the Web Animation API"&gt;&lt;/a&gt;
&lt;/h3&gt;&lt;p&gt;An optional extra step is to animate the collapse of the accordion using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API" target="_blank" rel="noopener"&gt;Web Animation API&lt;/a&gt;. The script is less than 1 KB of JavaScript (minified &amp;amp; gzipped) . The animation is triggered by the &lt;code&gt;click&lt;/code&gt; event on the &lt;code&gt;&amp;lt;summary&amp;gt;&lt;/code&gt; element.&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Accordion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;summary&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;.accordion-body&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isClosing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isExpanding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;click&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;overflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;hidden&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isClosing&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isExpanding&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shrink&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;shrink&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isClosing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetHeight&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;px`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetHeight&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;px`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animation&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;easing&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ease-in-out&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onfinish&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onAnimationFinish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;oncancel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isClosing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetHeight&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;px`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;expand&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;expand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isExpanding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetHeight&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;px`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetHeight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetHeight&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;px`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animation&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;easing&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ease-out&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onfinish&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onAnimationFinish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;oncancel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isExpanding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;onAnimationFinish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isClosing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isExpanding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;overflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;details&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Accordion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/2023/header-bootstrap-accordion-with-details-summary.jpg"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/2023/header-bootstrap-accordion-with-details-summary.jpg"/>
</item>
<item>
<title>Using PurgeCSS with Hugo</title>
<link>https://christianoliff.com/blog/using-purgecss-with-hugo/</link>
<pubDate>Tue, 05 Jul 2022 06:01:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/using-purgecss-with-hugo/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/header-using-purgecss-with-hugo.png" alt=""/>&lt;/p>&lt;p&gt;&lt;a href="https://purgecss.com/" target="_blank" rel="noopener"&gt;PurgeCSS&lt;/a&gt; is a great tool which can dramatically reduce the amount of compiled CSS deployed to your site by removing any classes that are not being used in your HTML markup - leaving only the CSS which is used. This will decrease the file-size of the compiled CSS and in turn, improve page load speeds.&lt;/p&gt;
&lt;p&gt;There are a few different ways of integrating PurgeCSS into your Hugo build process.&lt;/p&gt;
&lt;p&gt;You could &lt;a href="https://purgecss.com/CLI.html" target="_blank" rel="noopener"&gt;use the CLI&lt;/a&gt; and add a script to run PurgeCSS &lt;em&gt;after&lt;/em&gt; Hugo has finished building.&lt;/p&gt;
&lt;p&gt;In this tutorial though we&amp;rsquo;ll use PurgesCSS with PostCSS to immediately process the changes. For this you&amp;rsquo;ll need &lt;a href="https://gohugo.io/troubleshooting/faq/#i-get--this-feature-is-not-available-in-your-current-hugo-version" target="_blank" rel="noopener"&gt;Hugo Extended which supports SCSS&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="install-purgecss" class="mt-5"&gt;Install PurgeCSS
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#install-purgecss"
aria-label="Link to this section: Install PurgeCSS"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;First of all, install the required &lt;a href="https://purgecss.com/plugins/postcss.html" target="_blank" rel="noopener"&gt;PurgeCSS PostCSS&lt;/a&gt; package:&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install postcss postcss-cli @fullhuman/postcss-purgecss&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id="create-config-file" class="mt-5"&gt;Create config file
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#create-config-file"
aria-label="Link to this section: Create config file"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Next (if you don&amp;rsquo;t have one already) create a &lt;code&gt;postcss.config.js&lt;/code&gt; at the project root with these contents as an example starting point.&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;@fullhuman/postcss-purgecss&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;./assets/js/*.js&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;./content/*.md&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;./layouts/**/*.html&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;./static/js/*.js&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;safelist&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;arrow&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;tooltip&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;tooltip-arrow&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;tooltip-inner&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;webmentions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;blocklist&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;btn-group&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The &lt;strong&gt;content&lt;/strong&gt; section is what PurgeCSS will scan to include all the CSS classes that are used on your site so make sure you include the path to your markdown files, your templates and any JavaScript which may inject CSS classes to your templates DOM.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;strong&gt;safelist&lt;/strong&gt; section can be used to list any CSS classes that you never want removing. Ensure that any CSS is added here that maybe loaded via any externally hosted JavaScript.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;strong&gt;blocklist&lt;/strong&gt; section can be used to list any CSS classes that you don&amp;rsquo;t want in your compiled CSS. This will remove any CSS classes even if they are in your HTML or markdown files so be sure to only ever include CSS classes that you definitely don&amp;rsquo;t want included.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can read more about the &lt;a href="https://purgecss.com/configuration.html" target="_blank" rel="noopener"&gt;configuration options in the official docs&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="test" class="mt-5"&gt;Test
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#test"
aria-label="Link to this section: Test"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;This method of using PurgeCSS with your site is quite straightforward and if setup correctly shouldn&amp;rsquo;t cause any problems, but it&amp;rsquo;s always a good idea to test your ste and ensure everything is working as expected before deploying to production.&lt;/p&gt;
&lt;p&gt;Once your site has been deployed you can test how the performance with Google&amp;rsquo;s Lighthouse Performance Audit. Lighthouse is built-in to Chrome&amp;rsquo;s Dev Tools, but I like to use the &lt;a href="https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk?hl=en" target="_blank" rel="noopener"&gt;browser extension&lt;/a&gt; and have the icon pinned in my browser toolbar giving me immediate access to a quick audit without even needing to open dev tools. Look out for the &lt;a href="https://web.dev/unused-css-rules/" target="_blank" rel="noopener"&gt;Unused CSS&lt;/a&gt; rule in the audit. You should hopefully now see it in the &amp;lsquo;Passed Audits&amp;rsquo;.&lt;/p&gt;
&lt;p&gt;
&lt;img src="https://christianoliff.com/img/2022/lighthouse-audit.png" alt="Lighthouse Audit" decoding="async" loading="lazy"
width=874 height="437"
&gt;
&lt;/p&gt;
&lt;h2 id="bonus-tip" class="mt-5"&gt;Bonus Tip
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#bonus-tip"
aria-label="Link to this section: Bonus Tip"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Using PurgeCSS is a great way of reducing the compiled CSS size, but consider always minifying the other static assets at build time by adding the following to your Hugo config file.&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;minify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;minifyOutput&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This will minify your CSS, HTML, JS, JSON, SVGs and XML automatically. Read more about the &lt;a href="https://gohugo.io/getting-started/configuration/#configure-minify" target="_blank" rel="noopener"&gt;Minify options in the Hugo Docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Note: This blog post covers what I&amp;rsquo;ll go over in the &amp;lsquo;Using PurgeCSS with Hugo&amp;rsquo; talk for &lt;a href="https://hugoconf.io/" target="_blank" rel="noopener"&gt;HugoConf&lt;/a&gt;. A quick demo repo is at: &lt;a href="https://github.com/coliff/purgecss-test/" target="_blank" rel="noopener"&gt;https://github.com/coliff/purgecss-test/&lt;/a&gt;&lt;/p&gt;
&lt;style&gt;
article img[src$=".png"] {
background-color: #212121;
max-width: 100%;
}
&lt;/style&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/header-using-purgecss-with-hugo.png"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/header-using-purgecss-with-hugo.png"/>
</item>
<item>
<title>Safari for iOS 16 Wishlist</title>
<link>https://christianoliff.com/blog/safari-ios16-wishlist/</link>
<pubDate>Thu, 26 May 2022 03:11:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/safari-ios16-wishlist/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/header-safari-ios16-wishlist.png" alt=""/>&lt;/p>&lt;p&gt;With &lt;a href="https://developer.apple.com/wwdc22/" target="_blank" rel="noopener"&gt;WWDC 2022&lt;/a&gt; now just a couple of weeks away here is my Web Developers wish list for Safari on iOS 16.&lt;/p&gt;
&lt;style&gt;
article img[src$=".png"] {max-width:260px;float:right;padding-left:16px;margin-top:-2px;background-color:#000;}
article img[src$=".jpg"] {width:680px;margin-left:auto;margin-right:auto}
li code {color:inherit;font-family:inherit}
li code {font-size:inherit}
&lt;/style&gt;
&lt;h2 id="native-iframe-lazy-loading" class="mt-5"&gt;Native iframe Lazy Loading
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#native-iframe-lazy-loading"
aria-label="Link to this section: Native iframe Lazy Loading"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;&lt;a href="https://caniuse.com/loading-lazy-attr" target="_blank" rel="noopener"&gt;Native lazy loading of iframes&lt;/a&gt; with &lt;code&gt;loading='lazy'&lt;/code&gt; has shipped in Chrome and Edge already. This feature is available in Safari via &lt;strong&gt;Advanced Settings &amp;gt; Experimental Features&lt;/strong&gt; so hopefully we&amp;rsquo;ll see this enabled by default in iOS 16. I&amp;rsquo;d find it useful to lazy load YouTube iframe embeds so they don&amp;rsquo;t load automatically until a user scrolls near them.&lt;/p&gt;
&lt;p&gt;I requested this feature via &lt;a href="https://github.com/feedback-assistant/reports/issues/87" target="_blank" rel="noopener"&gt;Feedback Assistant&lt;/a&gt; - &lt;a href="https://github.com/feedback-assistant/reports" target="_blank" rel="noopener"&gt;you can too&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="low-data-mode-javascript-api" class="mt-5"&gt;Low-data Mode JavaScript API
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#low-data-mode-javascript-api"
aria-label="Link to this section: Low-data Mode JavaScript API"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;A &amp;lsquo;Low Data Mode&amp;rsquo; has been available in iOS Network Settings for a few years now. Setting this will disable automatic app updates, background iCloud syncing and lower the video/audio streaming quality in some apps. It&amp;rsquo;d be great if this setting was available to web developers via a JavaScript API.&lt;/p&gt;
&lt;p&gt;I requested this feature via &lt;a href="https://github.com/feedback-assistant/reports/issues/90" target="_blank" rel="noopener"&gt;Feedback Assistant&lt;/a&gt; - &lt;a href="https://github.com/feedback-assistant/reports" target="_blank" rel="noopener"&gt;you can too&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="view-source-mode--safari-web-inspector" class="mt-5"&gt;View Source Mode / Safari Web Inspector
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#view-source-mode--safari-web-inspector"
aria-label="Link to this section: View Source Mode / Safari Web Inspector"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;There are a few simple &lt;a href="https://andadinosaur.com/launch-web-inspector-for-ios#web-inspector-support" target="_blank" rel="noopener"&gt;&amp;lsquo;view source&amp;rsquo; third-party apps in the App Store&lt;/a&gt; for this, but it&amp;rsquo;d be really nice to see a more feature-rich native option for debugging sites with iPadOS. Ideally it should have a JavaScript console, network page resources and element inspector tabs.&lt;/p&gt;
&lt;p&gt;
&lt;img src="https://christianoliff.com/img/2022/web-inspector.jpg" alt="Web Inspector for iPad" decoding="async" loading="lazy"
width=2388 height="1668"
&gt;
&lt;small class="d-block text-muted ms-1"&gt;&lt;i&gt;Web Inspector App for iPad&lt;/i&gt;&lt;/small&gt;&lt;/p&gt;
&lt;h2 id="http3" class="mt-5"&gt;HTTP/3
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#http3"
aria-label="Link to this section: HTTP/3"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;The next version of the HTTP networking protocol, previously known as HTTP-over-QUIC is already enabled in Firefox, Chrome and Edge so it&amp;rsquo;d be great to see this enabled in Safari too.&lt;/p&gt;
&lt;h2 id="support-for-the-prefers-reduced-data-media-query" class="mt-5"&gt;Support for the &lt;code&gt;prefers-reduced-data&lt;/code&gt; Media Query
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#support-for-the-prefers-reduced-data-media-query"
aria-label="Link to this section: Support for the prefers-reduced-data Media Query"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-data" target="_blank" rel="noopener"&gt;prefers-reduced-data&lt;/a&gt; CSS media feature is used to detect if the user has requested the web content uses less data.&lt;/p&gt;
&lt;p&gt;This would be very useful to use smaller file-size or no background images, or default to fallback fonts instead of downloading heavy custom fonts.&lt;/p&gt;
&lt;h2 id="svg-favicons" class="mt-5"&gt;SVG Favicons
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#svg-favicons"
aria-label="Link to this section: SVG Favicons"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Safari is the only modern browser which &lt;a href="https://caniuse.com/link-icon-svg" target="_blank" rel="noopener"&gt;doesn&amp;rsquo;t support SVG favicons&lt;/a&gt;. It&amp;rsquo;d be nice to see support added because SVG favicons can support media queries.&lt;/p&gt;
&lt;h2 id="experimental-features-menu-improvements" class="mt-5"&gt;Experimental Features Menu Improvements
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#experimental-features-menu-improvements"
aria-label="Link to this section: Experimental Features Menu Improvements"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;
&lt;img src="https://christianoliff.com/img/2022/experimental-features.png" alt="Experimental WebKit Features" decoding="async" loading="lazy"
width=750 height="1334"
&gt;
&lt;/p&gt;
&lt;p&gt;In the Experimental WebKit Features menu only the title is displayed, and that is often truncated and unavailable to view in full making it impossible to know what some features are.&lt;/p&gt;
&lt;p&gt;See the screenshot on right for some examples.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What is &amp;lsquo;Allow per media element speak&amp;hellip;&amp;rsquo;?&lt;/li&gt;
&lt;li&gt;What does the &amp;lsquo;Aspect ratio of &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; from wid&amp;hellip;&amp;rsquo; do?&lt;/li&gt;
&lt;li&gt;What does &amp;lsquo;block top-level redirects by thir&amp;hellip;&amp;rsquo; mean?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;d like there to be an info link to learn more about a particular feature to see the W3C spec / API details or a link to the relevant WebKit issue.&lt;/p&gt;
&lt;p&gt;If a Safari Web Inspector feature was added then it could make sense to move these options to a tab there instead of hidden away many levels deep in System Settings.&lt;/p&gt;
&lt;div class="clearfix"&gt;&lt;/div&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/header-safari-ios16-wishlist.png"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/header-safari-ios16-wishlist.png"/>
</item>
<item>
<title>GitHub Actions Workflows</title>
<link>https://christianoliff.com/blog/github-actions-workflows/</link>
<pubDate>Mon, 16 May 2022 03:11:28 +0000</pubDate>
<guid>https://christianoliff.com/blog/github-actions-workflows/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/header-github-actions-workflows.jpg" alt=""/>&lt;/p>&lt;p&gt;&lt;a href="https://docs.github.com/en/actions" target="_blank" rel="noopener"&gt;GitHub Actions&lt;/a&gt; provide a great way to automate all parts of your development workflow. I often use the same workflows between open-source projects I work on. I&amp;rsquo;ve added the workflow configs below so feel free to copy and paste them to your projects.&lt;/p&gt;
&lt;style&gt;
details{margin-bottom:12px}
&lt;/style&gt;
&lt;h2 id="codeql" class="mt-5"&gt;CodeQL
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#codeql"
aria-label="Link to this section: CodeQL"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;&lt;a href="https://github.com/github/codeql-action/#codeql-action" target="_blank" rel="noopener"&gt;CodeQL&lt;/a&gt; is GitHub&amp;rsquo;s code security checking engine and this action runs a repository&amp;rsquo;s source code to find security vulnerabilities. It then displays the results in the repository&amp;rsquo;s security tab.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: This is only available for public repositories (or private repositories that have GitHub Advanced Security licensed)&lt;/em&gt;&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Code snippet&lt;/summary&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;CodeQL&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;main ]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pull_request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;main ]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;analyze&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Analyze&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;read&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;read&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;security-events&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;write&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;fail-fast&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matrix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;javascript&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Checkout repository&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;persist-credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Initialize CodeQL&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;github/codeql-action/init@v2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ matrix.language }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Perform CodeQL Analysis&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;github/codeql-action/analyze@v2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p&gt;&lt;a href="https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/setting-up-code-scanning-for-a-repository" target="_blank" rel="noopener"&gt;More info&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="dependency-review" class="mt-5"&gt;Dependency Review
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#dependency-review"
aria-label="Link to this section: Dependency Review"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;This one scans your pull requests for dependency changes and will raise an error if any newly added dependencies have existing vulnerabilities.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: This is only available for public repositories (or private repositories that have GitHub Advanced Security licensed)&lt;/em&gt;&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Code snippet&lt;/summary&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Dependency Review&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;pull_request]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;read&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;dependency-review&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Checkout Repository&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;persist-credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Dependency Review&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/dependency-review-action@v1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p&gt;&lt;a href="https://github.com/actions/dependency-review-action" target="_blank" rel="noopener"&gt;More info&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="cspell-spellcheck" class="mt-5"&gt;cSpell (Spellcheck)
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#cspell-spellcheck"
aria-label="Link to this section: cSpell (Spellcheck)"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;I&amp;rsquo;ve been happily using the &lt;a href="https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker" target="_blank" rel="noopener"&gt;VS Code extension&lt;/a&gt; of this for many years. The GitHub Action workflow is good for helping catch typos from contributors at the pull request stage. I recommend adding a &lt;code&gt;cspell.json&lt;/code&gt; config to your projects root, adding any false-positives to the dictionary and checking it in to git.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Code snippet&lt;/summary&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Check spelling&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# rebuild any PRs and main branch changes&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pull_request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches-ignore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;dependabot/**&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;read&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;spellcheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# run the action&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;persist-credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;streetsidesoftware/cspell-action@v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;warning&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;strict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;incremental_files_only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p&gt;&lt;a href="https://github.com/actions/dependency-review-action" target="_blank" rel="noopener"&gt;More info&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="test" class="mt-5"&gt;Test
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#test"
aria-label="Link to this section: Test"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;If you have a test script defined in your &lt;code&gt;package.json&lt;/code&gt; then you can set this to run on every PR.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Code snippet&lt;/summary&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Lint&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches-ignore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;dependabot/**&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pull_request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;FORCE_COLOR&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;NODE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;read&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;lint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Clone repository&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;persist-credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Set up Node.js&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/setup-node@v3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;node-version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;${{ env.NODE }}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;npm&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Install npm dependencies&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;npm ci&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Lint&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;npm run lint&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;h2 id="super-linter" class="mt-5"&gt;Super Linter
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#super-linter"
aria-label="Link to this section: Super Linter"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;This project from the folks at GitHub bundles a huge number of linters. You can tweak the linting configs or disable linting for a particular type. I recommend including this even if you have a test GitHub Action as above as Super Linter can test for additional files such as GitHub Actions.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Code snippet&lt;/summary&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Lint Code Base&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches-ignore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;dependabot/**&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;read&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Lint Code Base&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Checkout Code&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;persist-credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Lint Code Base&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;github/super-linter/slim@v4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;VALIDATE_ALL_CODEBASE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;DEFAULT_BRANCH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;VALIDATE_MARKDOWN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p&gt;&lt;a href="https://github.com/github/super-linter" target="_blank" rel="noopener"&gt;More info&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="wrap-up" class="mt-5"&gt;Wrap up
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#wrap-up"
aria-label="Link to this section: Wrap up"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;I recommend to always keep a &lt;code&gt;dependabot.yml&lt;/code&gt; config file in your repo&amp;rsquo;s &lt;code&gt;.github&lt;/code&gt; directory with something like the below to ensure you get PRs to update to any new versions of GitHub Actions as they become available.&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;updates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;package-ecosystem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;github-actions&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;monthly&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;I personally like to have them set on a monthly schedule to cut down on noise but you can change that to daily or weekly.&lt;/p&gt;
&lt;p&gt;You can do so much more with GitHub Actions - check the &lt;a href="https://docs.github.com/en/actions/using-workflows/advanced-workflow-features" target="_blank" rel="noopener"&gt;Advanced workflow features&lt;/a&gt; docs on GitHub for more ideas.&lt;/p&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/header-github-actions-workflows.jpg"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/header-github-actions-workflows.jpg"/>
</item>
<item>
<title>Freshdesk Messaging Facade</title>
<link>https://christianoliff.com/blog/freshdesk-messaging-facade/</link>
<pubDate>Tue, 26 Oct 2021 03:11:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/freshdesk-messaging-facade/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/header-freshdesk-messaging-facade.png" alt=""/>&lt;/p>&lt;p&gt;The &lt;a href="https://developers.freshchat.com/web-sdk/" target="_blank" rel="noopener"&gt;Freshdesk Messaging&lt;/a&gt; chat widget loads 1.1 MB (gzipped) of JavaScript and assets on page load increasing the time for the page to complete loading by 5 seconds. Typically only a small percentage of users will interact with the chat widget meaning that most users have needlessly downloaded a lot of data. It&amp;rsquo;d be better if the code for the widget loaded when hovered over instead.&lt;/p&gt;
&lt;figure&gt;
&lt;blockquote class="blockquote ms-4 opacity-75"&gt;
&lt;blockquote&gt;
"A &lt;em&gt;facade&lt;/em&gt; is a static element which looks similar to the actual embedded third-party, but is not functional and therefore much less taxing on the page load."
&lt;figcaption class="blockquote-footer mt-0 ms-4"&gt;
&lt;cite&gt;
&lt;a href="https://web.dev/third-party-facades/"&gt;Google web.dev&lt;/a&gt;
&lt;/cite&gt;
&lt;/figcaption&gt;
&lt;/blockquote&gt;
&lt;/figure&gt;
&lt;p&gt;Inspired by the awesome &lt;a href="https://github.com/paulirish/lite-youtube-embed" target="_blank" rel="noopener"&gt;Lite YouTube Embed&lt;/a&gt; by Paul Irish I created a lightweight embed which is 1/1000th of the size.&lt;/p&gt;
&lt;h2 id="comparison" class="mt-5"&gt;Comparison
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#comparison"
aria-label="Link to this section: Comparison"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;table class="table fw-normal"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Freshdesk Messaging JS&lt;/th&gt;
&lt;th&gt;Freshdesk Messaging Facade&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Number of assets&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network Transfer size&lt;/td&gt;
&lt;td&gt;1097 KB&lt;/td&gt;
&lt;td&gt;1 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Page Complete Time&lt;/td&gt;
&lt;td&gt;6.3 s&lt;/td&gt;
&lt;td&gt;1.1 s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="how-it-works" class="mt-5"&gt;How it works
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#how-it-works"
aria-label="Link to this section: How it works"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;A div with an inline SVG of the Freshdesk Messaging icon is displayed in the bottom-right corner - appearing just like the real thing. When a user hovers within 300 pixels it starts to download the Freshdesk Messaging script. A simple animated icon is displayed as the script loads.&lt;/p&gt;
&lt;link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/freshdesk-messaging-facade@1/css/freshdesk-messaging-facade.min.css"&gt;
&lt;div class="w-100 bg-white p-3 me-1 pe-1 shadow" style="min-height:88px"&gt;
&lt;did id="freshdesk-messaging" class="float-end me-2"&gt;
&lt;div id="freshdesk-messaging-icon" tabindex="0" role="button" aria-label="Chat" style="position:inherit;right:inherit"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="how-to-use" class="mt-5"&gt;How to use
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#how-to-use"
aria-label="Link to this section: How to use"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Load the CSS and JS in your head:&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;css/freshdesk-messaging-facade.min.css&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;js/freshdesk-messaging-facade.min.js&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;module&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;async&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Load the web component within your page:&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;freshdesk-messaging-facade&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;freshdesk-messaging-facade&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-siteid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;freshdesk-messaging-icon&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;tabindex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;button&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;freshdesk-messaging-facade&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Add your 36-digit Freshdesk Messaging token to the &lt;code&gt;data-token&lt;/code&gt; and your site&amp;rsquo;s id to &lt;code&gt;data-siteid&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="demo" class="mt-5"&gt;Demo
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#demo"
aria-label="Link to this section: Demo"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;&lt;a href="https://coliff.github.io/freshdesk-messaging-facade/" target="_blank" rel="noopener"&gt;https://coliff.github.io/freshdesk-messaging-facade/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="faqs" class="mt-5"&gt;FAQs
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#faqs"
aria-label="Link to this section: FAQs"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Q. How can I customize the chat widget&amp;rsquo;s color?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A. You can modify the background-color value of &lt;code&gt;#freshdesk-messaging-icon&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Q. Can I load this from a CDN?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A. Yes, it&amp;rsquo;s available on &lt;a href="https://www.jsdelivr.com/package/npm/freshdesk-messaging-facade" target="_blank" rel="noopener"&gt;JSDelivr&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Q. Does it work in IE 11?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A. No, but you can easily load the standard Freshdesk Messaging widget and add the &lt;code&gt;nomodule&lt;/code&gt; attribute to it as a fallback for legacy browsers. &lt;a href="https://gist.github.com/coliff/fe18a182c8224d8d92ae1c31a31d756f" target="_blank" rel="noopener"&gt;View Gist&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="known-issues" class="mt-5"&gt;Known Issues
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#known-issues"
aria-label="Link to this section: Known Issues"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Some content blockers on iOS may block the Freshdesk Messaging widget leading to the facade being non-functioning.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Freshdesk Messaging widget and assets are large so it can take a couple of seconds for them to load.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="contributing" class="mt-5"&gt;Contributing
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#contributing"
aria-label="Link to this section: Contributing"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;This project is &lt;a href="https://github.com/coliff/freshdesk-messaging-facade" target="_blank" rel="noopener"&gt;open source and contributions are welcome!&lt;/a&gt;&lt;/p&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/header-freshdesk-messaging-facade.png"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/header-freshdesk-messaging-facade.png"/>
</item>
<item>
<title>Carbon Ads or Google AdSense - Which is best?</title>
<link>https://christianoliff.com/blog/carbonads-or-google-ads-which-is-best/</link>
<pubDate>Fri, 24 Sep 2021 09:21:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/carbonads-or-google-ads-which-is-best/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/header-carbonads-or-google-ads-which-is-best.png" alt=""/>&lt;/p>&lt;p&gt;Just a quick post as a few people have asked me about this.&lt;/p&gt;
&lt;p&gt;I switched from using &lt;a href="https://www.google.com/adsense/start/" target="_blank" rel="noopener"&gt;Google AdSense Ads&lt;/a&gt; to &lt;a href="https://www.carbonads.net/" target="_blank" rel="noopener"&gt;Carbon Ads&lt;/a&gt; on this site last year. I noticed that although traffic to this site has remained quite constant, the monthly revenue generated from Carbon Ads were slightly lower than Google Ads.&lt;/p&gt;
&lt;p&gt;Overall though, I&amp;rsquo;d still recommend Carbon Ads for web developer-focused sites. You have more control over where they are positioned, they are less intrusive, look nicer and are more likely to be of interest to your users interest. Carbon Ads also payout from $20 earnings whereas Google only payout after $60 earnings.&lt;/p&gt;
&lt;p&gt;Finally, CarbonAds JavaScript is a lot lighter which makes for faster page load times.&lt;/p&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/header-carbonads-or-google-ads-which-is-best.png"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/header-carbonads-or-google-ads-which-is-best.png"/>
</item>
<item>
<title>Bootstrap 5 Print Stylesheet</title>
<link>https://christianoliff.com/blog/print-css-for-bootstrap-5/</link>
<pubDate>Wed, 07 Jul 2021 02:21:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/print-css-for-bootstrap-5/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/header-bootstrap-print-css.png" alt=""/>&lt;/p>&lt;style&gt;
header {
background-size: contain !important;
}
&lt;/style&gt;
&lt;p&gt;Bootstrap 5 no longer includes custom CSS to enhance the layout when printing (to paper or as a PDF). I&amp;rsquo;ve bundled up the Print styles from Bootstrap 4 and published them to npm for easy use within projects.&lt;/p&gt;
&lt;p&gt;Note: This should improve the experience when printing, but there are &lt;a href="https://github.com/twbs/bootstrap/issues?page=2&amp;amp;q=is%3Aissue&amp;#43;sort%3Aupdated-desc&amp;#43;print" target="_blank" rel="noopener"&gt;bugs and inconsistencies&lt;/a&gt; with the way that browsers handle printing so testing is recommended.&lt;/p&gt;
&lt;h2 id="quick-start" class="mt-5"&gt;Quick Start
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#quick-start"
aria-label="Link to this section: Quick Start"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/coliff/bootstrap-print-css/" target="_blank" rel="noopener"&gt;Download the latest release&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Clone the repo &lt;code&gt;git clone https://github.com/coliff/bootstrap-print-css.git&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Install with &lt;a href="https://www.npmjs.com/package/bootstrap-print-css" target="_blank" rel="noopener"&gt;npm&lt;/a&gt; &lt;code&gt;npm install bootstrap-print-css&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Install with &lt;a href="https://yarnpkg.com/package/bootstrap-print-css" target="_blank" rel="noopener"&gt;yarn&lt;/a&gt; &lt;code&gt;yarn add bootstrap-print-css&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="usage" class="mt-5"&gt;Usage
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#usage"
aria-label="Link to this section: Usage"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;You can include the CSS by either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Importing the &lt;code&gt;bootstrap-print.css&lt;/code&gt; to your main CSS. This will mean one less HTTP request compared to loading it separately. (Recommended)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Loading it as a separate CSS file:&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/css/bootstrap-print.min.css&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;media&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;print&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;It&amp;rsquo;s available on CDN too if you prefer:&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://cdn.jsdelivr.net/npm/bootstrap-print-css/css/bootstrap-print.min.css&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;media&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;print&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can prevent any elements you&amp;rsquo;d like to be not printed with Bootstraps&amp;rsquo;s &lt;code&gt;.d-print-none&lt;/code&gt; utility class. You may want to consider adding that to ads, navbars, footers etc.&lt;/p&gt;
&lt;h2 id="contributing" class="mt-5"&gt;Contributing
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#contributing"
aria-label="Link to this section: Contributing"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;For any Bootstrap 5 specific changes please &lt;a href="https://github.com/coliff/bootstrap-print-css" target="_blank" rel="noopener"&gt;open a PR or an issue at GitHub&lt;/a&gt; and for general improvements to the stylesheet please make open a PR or an issue upstream at &lt;a href="https://github.com/h5bp/main.css/" target="_blank" rel="noopener"&gt;main.css&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="how-can-i-test-this" class="mt-5"&gt;How can I test this?
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#how-can-i-test-this"
aria-label="Link to this section: How can I test this?"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Chrome/Edge Dev Tools offers &lt;a href="https://developer.chrome.com/docs/devtools/css/print-preview/" target="_blank" rel="noopener"&gt;Print style emulation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;img src="https://christianoliff.com/img/2021/print-stylesheet.png" alt="Screenshot of the emulate Print Stylesheet in Microsoft Edge Dev Tools" decoding="async" loading="lazy"
width=1762 height="855"
&gt;
&lt;/p&gt;
&lt;h2 id="credits--thanks" class="mt-5"&gt;Credits &amp;amp; Thanks
&lt;a class="header-link text-light text-decoration-none fw-normal" href="#credits--thanks"
aria-label="Link to this section: Credits &amp;amp; Thanks"&gt;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;All credit for the CSS work goes to the HTML5 Boilerplate and Bootstrap teams. I&amp;rsquo;ve just copied the &lt;a href="https://github.com/twbs/bootstrap/blob/v4-dev/scss/_print.scss" target="_blank" rel="noopener"&gt;Bootstrap 4 print styles&lt;/a&gt; and packaged them up for Bootstrap 5.&lt;/p&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/header-bootstrap-print-css.png"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/header-bootstrap-print-css.png"/>
</item>
<item>
<title>Building a 'Share this page' feature with Hugo</title>
<link>https://christianoliff.com/blog/building-a-share-this-page-bar-with-hugo/</link>
<pubDate>Mon, 28 Jun 2021 04:21:22 +0000</pubDate>
<guid>https://christianoliff.com/blog/building-a-share-this-page-bar-with-hugo/</guid>
<description>&lt;p>&lt;img src="https://christianoliff.com/img/header/header-building-a-share-this-page-bar-with-hugo.png" alt=""/>&lt;/p>&lt;style&gt;
header {
background-size: contain !important;
}
&lt;/style&gt;
&lt;p&gt;It&amp;rsquo;s easy enough to just copy and paste the JavaScript &amp;lsquo;share this page&amp;rsquo; widgets from Facebook, Twitter, LinkedIn etc, but these load their own JavaScript which comes with a performance and they also add their own tracking scripts to your site. They also have different styling and sizes which can give a messy, cluttered look to the page.&lt;/p&gt;
&lt;p&gt;Instead, you can build-your-own &amp;lsquo;share this page&amp;rsquo; widget with support for Twitter, LinkedIn, Facebook, Email - and the native &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share" target="_blank" rel="noopener"&gt;Web Share API&lt;/a&gt; for a neat, privacy-focused and performant solution with a consistent look.&lt;/p&gt;
&lt;p&gt;Add the following code block as a partial to your project as something like &lt;code&gt;layouts/partials/share-this-page.html&lt;/code&gt;. This uses Bootstrap 5 classes but it can be easily modified to suit your site&amp;rsquo;s CSS. I&amp;rsquo;ve used Font Awesome SVG brand icons as partials so that they are inlined, but you could replace them with &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags instead.&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;share&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://twitter.com/intent/tweet?via={{- .Site.Params.twitterID -}}&amp;amp;text={{ .Title }}&amp;amp;url={{ .Permalink }}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-bs-toggle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;tooltip&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-bs-placement&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;top&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Share on T​witter&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;onclick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;window.open(this.href, &amp;#39;window&amp;#39;, &amp;#39;left=20,top=20,width=500,height=500,toolbar=1,resizable=0&amp;#39;); return false;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {{- partial &amp;#34;icons/fa/brands/twitter-square.svg&amp;#34; (dict &amp;#34;width&amp;#34; &amp;#34;28&amp;#34; &amp;#34;height&amp;#34; &amp;#34;28&amp;#34;) -}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;visually-hidden&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;T​witter&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://www.linkedin.com/shareArticle?mini=true&amp;amp;url={{- .Permalink -}}&amp;amp;title={{- .Title -}}&amp;amp;summary={{- .Summary -}}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-bs-toggle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;tooltip&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Share on Link​edIn&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;onclick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;window.open(this.href, &amp;#39;window&amp;#39;, &amp;#39;left=20,top=20,width=500,height=500,toolbar=1,resizable=0&amp;#39;); return false;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {{- partial &amp;#34;icons/fa/brands/linkedin.svg&amp;#34; (dict &amp;#34;class&amp;#34; &amp;#34;width&amp;#34; &amp;#34;28&amp;#34; &amp;#34;height&amp;#34; &amp;#34;28&amp;#34;) -}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;visually-hidden&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Link​edIn&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://www.facebook.com/sharer.php?u={{- .Permalink -}}&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-bs-toggle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;tooltip&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Share on Facebook&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;onclick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;window.open(this.href, &amp;#39;window&amp;#39;, &amp;#39;left=20,top=20,width=500,height=500,toolbar=1,resizable=0&amp;#39;); return false;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {{- partial &amp;#34;icons/fa/brands/facebook-square.svg&amp;#34; (dict &amp;#34;width&amp;#34; &amp;#34;28&amp;#34; &amp;#34;height&amp;#34; &amp;#34;28&amp;#34;) -}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;visually-hidden&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Facebook&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;mailto:?subject={{ .Title }}&amp;amp;body=Check%20out%20this%20site {{ .Permalink -}}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;onclick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;window.open(this.href, &amp;#39;window&amp;#39;, &amp;#39;left=20,top=20,width=500,height=500,toolbar=1,resizable=0&amp;#39;); return false;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-bs-toggle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;tooltip&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Share via Email&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {{- partial &amp;#34;icons/fa/solid/envelope-square.svg&amp;#34; (dict &amp;#34;width&amp;#34; &amp;#34;28&amp;#34; &amp;#34;height&amp;#34; &amp;#34;28&amp;#34;) -}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;visually-hidden&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Email&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;border-0 bg-transparent btn-share-web-api d-none p-0&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-bs-toggle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;tooltip&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Share&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {{- partial &amp;#34;icons/fa/solid/share-alt-square.svg&amp;#34; (dict &amp;#34;width&amp;#34; &amp;#34;28&amp;#34; &amp;#34;height&amp;#34; &amp;#34;28&amp;#34;) -}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;visually-hidden&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Share&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;I&amp;rsquo;d suggest loading the Web Share API JavaScript as &lt;code&gt;type=&amp;quot;module&amp;quot;&lt;/code&gt; so older browsers (which don&amp;rsquo;t support the Web Share API) will completely ignore it.&lt;/p&gt;
&lt;div class="code-block mb-4"&gt;
&lt;div class="d-flex justify-content-end mb-2"&gt;
&lt;button type="button" class="btn btn-outline-light btn-sm btn-clipboard me-0 mt-0" aria-label="Copy code to clipboard"&gt;
Copy
&lt;/button&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;module&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shareButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.btn-share-web-api&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// if Web Share API is supported then the button will show by removing Bootstrap&amp;#39;s &amp;#39;d-none&amp;#39; utility class
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;share&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;shareButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;d-none&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;shareButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;click&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;share&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;share&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;{{ .Title }} | {{ .Site.Title }}&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;{{ .Description }}&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;{{ .Permalink }}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Thanks for sharing!&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://christianoliff.com/img/header/header-building-a-share-this-page-bar-with-hugo.png"/>
<media:content xmlns:media="http://search.yahoo.com/mrss/" medium="image" url="https://christianoliff.com/img/header/header-building-a-share-this-page-bar-with-hugo.png"/>
</item>
</channel>
</rss>