Fork of Chiri for Astro for my blog
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 125 lines 3.1 kB view raw
1<div class="gradient-mask"> 2 <slot /> 3</div> 4 5<script> 6 let mask: HTMLElement | null = null 7 let ticking = false 8 let isMobileSafariBrowser = false 9 10 // Check if the browser is mobile Safari 11 function isMobileSafari(): boolean { 12 if (typeof window === 'undefined') return false 13 14 const ua = navigator.userAgent 15 const platform = navigator.platform 16 17 const isIOSDevice = /iP(ad|hone|od)/.test(ua) || (platform === 'MacIntel' && navigator.maxTouchPoints > 1) 18 19 if (!isIOSDevice) return false 20 21 const isSafari = /Safari\//.test(ua) && !/(CriOS|FxiOS|EdgiOS|OPiOS|DuckDuckGo)/.test(ua) 22 if (!isSafari) return false 23 24 const isMobileLike = 25 window.matchMedia?.('(pointer: coarse)').matches || window.matchMedia?.('(max-width: 768px)').matches 26 27 return Boolean(isMobileLike) 28 } 29 30 function updateMask() { 31 if (isMobileSafariBrowser) return 32 if (!mask) { 33 mask = document.querySelector('.gradient-mask') as HTMLElement 34 } 35 if (!mask) return 36 37 const threshold = 64 38 const scrollY = window.scrollY 39 40 if (scrollY >= threshold) { 41 mask.style.opacity = '1' 42 } else { 43 mask.style.opacity = '0' 44 } 45 } 46 47 function onScroll() { 48 if (ticking) return 49 ticking = true 50 requestAnimationFrame(() => { 51 updateMask() 52 ticking = false 53 }) 54 } 55 56 function initGradientMask() { 57 isMobileSafariBrowser = isMobileSafari() 58 mask = document.querySelector('.gradient-mask') as HTMLElement 59 60 if (isMobileSafariBrowser && mask) { 61 mask.style.display = 'none' 62 return 63 } 64 65 updateMask() 66 } 67 68 // Use only astro:page-load as it fires on initial load and navigation 69 document.addEventListener('astro:page-load', initGradientMask) 70 window.addEventListener('scroll', onScroll, { passive: true }) 71</script> 72 73<style> 74 .gradient-mask { 75 position: fixed; 76 top: 0; 77 left: 0; 78 width: 100%; 79 height: 2rem; 80 z-index: 99; 81 pointer-events: none; 82 background-color: var(--bg); 83 backdrop-filter: blur(1px); 84 mask-image: linear-gradient( 85 to bottom, 86 black 0%, 87 rgba(0, 0, 0, 0.738) 19%, 88 rgba(0, 0, 0, 0.541) 34%, 89 rgba(0, 0, 0, 0.382) 47%, 90 rgba(0, 0, 0, 0.278) 56.5%, 91 rgba(0, 0, 0, 0.194) 65%, 92 rgba(0, 0, 0, 0.126) 73%, 93 rgba(0, 0, 0, 0.075) 80.2%, 94 rgba(0, 0, 0, 0.042) 86.1%, 95 rgba(0, 0, 0, 0.021) 91%, 96 rgba(0, 0, 0, 0.008) 95.2%, 97 rgba(0, 0, 0, 0.002) 98.2%, 98 transparent 100% 99 ); 100 -webkit-mask-image: linear-gradient( 101 to bottom, 102 black 0%, 103 rgba(0, 0, 0, 0.738) 19%, 104 rgba(0, 0, 0, 0.541) 34%, 105 rgba(0, 0, 0, 0.382) 47%, 106 rgba(0, 0, 0, 0.278) 56.5%, 107 rgba(0, 0, 0, 0.194) 65%, 108 rgba(0, 0, 0, 0.126) 73%, 109 rgba(0, 0, 0, 0.075) 80.2%, 110 rgba(0, 0, 0, 0.042) 86.1%, 111 rgba(0, 0, 0, 0.021) 91%, 112 rgba(0, 0, 0, 0.008) 95.2%, 113 rgba(0, 0, 0, 0.002) 98.2%, 114 transparent 100% 115 ); 116 opacity: 0; 117 transition: background-color 0.2s ease-out; 118 } 119 120 @media (min-width: 768px) { 121 .gradient-mask { 122 height: 4rem; 123 } 124 } 125</style>