fix v7: html-bg pin + correct video class names
Two bugs in prior video-isolation fix (452ce68):
1. .htmlVideoPlayer wrong class — Jellyfin actually uses
.videoPlayerContainer + <video class="htmlvideoplayer"> (lowercase).
:has(.htmlVideoPlayer) never matched, so L1 :not(:has) was always
true — body never excluded from #000 paint, L2 (lower specificity
0,2,1) lost to L1 (0,3,1). Replaced :has() gate with :not(.arrflix
-video-active) — JS body class is reliable signal.
2. html background-color stayed transparent on details/video pages
despite 5 stylesheet rules saying #000 !important. Headless Chrome
reported computed bg as rgba(0,0,0,0) — root canvas propagation
bug or cascade quirk. Fix: JS shim sets inline style on
<html> with !important. Inline styles win against any stylesheet.
Result: html paints #000 (so letterbox bars are black not white),
body transparent during playback (L2 wins on equal specificity via
source order), videoPlayerContainer + <video> transparent → frames
visible. Off-video: body opaque #000 (L1 fires).
Verified DOM probe: html bg rgb(0,0,0), body rgba(0,0,0,0) when
arrflix-video-active. Both flip when class removed.
This commit is contained in:
parent
452ce68d7a
commit
4f13db63f9
3 changed files with 21 additions and 18 deletions
|
|
@ -53,13 +53,13 @@ CSS = (
|
|||
".arrflix-nav{text-transform:uppercase;letter-spacing:.08em;font-weight:600;padding:0 .9em;color:#fff!important;text-decoration:none;display:inline-flex;align-items:center;height:100%;font-size:.85em;transition:color .18s ease,text-shadow .18s ease,font-weight .18s ease}\n"
|
||||
".arrflix-nav:hover{color:#E50914!important}\n"
|
||||
".arrflix-nav.active{color:#E50914!important;font-weight:700;text-shadow:0 0 12px rgba(229,9,20,0.55),0 0 24px rgba(229,9,20,0.25)}\n"
|
||||
"/* Pure-black background — L1: scope rules to non-video pages so they self-disable when player mounts. Skips when .htmlVideoPlayer or #videoOsdPage is in the DOM. Doc 30 lesson — recurring black-screen-over-video bug class. */\n"
|
||||
"html,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)),body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .backgroundContainer,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .skinBody,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .mainAnimatedPage,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .mainAnimatedPages,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .pageContainer,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) #reactRoot{background-color:#000!important}\n"
|
||||
"body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .backgroundContainer.withBackdrop{background-color:rgba(0,0,0,.86)!important}\n"
|
||||
"/* Video isolation L2: high-specificity transparent override gated by JS-toggled body.arrflix-video-active. Beats any ancestor opaque-bg rule (specificity 0,3,2 plus tag) by chaining 2 body classes + the wrapper class. */\n"
|
||||
"body.arrflix-themed.arrflix-video-active,body.arrflix-themed.arrflix-video-active .backgroundContainer,body.arrflix-themed.arrflix-video-active .skinBody,body.arrflix-themed.arrflix-video-active .mainAnimatedPage,body.arrflix-themed.arrflix-video-active .mainAnimatedPages,body.arrflix-themed.arrflix-video-active .pageContainer,body.arrflix-themed.arrflix-video-active #reactRoot,body.arrflix-themed.arrflix-video-active .videoPlayerContainer,body.arrflix-themed.arrflix-video-active .videoPlayerContainer-onTop,body.arrflix-themed.arrflix-video-active #videoOsdPage,body.arrflix-themed.arrflix-video-active #videoOsdPage .pageContainer,body.arrflix-themed.arrflix-video-active #videoOsdPage .mainAnimatedPage,body.arrflix-themed.arrflix-video-active #videoOsdPage .layout-desktop,body.arrflix-themed.arrflix-video-active .libraryPage,body.arrflix-themed.arrflix-video-active .htmlVideoPlayer{background-color:transparent!important;background:transparent!important;background-image:none!important}\n"
|
||||
"/* Pure-black background — L1: gated by :not(.arrflix-video-active). Self-disables when JS sets body.arrflix-video-active. Doc 30 lesson — recurring black-screen-over-video bug class. */\n"
|
||||
"html,body.arrflix-themed:not(.arrflix-video-active),body.arrflix-themed:not(.arrflix-video-active) .backgroundContainer,body.arrflix-themed:not(.arrflix-video-active) .skinBody,body.arrflix-themed:not(.arrflix-video-active) .mainAnimatedPage,body.arrflix-themed:not(.arrflix-video-active) .mainAnimatedPages,body.arrflix-themed:not(.arrflix-video-active) .pageContainer,body.arrflix-themed:not(.arrflix-video-active) #reactRoot{background-color:#000!important}\n"
|
||||
"body.arrflix-themed:not(.arrflix-video-active) .backgroundContainer.withBackdrop{background-color:rgba(0,0,0,.86)!important}\n"
|
||||
"/* Video isolation L2: when arrflix-video-active is set, ancestors become transparent so <video> renders unobscured. html stays #000 from the rule above so letterbox shows black. videoPlayerContainer (the actual Jellyfin wrapper, NOT .htmlVideoPlayer) + child video.htmlvideoplayer covered. */\n"
|
||||
"body.arrflix-themed.arrflix-video-active,body.arrflix-themed.arrflix-video-active .backgroundContainer,body.arrflix-themed.arrflix-video-active .skinBody,body.arrflix-themed.arrflix-video-active .mainAnimatedPage,body.arrflix-themed.arrflix-video-active .mainAnimatedPages,body.arrflix-themed.arrflix-video-active .pageContainer,body.arrflix-themed.arrflix-video-active #reactRoot,body.arrflix-themed.arrflix-video-active .videoPlayerContainer,body.arrflix-themed.arrflix-video-active .videoPlayerContainer-onTop,body.arrflix-themed.arrflix-video-active #videoOsdPage,body.arrflix-themed.arrflix-video-active #videoOsdPage .pageContainer,body.arrflix-themed.arrflix-video-active #videoOsdPage .mainAnimatedPage,body.arrflix-themed.arrflix-video-active #videoOsdPage .layout-desktop,body.arrflix-themed.arrflix-video-active .libraryPage,body.arrflix-themed.arrflix-video-active video.htmlvideoplayer{background-color:transparent!important;background:transparent!important;background-image:none!important}\n"
|
||||
"/* Video element on top of all stacking contexts during playback. */\n"
|
||||
"body.arrflix-themed.arrflix-video-active video.htmlvideoplayer,body.arrflix-themed.arrflix-video-active .htmlVideoPlayer video,body.arrflix-themed.arrflix-video-active .htmlVideoPlayer{z-index:9999!important;isolation:isolate}\n"
|
||||
"body.arrflix-themed.arrflix-video-active video.htmlvideoplayer,body.arrflix-themed.arrflix-video-active .videoPlayerContainer{z-index:9999!important;isolation:isolate}\n"
|
||||
"/* Search input: replace stock cyan focus ring (jellyfin-web/themes/dark/theme.css:262-272) with a borderless slab + red underline on focus, true to the Cineplex/Netflix accent */\n"
|
||||
"body.arrflix-themed .searchFields .emby-input,body.arrflix-themed input.searchfields-txtSearch,body.arrflix-themed #searchTextInput{background:#141414!important;border:0!important;border-bottom:2px solid transparent!important;border-radius:2px!important;color:#fff!important;transition:border-color .18s ease,box-shadow .18s ease,background-color .18s ease;padding:.55em .8em!important}\n"
|
||||
"body.arrflix-themed .searchFields .emby-input::placeholder,body.arrflix-themed input.searchfields-txtSearch::placeholder,body.arrflix-themed #searchTextInput::placeholder{color:rgba(255,255,255,.4);letter-spacing:.02em}\n"
|
||||
|
|
@ -128,6 +128,7 @@ JS = """
|
|||
Array.prototype.forEach.call(document.querySelectorAll('[data-arrflix-nav=\"series\"]'),function(n){ n.classList.toggle('active',seriesMatch); });
|
||||
}
|
||||
function start(){
|
||||
try{ document.documentElement.style.setProperty('background-color','#000','important'); }catch(e){}
|
||||
relayoutHeader();
|
||||
try{ new MutationObserver(relayoutHeader).observe(document.body,{childList:true,subtree:true}); }catch(e){}
|
||||
window.addEventListener('hashchange', relayoutHeader);
|
||||
|
|
|
|||
|
|
@ -259,13 +259,13 @@ body.arrflix-video-active:not(:has(#loginPage:not(.hide))) .skinHeader,body.arrf
|
|||
.arrflix-nav{text-transform:uppercase;letter-spacing:.08em;font-weight:600;padding:0 .9em;color:#fff!important;text-decoration:none;display:inline-flex;align-items:center;height:100%;font-size:.85em;transition:color .18s ease,text-shadow .18s ease,font-weight .18s ease}
|
||||
.arrflix-nav:hover{color:#E50914!important}
|
||||
.arrflix-nav.active{color:#E50914!important;font-weight:700;text-shadow:0 0 12px rgba(229,9,20,0.55),0 0 24px rgba(229,9,20,0.25)}
|
||||
/* Pure-black background — L1: scope rules to non-video pages so they self-disable when player mounts. Skips when .htmlVideoPlayer or #videoOsdPage is in the DOM. Doc 30 lesson — recurring black-screen-over-video bug class. */
|
||||
html,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)),body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .backgroundContainer,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .skinBody,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .mainAnimatedPage,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .mainAnimatedPages,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .pageContainer,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) #reactRoot{background-color:#000!important}
|
||||
body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .backgroundContainer.withBackdrop{background-color:rgba(0,0,0,.86)!important}
|
||||
/* Video isolation L2: high-specificity transparent override gated by JS-toggled body.arrflix-video-active. Beats any ancestor opaque-bg rule (specificity 0,3,2 plus tag) by chaining 2 body classes + the wrapper class. */
|
||||
body.arrflix-themed.arrflix-video-active,body.arrflix-themed.arrflix-video-active .backgroundContainer,body.arrflix-themed.arrflix-video-active .skinBody,body.arrflix-themed.arrflix-video-active .mainAnimatedPage,body.arrflix-themed.arrflix-video-active .mainAnimatedPages,body.arrflix-themed.arrflix-video-active .pageContainer,body.arrflix-themed.arrflix-video-active #reactRoot,body.arrflix-themed.arrflix-video-active .videoPlayerContainer,body.arrflix-themed.arrflix-video-active .videoPlayerContainer-onTop,body.arrflix-themed.arrflix-video-active #videoOsdPage,body.arrflix-themed.arrflix-video-active #videoOsdPage .pageContainer,body.arrflix-themed.arrflix-video-active #videoOsdPage .mainAnimatedPage,body.arrflix-themed.arrflix-video-active #videoOsdPage .layout-desktop,body.arrflix-themed.arrflix-video-active .libraryPage,body.arrflix-themed.arrflix-video-active .htmlVideoPlayer{background-color:transparent!important;background:transparent!important;background-image:none!important}
|
||||
/* Pure-black background — L1: gated by :not(.arrflix-video-active). Self-disables when JS sets body.arrflix-video-active. Doc 30 lesson — recurring black-screen-over-video bug class. */
|
||||
html,body.arrflix-themed:not(.arrflix-video-active),body.arrflix-themed:not(.arrflix-video-active) .backgroundContainer,body.arrflix-themed:not(.arrflix-video-active) .skinBody,body.arrflix-themed:not(.arrflix-video-active) .mainAnimatedPage,body.arrflix-themed:not(.arrflix-video-active) .mainAnimatedPages,body.arrflix-themed:not(.arrflix-video-active) .pageContainer,body.arrflix-themed:not(.arrflix-video-active) #reactRoot{background-color:#000!important}
|
||||
body.arrflix-themed:not(.arrflix-video-active) .backgroundContainer.withBackdrop{background-color:rgba(0,0,0,.86)!important}
|
||||
/* Video isolation L2: when arrflix-video-active is set, ancestors become transparent so <video> renders unobscured. html stays #000 from the rule above so letterbox shows black. videoPlayerContainer (the actual Jellyfin wrapper, NOT .htmlVideoPlayer) + child video.htmlvideoplayer covered. */
|
||||
body.arrflix-themed.arrflix-video-active,body.arrflix-themed.arrflix-video-active .backgroundContainer,body.arrflix-themed.arrflix-video-active .skinBody,body.arrflix-themed.arrflix-video-active .mainAnimatedPage,body.arrflix-themed.arrflix-video-active .mainAnimatedPages,body.arrflix-themed.arrflix-video-active .pageContainer,body.arrflix-themed.arrflix-video-active #reactRoot,body.arrflix-themed.arrflix-video-active .videoPlayerContainer,body.arrflix-themed.arrflix-video-active .videoPlayerContainer-onTop,body.arrflix-themed.arrflix-video-active #videoOsdPage,body.arrflix-themed.arrflix-video-active #videoOsdPage .pageContainer,body.arrflix-themed.arrflix-video-active #videoOsdPage .mainAnimatedPage,body.arrflix-themed.arrflix-video-active #videoOsdPage .layout-desktop,body.arrflix-themed.arrflix-video-active .libraryPage,body.arrflix-themed.arrflix-video-active video.htmlvideoplayer{background-color:transparent!important;background:transparent!important;background-image:none!important}
|
||||
/* Video element on top of all stacking contexts during playback. */
|
||||
body.arrflix-themed.arrflix-video-active video.htmlvideoplayer,body.arrflix-themed.arrflix-video-active .htmlVideoPlayer video,body.arrflix-themed.arrflix-video-active .htmlVideoPlayer{z-index:9999!important;isolation:isolate}
|
||||
body.arrflix-themed.arrflix-video-active video.htmlvideoplayer,body.arrflix-themed.arrflix-video-active .videoPlayerContainer{z-index:9999!important;isolation:isolate}
|
||||
/* Search input: replace stock cyan focus ring (jellyfin-web/themes/dark/theme.css:262-272) with a borderless slab + red underline on focus, true to the Cineplex/Netflix accent */
|
||||
body.arrflix-themed .searchFields .emby-input,body.arrflix-themed input.searchfields-txtSearch,body.arrflix-themed #searchTextInput{background:#141414!important;border:0!important;border-bottom:2px solid transparent!important;border-radius:2px!important;color:#fff!important;transition:border-color .18s ease,box-shadow .18s ease,background-color .18s ease;padding:.55em .8em!important}
|
||||
body.arrflix-themed .searchFields .emby-input::placeholder,body.arrflix-themed input.searchfields-txtSearch::placeholder,body.arrflix-themed #searchTextInput::placeholder{color:rgba(255,255,255,.4);letter-spacing:.02em}
|
||||
|
|
@ -332,6 +332,7 @@ body.arrflix-themed .searchFields .emby-input:focus,body.arrflix-themed input.se
|
|||
Array.prototype.forEach.call(document.querySelectorAll('[data-arrflix-nav="series"]'),function(n){ n.classList.toggle('active',seriesMatch); });
|
||||
}
|
||||
function start(){
|
||||
try{ document.documentElement.style.setProperty('background-color','#000','important'); }catch(e){}
|
||||
relayoutHeader();
|
||||
try{ new MutationObserver(relayoutHeader).observe(document.body,{childList:true,subtree:true}); }catch(e){}
|
||||
window.addEventListener('hashchange', relayoutHeader);
|
||||
|
|
|
|||
|
|
@ -259,13 +259,13 @@ body.arrflix-video-active:not(:has(#loginPage:not(.hide))) .skinHeader,body.arrf
|
|||
.arrflix-nav{text-transform:uppercase;letter-spacing:.08em;font-weight:600;padding:0 .9em;color:#fff!important;text-decoration:none;display:inline-flex;align-items:center;height:100%;font-size:.85em;transition:color .18s ease,text-shadow .18s ease,font-weight .18s ease}
|
||||
.arrflix-nav:hover{color:#E50914!important}
|
||||
.arrflix-nav.active{color:#E50914!important;font-weight:700;text-shadow:0 0 12px rgba(229,9,20,0.55),0 0 24px rgba(229,9,20,0.25)}
|
||||
/* Pure-black background — L1: scope rules to non-video pages so they self-disable when player mounts. Skips when .htmlVideoPlayer or #videoOsdPage is in the DOM. Doc 30 lesson — recurring black-screen-over-video bug class. */
|
||||
html,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)),body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .backgroundContainer,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .skinBody,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .mainAnimatedPage,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .mainAnimatedPages,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .pageContainer,body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) #reactRoot{background-color:#000!important}
|
||||
body.arrflix-themed:not(:has(.htmlVideoPlayer)):not(:has(#videoOsdPage)) .backgroundContainer.withBackdrop{background-color:rgba(0,0,0,.86)!important}
|
||||
/* Video isolation L2: high-specificity transparent override gated by JS-toggled body.arrflix-video-active. Beats any ancestor opaque-bg rule (specificity 0,3,2 plus tag) by chaining 2 body classes + the wrapper class. */
|
||||
body.arrflix-themed.arrflix-video-active,body.arrflix-themed.arrflix-video-active .backgroundContainer,body.arrflix-themed.arrflix-video-active .skinBody,body.arrflix-themed.arrflix-video-active .mainAnimatedPage,body.arrflix-themed.arrflix-video-active .mainAnimatedPages,body.arrflix-themed.arrflix-video-active .pageContainer,body.arrflix-themed.arrflix-video-active #reactRoot,body.arrflix-themed.arrflix-video-active .videoPlayerContainer,body.arrflix-themed.arrflix-video-active .videoPlayerContainer-onTop,body.arrflix-themed.arrflix-video-active #videoOsdPage,body.arrflix-themed.arrflix-video-active #videoOsdPage .pageContainer,body.arrflix-themed.arrflix-video-active #videoOsdPage .mainAnimatedPage,body.arrflix-themed.arrflix-video-active #videoOsdPage .layout-desktop,body.arrflix-themed.arrflix-video-active .libraryPage,body.arrflix-themed.arrflix-video-active .htmlVideoPlayer{background-color:transparent!important;background:transparent!important;background-image:none!important}
|
||||
/* Pure-black background — L1: gated by :not(.arrflix-video-active). Self-disables when JS sets body.arrflix-video-active. Doc 30 lesson — recurring black-screen-over-video bug class. */
|
||||
html,body.arrflix-themed:not(.arrflix-video-active),body.arrflix-themed:not(.arrflix-video-active) .backgroundContainer,body.arrflix-themed:not(.arrflix-video-active) .skinBody,body.arrflix-themed:not(.arrflix-video-active) .mainAnimatedPage,body.arrflix-themed:not(.arrflix-video-active) .mainAnimatedPages,body.arrflix-themed:not(.arrflix-video-active) .pageContainer,body.arrflix-themed:not(.arrflix-video-active) #reactRoot{background-color:#000!important}
|
||||
body.arrflix-themed:not(.arrflix-video-active) .backgroundContainer.withBackdrop{background-color:rgba(0,0,0,.86)!important}
|
||||
/* Video isolation L2: when arrflix-video-active is set, ancestors become transparent so <video> renders unobscured. html stays #000 from the rule above so letterbox shows black. videoPlayerContainer (the actual Jellyfin wrapper, NOT .htmlVideoPlayer) + child video.htmlvideoplayer covered. */
|
||||
body.arrflix-themed.arrflix-video-active,body.arrflix-themed.arrflix-video-active .backgroundContainer,body.arrflix-themed.arrflix-video-active .skinBody,body.arrflix-themed.arrflix-video-active .mainAnimatedPage,body.arrflix-themed.arrflix-video-active .mainAnimatedPages,body.arrflix-themed.arrflix-video-active .pageContainer,body.arrflix-themed.arrflix-video-active #reactRoot,body.arrflix-themed.arrflix-video-active .videoPlayerContainer,body.arrflix-themed.arrflix-video-active .videoPlayerContainer-onTop,body.arrflix-themed.arrflix-video-active #videoOsdPage,body.arrflix-themed.arrflix-video-active #videoOsdPage .pageContainer,body.arrflix-themed.arrflix-video-active #videoOsdPage .mainAnimatedPage,body.arrflix-themed.arrflix-video-active #videoOsdPage .layout-desktop,body.arrflix-themed.arrflix-video-active .libraryPage,body.arrflix-themed.arrflix-video-active video.htmlvideoplayer{background-color:transparent!important;background:transparent!important;background-image:none!important}
|
||||
/* Video element on top of all stacking contexts during playback. */
|
||||
body.arrflix-themed.arrflix-video-active video.htmlvideoplayer,body.arrflix-themed.arrflix-video-active .htmlVideoPlayer video,body.arrflix-themed.arrflix-video-active .htmlVideoPlayer{z-index:9999!important;isolation:isolate}
|
||||
body.arrflix-themed.arrflix-video-active video.htmlvideoplayer,body.arrflix-themed.arrflix-video-active .videoPlayerContainer{z-index:9999!important;isolation:isolate}
|
||||
/* Search input: replace stock cyan focus ring (jellyfin-web/themes/dark/theme.css:262-272) with a borderless slab + red underline on focus, true to the Cineplex/Netflix accent */
|
||||
body.arrflix-themed .searchFields .emby-input,body.arrflix-themed input.searchfields-txtSearch,body.arrflix-themed #searchTextInput{background:#141414!important;border:0!important;border-bottom:2px solid transparent!important;border-radius:2px!important;color:#fff!important;transition:border-color .18s ease,box-shadow .18s ease,background-color .18s ease;padding:.55em .8em!important}
|
||||
body.arrflix-themed .searchFields .emby-input::placeholder,body.arrflix-themed input.searchfields-txtSearch::placeholder,body.arrflix-themed #searchTextInput::placeholder{color:rgba(255,255,255,.4);letter-spacing:.02em}
|
||||
|
|
@ -332,6 +332,7 @@ body.arrflix-themed .searchFields .emby-input:focus,body.arrflix-themed input.se
|
|||
Array.prototype.forEach.call(document.querySelectorAll('[data-arrflix-nav="series"]'),function(n){ n.classList.toggle('active',seriesMatch); });
|
||||
}
|
||||
function start(){
|
||||
try{ document.documentElement.style.setProperty('background-color','#000','important'); }catch(e){}
|
||||
relayoutHeader();
|
||||
try{ new MutationObserver(relayoutHeader).observe(document.body,{childList:true,subtree:true}); }catch(e){}
|
||||
window.addEventListener('hashchange', relayoutHeader);
|
||||
|
|
|
|||
Loading…
Reference in a new issue