External embed: actually force html transparent (CSS + inline)

Previous fix set documentElement.style.background = 'transparent'
but didn't beat the global

  html, body { background: var(--bg); ... }

rule at the top of the stylesheet. --bg is #e8f4f8 (light cyan,
reads as near-white), so pixel-art transparent pixels were showing
that light cyan through instead of the host page background.

Two fixes layered:

1. CSS rule using :has() so html is targeted only when an
   embed-mode body is its descendant:

     html:has(body.embed-mode), body.embed-mode {
       background: transparent !important;
     }

   :has() is supported in all current browsers (Chrome 105+,
   Safari 15.4+, Firefox 121+). The !important flag beats the
   global var(--bg) declaration.

2. Inline override via style.setProperty('background',
   'transparent', 'important') on both documentElement and body
   at the top of bootEmbedViewer. Inline + !important = highest
   specificity possible, so this guarantees transparency even on
   browsers/edge cases where :has() doesn't trigger immediately
   on dynamic class change.

Net effect: from <html> → <body> → #embedRoot → .embedStage →
.designObjectFitWrap → renderer's pixel-art box → canvas, every
layer is transparent. Host backgrounds (color, image, gradient)
now actually show through transparent pixel-art cells.
This commit is contained in:
thePR0M3TH3AN committed 2026-06-01 09:40:12 -04:00
1 parent 34fefe6d79
commit c3a8aa9946
1 file changed
+19 -5
+19 -5
View File
@@ -585,7 +585,16 @@
host theme (light, dark, branded). Each chip carries its own
semi-opaque dark background + blur so it stays readable
regardless of what's behind. */
body.embed-mode { margin: 0; padding: 0; overflow: hidden; background: transparent; }
/* Force transparency from <html> down so embeds can sit over
any host background (color, image, gradient). The global
`html, body { background: var(--bg) }` rule at the top of
this file would otherwise paint the html element white in
embed mode, killing host-show-through. The :has() selector
targets html only when an embed-mode body is its descendant. */
html:has(body.embed-mode), body.embed-mode {
background: transparent !important;
}
body.embed-mode { margin: 0; padding: 0; overflow: hidden; }
body.embed-mode > :not(#embedRoot) { display: none !important; }
#embedRoot {
position: fixed; inset: 0;
@@ -21536,10 +21545,15 @@
// private sources refuse with a placeholder + Open in Artstr.
async function bootEmbedViewer(route) {
document.body.classList.add('embed-mode');
// Force the <html> root transparent too — body alone leaves
// the browser's default white element behind, which kills
// host-bg-show-through for transparent pixel art etc.
document.documentElement.style.background = 'transparent';
// Force the <html> + <body> backgrounds transparent with
// !important so the global `html, body { background:
// var(--bg) }` rule near the top of this file (which would
// otherwise paint the iframe document with the light theme's
// #e8f4f8) doesn't bleed through transparent pixel art. The
// CSS :has()-rule we set covers modern browsers; this inline
// is the belt-and-suspenders for any specificity edge case.
document.documentElement.style.setProperty('background', 'transparent', 'important');
document.body.style.setProperty('background', 'transparent', 'important');
const root = _ensureEmbedRoot();
_setEmbedStatus(root, 'loading', '⟳ Loading Artstr design…');
const retry = () => bootEmbedViewer(route);