Minify Dark/Light Mode Switching JavaScript

When I set the ‘Default Color Mode’ to ‘Auto’, Bootstrap Studio adds some JavaScript to handle switching the page to light or dark mode.

I’d love it if you guys would minify this JavaScript.

File > Settings > Design > Export > Export Settings

Turn on the first option, and your JS will be minified.

That won’t work as the JS generated is place in the head of the HTML, minifying HTML won’t work either, this is something @martin would need to address. Although @kuligaposten did provide a solution in another post a few weeks ago (which is now unfortunatly offline).

@richards I mean, if anything fails, @BlueMarble you could always

  1. check the generated html,
  2. anaylze what it did,
  3. made component manually so it can be manually styled using bss tag compliance,
  4. put style on css file,
  5. put the logic in js file,
  6. set bss minifier on, as @printninja said…

@muhammadhakimjazuli the problem with that is by setting the default color mode to auto it will automatically add the unminified javascript. The only solution at the moment is to set the mode to light and use some custom JS as @kuligaposten mentioned in this post:

As a work around using the javascript from bootstrap:

And adding it to a javascript file works,

keeping the bss settings as light

1 Like

If the question is why the theme-switching JS code is in the head of the page, this is deliberate. It is because it needs to run as soon as possible in order to prevent flashing of white content on page load when dark mode has been selected by the user. If this code is moved to a file, it will take some time for the browser to load it during which the incorrect theme is displayed.

The code is small and even though it is unminified it shouldn’t affect your page load time or Lighthouse scores. We can make it respect the Minify export setting and minify it when it is activated, but I am not sure the performance difference can even be measured.

2 Likes

@richards
last comment from @kuligaposten “If you will do something similar remember that the Default Color Mode in the settings dialog must be ‘light’ or ‘dark’ if you choose ‘auto’ it will trigger Bootstrap Studio’s javascript code in the head section”
I failed to understand… what script in the head @kuligaposten refering to…
if you remove the bss theme-switcher default component, and rebuild it manually(as separated html, js and css), shouldn’t you have no script in the head tag?

as for @martin I think there’s a workaround(which most likely we shouldn’t do… but…) for the flashing problem, which is by saving the script as module JS, then reference it in the head tag(manually in the head content setting)…
why module JS?… well…

  1. bss export/publish doesn’t include .mjs file to the bundle process, so it’s likely the script will be there as static file which can be referenced(or some case, replacing .mjs with .min.mjs).
  2. html standard on type=“module”, is only load/run it once(on a single html document)… so in event of you have to include it normally(which is in the bottom, before body closing tag) to avoid some scenario that the file might end up not be export/published, you can add the script tag on the head content, and it still be run only once…

This isn’t anything to do with the theme switch component but rather the theme option in the settings. If you set it to auto then it generates JavaScript in the head

1 Like

@martin’s answer was my first thought. Does it even matter if it’s minified? It’s just a few lines of JS. Unless you’re stuck on a 2G or 3G connection, it’s unlikely you’d notice any difference between minified and beautified versions of this code.

In all but the least modern countries, the days where minifying code makes a noticeable difference in website loading speed are fading fast. 95% of the world has 3G and 60% has 4G. In 5 years, 95% will have 4G, and 5G will be fast replacing it in modern countries.

I often tell people, when considering a website’s loading speed, also consider who will be visiting it, where they are located, and the type of internet connections they have.

For example, I build websites mostly for small businesses located in urban or suburban areas of America. The vast majority of traffic these clients get is from people with broadband/4G internet (100 mbps or faster.) Unless they’re specifically concerned about people in rural areas who are stuck on DSL, 3G, or slow satellite connections, blazing fast website speed is not crucial. A lighthouse score of 60 vs 100 is indistinguishable on a 100 mbps connection. I’ve seen websites that score in the 30’s on Lighthouse that still rank in the top 3 in the Google SERP for their industry.

(Also, the unminified code generated by BSS is already very clean. I’ve seen code from some website builders that is horrific. You should look at the HTML that programs like Adobe Muse used to produce!)

I see, will check it later I guess…

If a model that offers a simplified version of light and dark theme management.
Of course, there’s always room for improvement.
https://theme-management.bss.design

Thanks to @kuligaposten for inspiring me with a solution.

If you only want your site to respect the user’s system color mode setting without the Theme Switcher add this in the head content and in the settings dialog set the Default Color Mode to your prefered mode light or dark not auto

<script>document.documentElement.setAttribute('data-bs-theme',(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'));</script>

if you use the Theme Switcher and want the icon on the dropdown to change to the selected color mode
add this to a javascript file, and do not add any script tag in the head content

class IconChecker {
  constructor() {
    this.init();
  }

  toggleIcon(themeIcon) {
    if (themeIcon) {
      document.querySelectorAll('.theme-switcher').forEach((switcher) => {
        const switcherIcon = switcher.querySelector('svg');
        switcherIcon.innerHTML = '';
        switcherIcon.appendChild(themeIcon.cloneNode(true));
      });
    }
  }

  iconChecker() {
    const theme = localStorage.getItem('theme') || 'auto';
    const icon = document.querySelector(`[data-bs-theme-value=${theme}] svg`);
    if (icon) this.toggleIcon(icon);
  }

  init() {
    const iconObserver = new MutationObserver(() => this.iconChecker());
    iconObserver.observe(document.documentElement, {
      attributeFilter: ['data-bs-theme'],
    });
    this.iconChecker();
  }
}

document.addEventListener('DOMContentLoaded', () => {
  new IconChecker();
});

There is no issue with flashing white content by moving the theme switcher code to a javascript file. Here is an example check it out, if you see any white flashing content let me know.

In your example, you’re loading your theme switcher JS file before the head content. I think Martin meant if you added the JS in the traditional manner in BSS (Design > Javascript) it would get placed before the body closing tag, like any other JS script.

The theme switcher JS is added in the traditional manner in BSS (Design > Javascript). The bs-init-color-modes.js is only visible on a dummy.html which I hide in export. In the export settings the minify js is set to false so the js file doesn’t change name when export.

The example just show that the js code can be in a js-file instead of inline
script in the head <script>the js code here</script> and it wont be any color flickering when changing color mode

Simplified proposal that does not use the “auto” mode.
JS script place in head to apply mode before page display.

let theme = localStorage.getItem('theme');
if (theme) {document.documentElement.setAttribute('data-bs-theme', theme);}

Plus a JavaScript file in the traditional way in BSS.
Example: https://theme-management.bss.design/