Files
Santhosh Janardhanan ac3de3e142
Some checks failed
ci / site (push) Has been cancelled
publish-image / publish (push) Has been cancelled
lazy-loading done
2026-02-10 15:59:03 -05:00

3.5 KiB
Raw Permalink Blame History

1. CSS shimmer styles

  • 1.1 Add @keyframes shimmer animation to global.css — a translucent gradient sweep (left-to-right) that works on the dark theme background (--bg0/--bg1 palette).
  • 1.2 Add .img-shimmer-wrap class to global.cssposition: relative; overflow: hidden; container that inherits dimensions from its parent. Add a ::before pseudo-element with the shimmer animation (full width/height, absolute positioned, translucent light gradient).
  • 1.3 Add .img-loading class to global.css — sets opacity: 0 on the <img> element. Add transition: opacity 250ms ease.
  • 1.4 Add .img-error class to global.css — stops the shimmer animation on the wrapper (animation: none on ::before) so the placeholder displays as a static block.
  • 1.5 Verify the existing @media (prefers-reduced-motion: reduce) rule in global.css already suppresses the shimmer @keyframes animation (it should — the global rule sets animation-duration: 0.001ms !important).

2. Card thumbnail shimmer

  • 2.1 Update StandardCard.astro — wrap the existing <img> in a <div class="img-shimmer-wrap">. Add class img-loading to the <img> element. Keep the existing .card-placeholder fallback for cards with no image (no shimmer needed there).
  • 2.2 Ensure the .img-shimmer-wrap inside .card-media inherits the correct dimensions (width: 100%; height: 180px on desktop, 200px on mobile) without causing layout shift.
  • 3.1 Update blog/post/[slug].astro — wrap the featured <img> in a <div class="img-shimmer-wrap"> with matching inline styles (width: 100%; max-height: 420px; border-radius: 16px; overflow: hidden;). Add class img-loading to the <img>.
  • 3.2 Update blog/page/[slug].astro — same shimmer wrapper treatment as blog posts.

4. Image load/error script

  • 4.1 Add an inline <script is:inline> in BaseLayout.astro (or a shared location) that runs on DOM ready. For every img.img-loading element: if img.complete && img.naturalWidth > 0, remove img-loading immediately (cached images). Otherwise, add load event listener to remove img-loading and error event listener to add img-error to the wrapper.
  • 4.2 Verify the script handles dynamically added images (not currently needed — SSG renders all images server-side — but ensure the script runs after all DOM is ready).

5. Verification

  • 5.1 Run npm run build in site/ and verify no build errors.
  • 5.2 Run npm test in site/ and verify all existing tests pass (1 pre-existing failure in blog-nav.test.ts unrelated to this change — expects /about nav link that doesn't exist).
  • 5.3 Manual smoke test: throttle network in DevTools (Slow 3G), load homepage — verify shimmer appears on card thumbnails, images fade in on load.
  • 5.4 Manual smoke test: load a blog post with a featured image on throttled network — verify shimmer and fade-in.
  • 5.5 Manual smoke test: break an image URL temporarily — verify static placeholder shows (no broken image icon, no infinite shimmer).
  • 5.6 Manual smoke test: enable prefers-reduced-motion: reduce in browser/OS settings — verify shimmer animation is suppressed (static placeholder, no sweep).
  • 5.7 Verify no cumulative layout shift: compare card dimensions before and after the change using DevTools Layout Shift overlay.

Note: Tasks 5.35.7 require manual browser testing with DevTools network throttling.