Skip to content

Gotcha

The Idea

Lenis smooth scroll library is INCOMPATIBLE with CSS scroll-snap. They fight for scroll control.

Context

Wedding invitation site had both Lenis (for smooth parallax scrolling) and CSS scroll-snap (for section-by-section navigation). Neither worked properly.

Raw Exchange

Librarian agent research: “CRITICAL: Lenis and CSS scroll-snap are INCOMPATIBLE - Lenis hijacks native scrolling” Solution: “Remove Lenis, use CSS scroll-snap + native smooth scroll for better mobile performance”

Investigation

Lenis works by:

  1. Intercepting wheel/touch events
  2. Applying its own scroll animation via requestAnimationFrame
  3. Updating scroll position programmatically

CSS scroll-snap expects:

  1. Native scroll behavior
  2. Browser to handle snap points
  3. No interference with scroll position

When combined:

  • Lenis animates scroll → browser tries to snap → Lenis overrides → janky behavior
  • Mobile especially broken (touch events fight)

Resolution

Removed Lenis entirely:

// Before (Layout.astro)
import Lenis from 'lenis';
const lenis = new Lenis({ ... });
lenis.on('scroll', ScrollTrigger.update);

// After
// Just GSAP ScrollTrigger, no Lenis
gsap.registerPlugin(ScrollTrigger);

Added native smooth scroll:

Read more

What Happened

Test script failed silently after first passing test. The script used set -e (exit on error) combined with bash arithmetic increment:

set -e
TESTS_PASSED=0

log_success() {
    echo "[PASS] $1"
    ((TESTS_PASSED++))  # THIS CAUSES EXIT!
}

Why It Matters

((TESTS_PASSED++)) returns exit code based on the POST-increment value:

  • When TESTS_PASSED=0: ((0++)) evaluates to 0 (falsy) → exit code 1
  • set -e sees exit code 1 → script exits

This is a common bash gotcha that’s hard to debug because:

  • No error message
  • Happens on the FIRST success, not failure
  • Looks like it should work

Resolution

Use explicit arithmetic assignment instead:

log_success() {
    echo "[PASS] $1"
    TESTS_PASSED=$((TESTS_PASSED + 1))  # Safe - always returns 0
}

Lesson

Never use ((var++)) with set -e. The increment operator’s return value is the pre-increment value, which is falsy when starting from 0.