diff --git a/assets/css/core/components-ext.css b/assets/css/core/components-ext.css index f4e17a0f..832dc94f 100644 --- a/assets/css/core/components-ext.css +++ b/assets/css/core/components-ext.css @@ -541,6 +541,35 @@ } } +/* Runtime broad ripple (.aksrt-wave injected into .but/.btn). + * MUST stay out of flow — missing absolute made header CTA grow on click. */ +.aksrt-wave { + position: absolute !important; + border-radius: 50%; + background: rgba(255, 255, 255, 0.35); + pointer-events: none !important; + z-index: 1; + transform: scale(0); + animation: aksrtWaveRipple 0.6s ease-out forwards; +} + +@keyframes aksrtWaveRipple { + to { + transform: scale(1); + opacity: 0; + } +} + +/* Header CTA chips: never host layout-affecting ripple children */ +.navbar-top a.navbar-cta, +.navbar-top a.newadd-btns, +.navbar-top a.payvip-icon.navbar-cta, +.navbar-top .navbar-but .but, +.navbar-top .navbar-vip a.but, +.nowave { + overflow: hidden; +} + /* ============================================================ * 10. 模态框堆叠动画 — 父模态缩小 * ============================================================ */ diff --git a/assets/css/frontend/nav.css b/assets/css/frontend/nav.css index b73ad2df..d5014a1b 100644 --- a/assets/css/frontend/nav.css +++ b/assets/css/frontend/nav.css @@ -636,3 +636,24 @@ body.dark-theme .navbar-but-cluster .toggle-theme .theme-icon-sun { display: none !important; } } + +/* Absolute-size CTA chips: ignore injected .aksrt-wave for layout */ +.navbar-top a.navbar-cta, +.navbar-top a.newadd-btns.navbar-cta, +.navbar-top a.navbar-newposts.navbar-cta, +.navbar-top a.payvip-icon.navbar-cta, +.navbar-top .navbar-but .but, +.navbar-top .navbar-form.navbar-but a.but, +.navbar-top .navbar-form.navbar-vip a.but { + position: relative !important; + overflow: hidden !important; + flex: 0 0 auto !important; +} +.navbar-top a.navbar-cta > .aksrt-wave, +.navbar-top a.but > .aksrt-wave, +.navbar-top .but > .aksrt-wave { + position: absolute !important; + pointer-events: none !important; + margin: 0 !important; + flex: none !important; +} diff --git a/assets/js/aksrt-runtime.js b/assets/js/aksrt-runtime.js index de10e024..0360c8b7 100644 --- a/assets/js/aksrt-runtime.js +++ b/assets/js/aksrt-runtime.js @@ -796,6 +796,10 @@ document.addEventListener('click', function (e) { var target = e.target.closest(RIPPLE_SELECTORS); if (!target) return; + // Markup opt-out (header publish uses class="nowave") + nav CTA chips + if (target.classList.contains('nowave') || target.closest('.nowave')) return; + if (target.classList.contains('navbar-cta') || target.closest('.navbar-cta')) return; + if (target.closest('.navbar-top .navbar-but, .navbar-top .navbar-vip, .navbar-but-cluster')) return; if (target.querySelector('.aksrt-wave')) return; var rect = target.getBoundingClientRect(); @@ -805,13 +809,18 @@ var wave = document.createElement('span'); wave.className = 'aksrt-wave'; - wave.style.cssText = 'width:' + size + 'px;height:' + size + 'px;left:' + x + 'px;top:' + y + 'px;'; + // Must be absolute — without it the huge span expands the button box ("变长"). + wave.style.cssText = 'position:absolute;pointer-events:none;border-radius:50%;background:rgba(255,255,255,0.35);width:' + + size + 'px;height:' + size + 'px;left:' + x + 'px;top:' + y + 'px;transform:scale(0);animation:aksrtWaveRipple .6s ease-out forwards;'; - var pos = getComputedStyle(target).position; - if (pos === 'static') target.style.position = 'relative'; + var cs = getComputedStyle(target); + if (cs.position === 'static') target.style.position = 'relative'; + if (cs.overflow === 'visible') target.style.overflow = 'hidden'; target.appendChild(wave); - setTimeout(function () { wave.remove(); }, 600); + setTimeout(function () { + if (wave.parentNode) wave.parentNode.removeChild(wave); + }, 600); }); // ══════════════════════════════════════════════════════════════