Real estate

Luxury real estate website design: cinematic property tours without scroll jank

Cinematic property tours often stutter on mid-range phones and bury the booking form. Here is how we build scroll-driven tours to stay smooth, accessible and measurable.

On this page
  1. Why luxury real estate website design stutters on real phones
  2. Why the usual fixes for scroll jank fail
  3. One animation clock for GSAP ScrollTrigger and Lenis
  4. A 16.67 ms motion budget, and an image budget for Core Web Vitals
  5. Reduced motion as a designed version, with a pause button
  6. How to measure dropped frames on a website, not by feel
  7. What we would harden next, and a checklist you can use
  8. Questions we hear

The short version

  • Drive smooth scroll and scroll animations from one clock, so the pinned tour stays locked to the page under wheel and trackpad scrolling.
  • Animate only transform and opacity, so each scroll frame fits the browser’s 16.67 ms budget.
  • Cap images at 300 KB with width and height set, so the first screen loads fast and text never jumps.
  • Gate the motion, never the content: keep every room under reduced motion, add a pause button and keep the booking button in view.
  • Count dropped frames in a browser test, for the whole scroll and the heaviest section, and fail the build on missing alt text or oversized images.

Why luxury real estate website design stutters on real phones

Picture a buyer opening a villa launch link on a three-year-old Android phone. The luxury real estate website design looked flawless on the agency’s laptop. On her phone, the living room glides in, the kitchen shudders, and the tour suddenly jumps, leaving a blank strip of screen.

The “Book a private viewing” form sits five screens of stutter further down. She closes the tab before she reaches it, and the click the launch campaign paid for is gone.

We have built two sites like this: a prototype villa tour made to test scroll-driven motion, and a lightweight website kit, a product we built for architects and property developers. Here is what they taught us.

70%

of US home buyers used a mobile or tablet device during their search, and 52% found their home online.

National Association of Realtors, 2025
48%

of mobile websites passed all three Core Web Vitals in 2025, against 56% on desktop.

HTTP Archive Web Almanac, 2025
8.6%

more page views per session for luxury brands after a 0.1-second mobile speed gain.

Deloitte Digital for Google, 2020

Cinematic tours tend to fail in four places:

  • Jank. Scroll-linked motion misses frames, so rooms stutter instead of glide.
  • Core Web Vitals. These are Google’s scores for how fast the main content appears, how quickly taps respond and how much the layout jumps. Heavy heroes, heavy scripts and images without dimensions hurt them.
  • Motion sickness. Large scroll-driven zooms with no off switch make some visitors unwell.
  • Buried enquiries. The booking form sits below the spectacle and breaks when the motion code breaks.

Why the usual fixes for scroll jank fail

Teams often bolt a smooth-scroll library onto the agency build, judge the result on a laptop, and switch everything off for anyone who asks for reduced motion. Each treats a symptom.

Typical cinematic build against what held up
Typical build
  • Smooth scroll on its own animation loop
  • Animate top, height, filters and shadows
  • Ship renders at whatever size arrived
  • Reduced motion means “skip the code”
  • Judge smoothness by eye on a fast laptop
What held up
  • One clock drives scrolling and animation
  • Animate transform and opacity only
  • WebP under 300 KB, width and height set
  • A designed still version, plus a pause button
  • Count dropped frames in a scripted test

Without a measure, designer and developer trade screen recordings and opinions. We wanted a number both sides could agree on, the same idea behind our release evidence for UAT sign-off.

One animation clock for GSAP ScrollTrigger and Lenis

Two libraries usually do the work. Lenis makes scrolling glide instead of step, and GSAP ScrollTrigger moves the rooms as the page scrolls. If each keeps its own timer, they read the scroll position at different moments, and the room trails the page by a frame.

So in the tour, one clock drives both. The GSAP ticker calls lenis.raf on every tick, and Lenis reports each scroll to ScrollTrigger.update. Setting lagSmoothing(0) stops GSAP from pretending less time passed after a long stall.

What happens in one frame
  1. Ticker fires

    The GSAP ticker, the only loop on the page, starts the frame.

  2. Scroll advances

    Lenis moves the eased scroll position one step.

  3. Triggers update

    ScrollTrigger reads that position and computes each scene’s progress.

  4. Layers move

    The tour writes transform and opacity, and the GPU composites the result.

On phones this matters less than it sounds. Lenis leaves touch scrolling native by default, so the shared clock mainly fixes wheel and trackpad jitter. Touch pins still need a test on a real device.

The pinned room-by-room tour

The tour section stays pinned (fixed on screen) for five screens of scrolling, one per room. Each room fades out while scaling to 1.08, and the next settles from 1.12 to full size.

A 0.8-second scrub lets rooms ease after the scroll instead of snapping, while the pin stays locked to the page. The anticipatePin setting stops the jump as the section locks, and invalidateOnRefresh recalculates after a resize.

A 16.67 ms motion budget, and an image budget for Core Web Vitals

At 60 frames a second, the browser has 16.67 milliseconds per frame, and less on 90 or 120 Hz screens. Miss that and the frame is dropped, which the eye reads as stutter.

Transform and opacity are the properties a browser can usually animate on the GPU without new layout or paint. So every scrubbed effect in the tour is a move, a scale or a fade, and even the progress bar grows by scaling, not by height.

GSAP still writes those values from the main thread, so a long script task can drop a frame. Effects that need paint play once: the floor plan’s lines draw in when it enters view.

  • Images requested at a fixed width per slot. Full-bleed rooms request 1,800 px WebP, tiles 600 to 1,000 px, swatches 500 px and floor-plan previews 400 px. With no srcset yet, a phone downloads the same 1,800 px room as a desktop.
  • Only the top of the page loads eagerly. The hero and first tour room load at once, and the rest waits until the visitor nears it. The kit also gives its hero high fetch priority, since the hero is usually what Google’s main load score times.
  • In the kit, every image declares width and height, so the browser reserves the space and text does not jump. The tour’s photos do not.
  • A hard 300 KB cap per image. In the kit, a smoke test fails if any WebP crosses it. The six bundled photos weigh 115 KB to 233 KB.

Reduced motion as a designed version, with a pause button

Visitors who get dizzy from motion can ask their device for less, and a site reads that request through the prefers-reduced-motion media query.

Our tour prototype shows the trap. When a visitor asks for less motion, its setup code exits early, which correctly skips smooth scroll and every scroll scene.

But the same exits skip wiring the date picker, time slots and guest counter, and rooms two to five start invisible in the HTML. That visitor sees one room, a materials strip whose later swatches are out of reach, and booking controls that do not respond.

The fix is ordering: show the content and wire the form first, then exit only from the motion code.

The kit works the other way round. Under reduced motion, or without IntersectionObserver, every reveal is marked visible, and content is hidden only after the script runs. A script that fails to load never leaves a blank section.

Gate the motion, never the content or the enquiry form.

Keep the booking button in view

The tour keeps a “Book a Tour” button in its fixed navigation bar, so a buyer can jump to the form from any room. The motion is the showcase, and the enquiry should never wait behind it.

A pause button for every visitor

Many people never find the system setting, so the kit shows a visible Pause motion toggle. It stops looping animations, flattens tilted cards and pauses the embedded demo previews.

How to measure dropped frames on a website, not by feel

A frame-timing harness opens the page in a real browser engine, scrolls it in fixed steps, and records how long each frame took. Ours uses Playwright and headless Chromium at 1,440 × 900.

How the frame-timing harness runs
  1. Serve and settle

    The page loads from a local server and waits 4 seconds for the loader.

  2. Scroll in steps

    Wheel events bring the page near a section, then 50 to 60 px programmatic steps move through it.

  3. Record frame gaps

    A requestAnimationFrame loop stores frame gaps after 5 to 10 warm-up frames.

  4. Score the frames

    Ours counts gaps over 16.67 ms as dropped and over 33 ms as severe, a strict line that also catches timer jitter.

  5. Check for blanks

    Five points sampled every 200 px catch empty screens.

One run scores the whole page and a second scores the horizontal materials strip, our heaviest section. Scoring every scene separately is next.

Across the whole page, under 5% dropped frames reads as smooth, 5 to 20% as minor stutter, and over 20% as a problem. The materials run is looser: under 30% counts as smooth.

Structural checks flag a tour shorter than 90% of five viewports (a collapsed pin), a dead zone over 1,000 px after it, console errors, failed requests, broken images and sideways overflow at 390 × 844.

A smoke test for the rules people forget

The kit adds a source check that needs no browser. It fails on missing alt text or image sizes, placeholder “#” links, broken anchors and duplicate ids. It also fails on missing reduced-motion rules, any WebP over 300 KB, and JavaScript that does not parse.

Alt text alone is worth automating: WebAIM found images missing alternative text on 53.1% of the top million home pages in 2026.

What we would harden next, and a checklist you can use

Both builds have limits we would fix next:

  • A laptop is not a mid-range phone. A desktop CPU flatters every number, headless Chromium has no phone GPU, and the measured steps bypass smooth scroll. Treat the scores as a relative signal. Next we would add CPU throttling, run the harness on each pull request, and compare with field data.
  • The 1.5-second refresh is a guess. None of the tour’s 19 images declare width and height, and there is no srcset. Reserving image space, serving phone-sized files and refreshing when fonts are ready would remove the guess.
  • Layer hints are a budget too. Each will-change hint can cost GPU memory, and the tour sets it on about 20 selectors, including every testimonial character and two wrappers that never move. We would hint only what animates.
  • The tour has no pause button. Its stat marquee and slow hero zoom loop forever unless reduced motion is set, the case WCAG 2.2.2 covers.
  • Reduced motion needs its own test run. Emulating the preference in the harness would have caught the hidden rooms and silent date picker on day one.
Cinematic property site checklist
  • One frame loop drives smooth scroll and scroll animations.
  • Scroll-linked motion uses transform and opacity only.
  • Every image has alt text, width and height, and stays under 300 KB.
  • Only first-screen images load at once, and the hero gets high priority.
  • Reduced motion shows every room and a working booking form.
  • A visible pause control works for every visitor.
  • A frame-timing test reports missed frames for each section.
  • Touch scrolling and pins are checked on a real mid-range phone.
  • A build check fails on missing alt text, oversized images and dead links.
  • A booking button sits in the navigation from the first screen.
Download this checklist (PDF)

If your real estate developer website wins compliments in review and loses enquiries on phones, we can help. We build custom web software with these checks built in. Book a free 30-minute discovery call, bring the URL, and we will walk through where it stutters on a mid-range phone, what slows the first screen and whether booking works with motion off.

Questions we hear

Why do GSAP ScrollTrigger and Lenis stutter together?

Often because they run on separate requestAnimationFrame loops, so pins lag a frame behind the scroll. Drive Lenis from the GSAP ticker, call ScrollTrigger.update on each Lenis scroll event, and set lagSmoothing(0). Refresh ScrollTrigger when late images or fonts arrive. Test touch separately, because Lenis leaves it native by default.

What is scroll-jacking, and is it bad for accessibility?

Scroll-jacking is when a site takes over normal scrolling, for example by pinning a section or changing scroll speed. It is not automatically wrong, but large scroll-linked motion can cause dizziness or nausea. Respect prefers-reduced-motion with a complete still version, add a visible pause control, and keep forms working with every effect off.

How do you measure dropped frames on a website?

Load the page in a real browser engine, scroll it at a steady pace, and record the time between requestAnimationFrame callbacks. At 60 Hz a frame lands every 16.67 ms, so one missed frame shows as a gap near 33 ms. Count gaps above about 25 ms as dropped so timer jitter is ignored, report the share per section, and throttle the CPU, because a fast laptop hides problems.

How do you detect prefers-reduced-motion in JavaScript?

Call window.matchMedia with the query (prefers-reduced-motion: reduce). Its matches property is true when the visitor has asked for less motion, and a change listener catches them switching mid-visit. Use it to skip smooth scroll and scroll scenes, but always run the code that reveals content and wires up forms first.

Sources

  1. 2025 NAR Profile of Home Buyers and SellersNational Association of Realtors
  2. Web Almanac 2025: PerformanceHTTP Archive
  3. Milliseconds Make MillionsDeloitte Digital, commissioned by Google
  4. The WebAIM Million: the 2026 report on the accessibility of the top 1,000,000 home pagesWebAIM
  5. Understanding Success Criterion 2.2.2: Pause, Stop, HideW3C Web Accessibility Initiative
  6. Understanding Success Criterion 2.3.3: Animation from InteractionsW3C Web Accessibility Initiative
Written by the SeriusTech engineering team

We build custom software, business systems, applied AI and localization technology for growing businesses. Every technical claim in this note was checked against the code it describes. Products and clients stay unnamed.

Custom software servicesFollow for new field notes
Free 30-minute discovery call

Want this solved in your business?

  1. Send a short request. We reply within 1 business day with times that suit your time zone.
  2. Talk it through for 30 minutes, free and with no obligation.
  3. Leave with a suggested first step, such as a fixed-price discovery sprint.
Free, 30 minutes, no obligation

Request your discovery call

Tell us a little about your project. We reply within 1 business day with times that suit your time zone.

Open email draft

This opens your email app with a draft to contact@seriustech.com. Nothing is sent until you send it.