My website uses many external SVG files with their own <style> elements within the SVG files themselves. I have dark mode media queries within the main website CSS and within the SVG files' own styles: @media (prefers-color-scheme:light) and @media (prefers-color-scheme:dark)
On initial load, or a hard refresh, everything works as expected, both the website CSS and the SVG CSS load the appropriate styles depending on whether the system OS is set to dark or light mode.
But, if I switch the mode in the OS, only the website CSS is updated, not the external SVG file's CSS.
So, I need to either hard reload the cached SVG images in full or somehow perhaps just refresh the SVG CSS.
I have an event listener set up in javascript which correctly detects an OS mode change, but I don't know how to trigger the SVGs to refresh when the OS dark/light mode is changed. I've searched high and low and am not sure how to do this, hopefully, in the simplest, most elegant manner.
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
// WHAT GOES HERE TO REFRESH SVGs TO CORRECTLY REFLECT OS MODE?
});
window.location.reload(true); does not hard reload cached files. I'm not sure if cache.delete is appropriate here, or how I would use it for force a reload of all SVG images (<img src="whatever.svg"/>). Perhaps there is another method I'm overlooking.
Thank you for any help.
This does the trick, a few lines of javascript. First, on page load, identify all SVG images and determine the current prefers-color-scheme theme. Then, detect when that theme changes and append a dynamic cachebreaker to those filenames, which forces SVGs to reload.
// Dark mode changes needs cache refresh for external SVG file CSS.
allImg = document.querySelectorAll('img[src$=".svg"');
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
thisMode = 'dark';
} else {
thisMode = 'light';
}
window.matchMedia('(prefers-color-scheme: '+ thisMode + ')').addEventListener('change', e => {
allImg.forEach(img => {
imgTime = Date.now();
newImgSrc = img.src + '?' + imgTime;
img.src = newImgSrc;
});
});
Updated original answer 12/13/21. Now cachebuster, which forces reload of SVGs, is only called after mode change, not at every page load.
Update 12/19/21: This solution does not work with Safari (there's a known bug whereby Safari doesn't respect the prefers-color-scheme media query within SVG file CSS). For Safari, I wrote extra JS that detects Safari on page load, uses the prefers-color-scheme conditional above, and, if OS is dark mode, replaces all SVG filenames from "image.svg" to "image-dark.svg", calling light or dark versions of each SVG. It also reloads page in Safari when OS dark/light theme changed. If Apple ever fixes the bug, I can go with the simpler solution above.