Fix header scrolling transition on public

This commit is contained in:
Justin Edmund 2025-06-02 14:11:28 -07:00
parent 5dba6af729
commit 2203e050bf

View file

@ -3,29 +3,37 @@
import SegmentedController from './SegmentedController.svelte' import SegmentedController from './SegmentedController.svelte'
let scrollY = $state(0) let scrollY = $state(0)
let hasScrolled = $state(false) // Smooth gradient opacity from 0 to 1 over the first 100px of scroll
let gradientOpacity = $derived(Math.min(scrollY / 40, 1)) let gradientOpacity = $derived(Math.min(scrollY / 100, 1))
// Padding transition happens more quickly
let paddingProgress = $derived(Math.min(scrollY / 50, 1))
$effect(() => { $effect(() => {
const handleScroll = () => { let ticking = false
scrollY = window.scrollY
// Add hysteresis to prevent flickering const updateScroll = () => {
if (!hasScrolled && scrollY > 30) { scrollY = window.scrollY
hasScrolled = true ticking = false
} else if (hasScrolled && scrollY < 20) { }
hasScrolled = false
const handleScroll = () => {
if (!ticking) {
requestAnimationFrame(updateScroll)
ticking = true
} }
} }
window.addEventListener('scroll', handleScroll) // Set initial value
scrollY = window.scrollY
window.addEventListener('scroll', handleScroll, { passive: true })
return () => window.removeEventListener('scroll', handleScroll) return () => window.removeEventListener('scroll', handleScroll)
}) })
</script> </script>
<header <header
class="site-header {hasScrolled ? 'scrolled' : ''}" class="site-header"
style="--gradient-opacity: {gradientOpacity}" style="--gradient-opacity: {gradientOpacity}; --padding-progress: {paddingProgress}"
> >
<div class="header-content"> <div class="header-content">
<a href="/about" class="header-link" aria-label="@jedmund"> <a href="/about" class="header-link" aria-label="@jedmund">
@ -42,36 +50,33 @@
z-index: 100; z-index: 100;
display: flex; display: flex;
justify-content: center; justify-content: center;
padding: $unit-5x 0; // Smooth padding transition based on scroll
transition: padding: calc($unit-5x - ($unit-5x - $unit-2x) * var(--padding-progress)) 0;
padding 0.3s ease,
background 0.3s ease;
pointer-events: none; pointer-events: none;
// Add a very subtle transition to smooth out any remaining jitter
transition: padding 0.1s ease-out;
&.scrolled { &::before {
padding: $unit-2x 0; content: '';
position: absolute;
&::before { top: 0;
content: ''; left: 0;
position: absolute; right: 0;
top: 0; height: 120px;
left: 0; background: linear-gradient(
right: 0; to bottom,
height: 120px; rgba(0, 0, 0, 0.15),
background: linear-gradient( transparent
to bottom, );
rgba(0, 0, 0, calc(0.15 * var(--gradient-opacity))), backdrop-filter: blur(6px);
transparent -webkit-backdrop-filter: blur(6px);
); mask-image: linear-gradient(to bottom, black 0%, black 15%, transparent 90%);
backdrop-filter: blur(calc(6px * var(--gradient-opacity))); -webkit-mask-image: linear-gradient(to bottom, black 0%, black 15%, transparent 90%);
-webkit-backdrop-filter: blur(calc(6px * var(--gradient-opacity))); pointer-events: none;
mask-image: linear-gradient(to bottom, black 0%, black 15%, transparent 90%); z-index: -1;
-webkit-mask-image: linear-gradient(to bottom, black 0%, black 15%, transparent 90%); opacity: var(--gradient-opacity);
pointer-events: none; // Add a very subtle transition to smooth out any remaining jitter
z-index: -1; transition: opacity 0.1s ease-out;
opacity: var(--gradient-opacity);
transition: opacity 0.2s ease;
}
} }
} }