From 082120b70b28694a4143d7b3c74825aa5a5cd153 Mon Sep 17 00:00:00 2001 From: CodeDevMLH <145071728+CodeDevMLH@users.noreply.github.com> Date: Tue, 24 Feb 2026 23:58:08 +0100 Subject: [PATCH] Refactor seasonal CSS animations: update positioning and transform properties for autumn, carnival, cherry blossom, christmas, resurrection, and snowflakes styles --- Jellyfin.Plugin.Seasonals/Web/autumn.css | 16 ++++++++------ Jellyfin.Plugin.Seasonals/Web/carnival.css | 8 +++---- .../Web/cherryblossom.css | 9 ++++---- Jellyfin.Plugin.Seasonals/Web/christmas.css | 15 ++++++------- .../Web/resurrection.css | 22 +++++++++++++------ Jellyfin.Plugin.Seasonals/Web/resurrection.js | 13 ++++++++--- Jellyfin.Plugin.Seasonals/Web/snowflakes.css | 14 ++++++------ 7 files changed, 57 insertions(+), 40 deletions(-) diff --git a/Jellyfin.Plugin.Seasonals/Web/autumn.css b/Jellyfin.Plugin.Seasonals/Web/autumn.css index 4626341..ae67665 100644 --- a/Jellyfin.Plugin.Seasonals/Web/autumn.css +++ b/Jellyfin.Plugin.Seasonals/Web/autumn.css @@ -14,7 +14,9 @@ .leaf { position: fixed; z-index: 15; - top: -10%; + top: 0; + will-change: transform; + translate: 0 -10vh; font-size: 1em; color: #fff; font-family: Arial, sans-serif; @@ -41,30 +43,30 @@ @-webkit-keyframes leaf-fall { 0% { - top: -10%; + translate: 0 -10vh; } 100% { - top: 110%; + translate: 0 100vh; } } @keyframes leaf-fall { 0% { - top: -10%; + translate: 0 -10vh; } 100% { - top: 110%; + translate: 0 100vh; } } @-webkit-keyframes leaf-shake { 0%, 100% { - -webkit-transform: translateX(0) rotate(var(--rotate-start, -20deg)); + transform: translateX(0) rotate(var(--rotate-start, -20deg)); } 50% { - -webkit-transform: translateX(80px) rotate(var(--rotate-end, 20deg)); + transform: translateX(80px) rotate(var(--rotate-end, 20deg)); } } diff --git a/Jellyfin.Plugin.Seasonals/Web/carnival.css b/Jellyfin.Plugin.Seasonals/Web/carnival.css index 41e62ed..bc8747b 100644 --- a/Jellyfin.Plugin.Seasonals/Web/carnival.css +++ b/Jellyfin.Plugin.Seasonals/Web/carnival.css @@ -15,7 +15,7 @@ .carnival-wrapper { position: fixed; z-index: 15; - top: -20px; + top: 0; will-change: transform; animation-name: carnival-fall; animation-timing-function: linear; @@ -34,7 +34,7 @@ .carnival-confetti { width: 8px; height: 16px; - background-color: #f0f; + background-color: rgb(0, 0, 0); will-change: transform; animation-name: carnival-flutter; animation-timing-function: linear; @@ -60,10 +60,10 @@ @keyframes carnival-fall { 0% { - transform: translateY(0); + transform: translate3d(0, -10vh, 0); } 100% { - transform: translateY(120vh); + transform: translate3d(0, 110vh, 0); } } diff --git a/Jellyfin.Plugin.Seasonals/Web/cherryblossom.css b/Jellyfin.Plugin.Seasonals/Web/cherryblossom.css index 8bea8e5..2be9647 100644 --- a/Jellyfin.Plugin.Seasonals/Web/cherryblossom.css +++ b/Jellyfin.Plugin.Seasonals/Web/cherryblossom.css @@ -14,14 +14,15 @@ /* Petals */ .cherryblossom-petal { position: fixed; - top: -20px; + top: 0; z-index: 1005; width: 15px; height: 10px; background-color: #ffc0cb; border-radius: 15px 0px 15px 0px; - will-change: transform, top; + will-change: transform; + translate: 0 -10vh; animation-name: cherryblossom-fall, cherryblossom-sway; animation-timing-function: linear, ease-in-out; animation-iteration-count: infinite, infinite; @@ -45,8 +46,8 @@ } @keyframes cherryblossom-fall { - 0% { top: -10%; } - 100% { top: 110%; } + 0% { translate: 0 -10vh; } + 100% { translate: 0 110vh; } } @keyframes cherryblossom-sway { diff --git a/Jellyfin.Plugin.Seasonals/Web/christmas.css b/Jellyfin.Plugin.Seasonals/Web/christmas.css index 747939a..33f283c 100644 --- a/Jellyfin.Plugin.Seasonals/Web/christmas.css +++ b/Jellyfin.Plugin.Seasonals/Web/christmas.css @@ -14,7 +14,9 @@ .christmas { position: fixed; z-index: 15; - top: -10%; + top: 0; + will-change: transform; + translate: 0 -10vh; font-size: 1em; color: #fff; font-family: Arial, sans-serif; @@ -34,11 +36,11 @@ @-webkit-keyframes christmas-fall { 0% { - top: -10%; + translate: 0 -10vh; } 100% { - top: 110%; + translate: 0 110vh; } } @@ -46,28 +48,25 @@ 0%, 100% { - -webkit-transform: translateX(0); transform: translateX(0); } 50% { - -webkit-transform: translateX(80px); transform: translateX(80px); } } @keyframes christmas-fall { 0% { - top: -10%; + translate: 0 -10vh; } 100% { - top: 110%; + translate: 0 110vh; } } @keyframes christmas-shake { - 0%, 100% { transform: translateX(0); diff --git a/Jellyfin.Plugin.Seasonals/Web/resurrection.css b/Jellyfin.Plugin.Seasonals/Web/resurrection.css index c33084d..3ffdcc5 100644 --- a/Jellyfin.Plugin.Seasonals/Web/resurrection.css +++ b/Jellyfin.Plugin.Seasonals/Web/resurrection.css @@ -14,14 +14,22 @@ .resurrection-symbol { position: fixed; z-index: 15; - top: -15%; + top: 0; + translate: 0 -15vh; user-select: none; -webkit-user-select: none; cursor: default; - animation-name: resurrection-fall, resurrection-sway; - animation-timing-function: linear, ease-in-out; - animation-iteration-count: infinite, infinite; - will-change: transform, top; + animation-name: resurrection-fall; + animation-timing-function: linear; + animation-iteration-count: infinite; + will-change: transform; +} + +.resurrection-sway-wrapper { + will-change: transform; + animation-name: resurrection-sway; + animation-timing-function: ease-in-out; + animation-iteration-count: infinite; } .resurrection-symbol img { @@ -40,11 +48,11 @@ @keyframes resurrection-fall { 0% { - top: -15%; + transform: translate3d(0, -15vh, 0); } 100% { - top: 110%; + transform: translate3d(0, 105vh, 0); } } diff --git a/Jellyfin.Plugin.Seasonals/Web/resurrection.js b/Jellyfin.Plugin.Seasonals/Web/resurrection.js index 1dd21b1..b3c1d2d 100644 --- a/Jellyfin.Plugin.Seasonals/Web/resurrection.js +++ b/Jellyfin.Plugin.Seasonals/Web/resurrection.js @@ -52,20 +52,27 @@ function createSymbol(imageSrc, leftPercent, delaySeconds) { const symbol = document.createElement('div'); symbol.className = 'resurrection-symbol'; + const swayWrapper = document.createElement('div'); + swayWrapper.className = 'resurrection-sway-wrapper'; + const img = document.createElement('img'); img.src = imageSrc; img.alt = ''; symbol.style.left = `${leftPercent}%`; - symbol.style.animationDelay = `${delaySeconds}s, -${Math.random() * 3}s`; + symbol.style.animationDelay = `${delaySeconds}s`; if (enableDifferentDuration) { const fallDuration = Math.random() * 7 + 7; const swayDuration = Math.random() * 4 + 2; - symbol.style.animationDuration = `${fallDuration}s, ${swayDuration}s`; + symbol.style.animationDuration = `${fallDuration}s`; + swayWrapper.style.animationDuration = `${swayDuration}s`; } - symbol.appendChild(img); + swayWrapper.style.animationDelay = `${Math.random() * 3}s`; + + swayWrapper.appendChild(img); + symbol.appendChild(swayWrapper); return symbol; } diff --git a/Jellyfin.Plugin.Seasonals/Web/snowflakes.css b/Jellyfin.Plugin.Seasonals/Web/snowflakes.css index 9cdad40..fd01489 100644 --- a/Jellyfin.Plugin.Seasonals/Web/snowflakes.css +++ b/Jellyfin.Plugin.Seasonals/Web/snowflakes.css @@ -14,7 +14,9 @@ .snowflake { position: fixed; z-index: 15; - top: -10%; + top: 0; + will-change: transform; + translate: 0 -10vh; font-size: 1em; color: #fff; font-family: Arial, sans-serif; @@ -34,11 +36,11 @@ @-webkit-keyframes snowflakes-fall { 0% { - top: -10%; + translate: 0 -10vh; } 100% { - top: 110%; + translate: 0 110vh; } } @@ -46,23 +48,21 @@ 0%, 100% { - -webkit-transform: translateX(0); transform: translateX(0); } 50% { - -webkit-transform: translateX(80px); transform: translateX(80px); } } @keyframes snowflakes-fall { 0% { - top: -10%; + translate: 0 -10vh; } 100% { - top: 110%; + translate: 0 110vh; } }