Summary
When a page does not set an explicit background color on body (relying on the UA color-scheme/canvas background or a <meta name="color-scheme" content="light dark">), the auto theme detector classifies the page as dark even when the visible page is white and the OS is in light mode. The player then applies the dark preset (white controls/waveform rgba(255,255,255,…)) on a white page and becomes invisible.
Package: @arraypress/waveform-player v1.24.0 · component: core player auto-theme detection (src/js/themes.js)
Root cause
In detectColorScheme():
function detectColorScheme() {
if (hasThemeHint("dark")) return "dark";
if (hasThemeHint("light")) return "light";
try {
const bodyBg = getComputedStyle(document.body).backgroundColor;
const brightness = perceivedBrightness(bodyBg);
if (brightness !== null) {
if (brightness > 128) return "light";
if (brightness < 128) return "dark"; // ← always taken for transparent bg
}
} catch (e) {}
if (window.matchMedia) { /* prefers-color-scheme … never reached */ }
return "dark";
}
perceivedBrightness():
function perceivedBrightness(color) {
const rgb = typeof color === "string" ? color.match(/\d+/g) : null;
if (!rgb || rgb.length < 3) return null;
const [r, g, b] = rgb.map(Number); // alpha digit ignored
return (r * 299 + g * 587 + b * 114) / 1e3;
}
With no background set, getComputedStyle(document.body).backgroundColor returns rgba(0, 0, 0, 0). The regex yields [0,0,0,0]; the alpha channel is ignored, so brightness = (0·299+0·587+0·114)/1000 = 0, which is < 128 → "dark". The prefers-color-scheme: light branch is never reached.
It is also sticky: _scheme is resolved once at construction, and re-detection (refreshTheme()) only runs from a MutationObserver (class/data-theme/data-color-scheme/style attribute changes) and a matchMedia change event, so switching the OS theme doesn't fix it either.
Repro
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="color-scheme" content="light dark">
<title>Repro</title>
<link rel="stylesheet" href="https://unpkg.com/@arraypress/waveform-player/dist/waveform-player.css">
<script src="https://unpkg.com/@arraypress/waveform-player/dist/waveform-player.min.js"></script>
</head>
<body>
<div data-waveform-player data-src="https://example.com/track.mp3"></div>
</body>
</html>
Open with the OS in light mode. The player renders with white controls on a white page (invisible). Adding body { background: #fff } (so the computed background is rgb(255,255,255)) makes it correctly detect "light".
Expected
- A transparent (fully invisible, alpha 0) background should be treated as "unknown" so detection falls through to
prefers-color-scheme.
perceivedBrightness() should parse rgb()/rgba() properly (including the alpha channel) instead of picking up the alpha digit as a 4th match and ignoring it.
Suggested fix
function perceivedBrightness(color) {
if (typeof color !== "string") return null;
const m = color.match(/rgba?\(([\d.]+)[,\s]+([\d.]+)[,\s]+([\d.]+)(?:[,\s]+([\d.]+))?/);
if (!m) return null;
const [, r, g, b, a = 1] = m.map(Number);
if (a <= 0) return null; // transparent → unknown, defer to prefers-color-scheme
return (r * 299 + g * 587 + b * 114) / 1e3;
}
Environment
- Browser: Firefox (incl. Firefox Dev), Chromium
- OS: Linux
- Version: 1.24.0 (also reproduced against the unpkg CDN build)
Workarounds
- Set an explicit
background on body for both schemes (e.g. #fff / dark).
- Pass
data-color-preset="light" / data-color-preset="dark" to opt out of auto-detection.
Summary
When a page does not set an explicit background color on
body(relying on the UAcolor-scheme/canvasbackground or a<meta name="color-scheme" content="light dark">), the auto theme detector classifies the page as dark even when the visible page is white and the OS is in light mode. The player then applies the dark preset (white controls/waveformrgba(255,255,255,…)) on a white page and becomes invisible.Package:
@arraypress/waveform-playerv1.24.0 · component: core player auto-theme detection (src/js/themes.js)Root cause
In
detectColorScheme():perceivedBrightness():With no background set,
getComputedStyle(document.body).backgroundColorreturnsrgba(0, 0, 0, 0). The regex yields[0,0,0,0]; the alpha channel is ignored, so brightness =(0·299+0·587+0·114)/1000 = 0, which is< 128→"dark". Theprefers-color-scheme: lightbranch is never reached.It is also sticky:
_schemeis resolved once at construction, and re-detection (refreshTheme()) only runs from a MutationObserver (class/data-theme/data-color-scheme/styleattribute changes) and a matchMedia change event, so switching the OS theme doesn't fix it either.Repro
Open with the OS in light mode. The player renders with white controls on a white page (invisible). Adding
body { background: #fff }(so the computed background isrgb(255,255,255)) makes it correctly detect "light".Expected
prefers-color-scheme.perceivedBrightness()should parse rgb()/rgba() properly (including the alpha channel) instead of picking up the alpha digit as a 4th match and ignoring it.Suggested fix
Environment
Workarounds
backgroundonbodyfor both schemes (e.g.#fff/ dark).data-color-preset="light"/data-color-preset="dark"to opt out of auto-detection.