Widget:ScrollToTopSidebar: Difference between revisions
((by SublimeText.Mediawiker)) |
(Scroll-to-top button deepens its background with reading progress through the content column) |
||
| Line 1: | Line 1: | ||
<style> | |||
/* Background deepens with reading progress through the content column (--stt-a, set below). */ | |||
#scrollToTop { | |||
background: rgba(186, 27, 29, var(--stt-a, .08)); | |||
transition: background-color .15s linear; | |||
} | |||
#scrollToTop:hover { | |||
background: rgba(186, 27, 29, calc(var(--stt-a, .08) + .15)); | |||
} | |||
</style> | |||
<script> | <script> | ||
// Create the scroll to top button | // Create the scroll to top button | ||
| Line 21: | Line 31: | ||
}); | }); | ||
// | // Progress is measured through the main content column beside the sidebar | ||
// (the .col-md-9 sibling), falling back to the whole page. | |||
const sttRow = container.closest('.row'); | |||
const sttContent = (sttRow && sttRow.querySelector(':scope > .col-md-9')) || document.documentElement; | |||
const STT_MIN = 0.08, STT_MAX = 0.55; | |||
function sttProgress() { | |||
const rect = sttContent.getBoundingClientRect(); | |||
const range = rect.height - window.innerHeight; | |||
if (range <= 0) return 1; | |||
return Math.min(1, Math.max(0, -rect.top / range)); | |||
} | |||
// Show/hide the button and deepen its background with scroll position | |||
let sttTicking = false; | |||
function sttUpdate() { | |||
sttTicking = false; | |||
if (window.pageYOffset > 300) { | if (window.pageYOffset > 300) { | ||
scrollToTopButtonSb.style.display = 'block'; | scrollToTopButtonSb.style.display = 'block'; | ||
scrollToTopButtonSb.style.setProperty('--stt-a', (STT_MIN + (STT_MAX - STT_MIN) * sttProgress()).toFixed(3)); | |||
} else { | } else { | ||
scrollToTopButtonSb.style.display = 'none'; | scrollToTopButtonSb.style.display = 'none'; | ||
} | } | ||
}); | } | ||
window.addEventListener('scroll', () => { | |||
if (!sttTicking) { | |||
sttTicking = true; | |||
window.requestAnimationFrame(sttUpdate); | |||
} | |||
}, { passive: true }); | |||
// Scroll to top when the button is clicked | // Scroll to top when the button is clicked | ||
Revision as of 18:15, 30 September 2026
<style> /* Background deepens with reading progress through the content column (--stt-a, set below). */
- scrollToTop {
background: rgba(186, 27, 29, var(--stt-a, .08)); transition: background-color .15s linear; }
- scrollToTop:hover {
background: rgba(186, 27, 29, calc(var(--stt-a, .08) + .15)); } </style> <script> // Create the scroll to top button const scrollToTopButtonSb = document.createElement('button'); scrollToTopButtonSb.innerHTML = 'to top '; scrollToTopButtonSb.setAttribute('id', 'scrollToTop');
// Add the button to the document body const container = document.getElementById('scrollToTopContainer'); container.appendChild(scrollToTopButtonSb);
// Handle initial hash navigation window.addEventListener('load', () => { if (window.location.hash) { setTimeout(() => { const element = document.querySelector(window.location.hash); if (element) { element.scrollIntoView({ behavior: 'smooth' }); } }, 100); } });
// Progress is measured through the main content column beside the sidebar // (the .col-md-9 sibling), falling back to the whole page. const sttRow = container.closest('.row'); const sttContent = (sttRow && sttRow.querySelector(':scope > .col-md-9')) || document.documentElement; const STT_MIN = 0.08, STT_MAX = 0.55;
function sttProgress() { const rect = sttContent.getBoundingClientRect(); const range = rect.height - window.innerHeight; if (range <= 0) return 1; return Math.min(1, Math.max(0, -rect.top / range)); }
// Show/hide the button and deepen its background with scroll position let sttTicking = false; function sttUpdate() { sttTicking = false; if (window.pageYOffset > 300) { scrollToTopButtonSb.style.display = 'block'; scrollToTopButtonSb.style.setProperty('--stt-a', (STT_MIN + (STT_MAX - STT_MIN) * sttProgress()).toFixed(3)); } else { scrollToTopButtonSb.style.display = 'none'; } } window.addEventListener('scroll', () => { if (!sttTicking) { sttTicking = true; window.requestAnimationFrame(sttUpdate); } }, { passive: true });
// Scroll to top when the button is clicked scrollToTopButtonSb.addEventListener('click', () => { window.scrollTo({ top: 0, behavior: 'smooth' }); }); </script>