<picture>
<source media="(prefers-color-scheme: light)" srcset="https://via.placeholder.com/180/ffff00/000000?text=Light%20image">
<source media="(prefers-color-scheme: dark)" srcset="https://via.placeholder.com/180/002244/ffffff?text=Dark%20image">
<img src="https://via.placeholder.com/180/ffff00/000000?text=Light%20image%20fallback" alt="" />
</picture>
<div>
<h1>Switch theme:</h1>
<button onclick="setPicturesThemed(null)">Default (system)</button>
<button onclick="setPicturesThemed('light')">Light</button>
<button onclick="setPicturesThemed('dark')">Dark</button>
</div>
/***************************************
Presentational styles for demo only!
***************************************/
body {
display: flex;
font-family: sans-serif;
}
img {
display: block;
width: 100%;
}
div {
display: flex;
flex-direction: column;
margin-left: 15px;
}
h1 {
margin: 0;
font-size: 1em;
font-weight: normal;
margin-bottom: 5px;
}
button {
margin-bottom: 5px;
white-space: nowrap;
}
function setPicturesThemed(colorScheme = undefined) {
// Clean up all existing picture sources that were cloned
document.querySelectorAll('picture > source[data-cloned-theme]').forEach(el => {
el.remove();
});
if (colorScheme) {
// Find all picture sources with the desired colour scheme
document.querySelectorAll(`picture > source[media*="(prefers-color-scheme: ${colorScheme})"]`).forEach(el => {
// 1. Clone the given <source>
// 2. Remove the media attribute so the new <source> is unconditional
// 3. Add a "data-cloned-theme" attribute to it for future reference / removal
// 4. Prepend the new <source> to the parent <picture> so it takes precedence
const cloned = el.cloneNode();
cloned.removeAttribute('media');
cloned.setAttribute('data-cloned-theme', colorScheme);
el.parentNode.prepend(cloned);
});
}
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.