iOS Safari Kills Your Parallax Hero Section (The Two-Layer Fix That Actually Works)
June 2026
You build a hero section with a parallax background. It looks great on Chrome. It looks great on Firefox. You open it on an iPhone and the background image is gone.
Not broken. Not glitchy. Just gone. A solid gray rectangle where your full-bleed photo was supposed to be.
This bit us on three separate client sites before we landed on a fix that actually holds up. Here's every approach we tried, why most of them failed, and the two-layer technique that's been running in production without issues.
The Problem
iOS Safari does not support background-attachment: fixed.
Apple disabled it years ago because fixed backgrounds cause severe performance problems on mobile. The GPU has to composite the fixed background layer separately from the scrolling content, and on mobile hardware with limited memory bandwidth, that tanks frame rates.
So Safari just ignores it. Your background-attachment: fixed declaration gets silently dropped. Depending on the rest of your CSS, the image either vanishes, renders as a flat gray box, or shows up with bizarre visual artifacts.
This affects every iPhone. Every iPad. Every version of mobile Safari we've tested. It also hits Chrome on iOS because Chrome on iPhone uses WebKit under the hood, not Blink.
If your site has a parallax hero section, there's a good chance it's broken on every Apple device right now.
What We Tried That Didn't Work
Attempt 1: Next.js next/image with the fill prop.
We figured the framework's image component would handle the cross-browser rendering. It didn't. On iOS Safari, the next/image fill variant rendered a gray box for hero backgrounds. No error in the console. Just a gray rectangle. The fix for this specific issue is using a standard <img> tag with object-cover and adding -webkit-transform: translateZ(0) to force GPU compositing. But that alone doesn't give you the parallax effect on desktop.
Attempt 2: Pure CSS with a single approach for all devices.
We tried using background-attachment: fixed and letting it gracefully degrade to scroll on mobile. The problem is "graceful degradation" here means "no parallax on any device" because you can't reliably detect iOS Safari support for background-attachment with CSS alone. Media queries can't target this. @supports doesn't help because Safari reports that it supports the property; it just doesn't render it.
Attempt 3: JavaScript-driven parallax with transform on scroll.
This works on paper. Listen for scroll events, calculate the offset, apply translateY to the background. In practice, iOS Safari throttles scroll events during momentum scrolling. The background jumps and stutters instead of sliding smoothly. You can use requestAnimationFrame and -webkit-overflow-scrolling: touch, but the result still looks janky compared to native background-attachment: fixed on desktop.
None of these gave us what we wanted: real parallax on desktop and a clean, gap-free image on mobile.
The Two-Layer Fix
The solution is two separate elements stacked in the same container. Desktop gets a div with background-attachment: fixed. Mobile gets an actual <img> tag. Tailwind utility classes toggle which one is visible.
Here's the structure:
<section class="relative min-h-screen overflow-hidden">
<!-- Desktop: parallax background (hidden on mobile) -->
<div
class="hidden lg:block absolute inset-0"
style="
background-image: url('/images/hero.webp');
background-attachment: fixed;
background-size: cover;
background-position: center top;
background-repeat: no-repeat;
background-color: #1a1a2e;
"
></div>
<!-- Mobile: static image (hidden on desktop) -->
<img
src="/images/hero.webp"
alt="Hero background"
class="lg:hidden absolute inset-0 w-full h-full object-cover"
style="-webkit-transform: translateZ(0);"
/>
<!-- Overlay (shared by both layers) -->
<div class="absolute inset-0 bg-black/50"></div>
<!-- Content -->
<div class="relative z-10 flex items-center justify-center min-h-screen">
<h1 class="text-white text-5xl font-bold">Your Headline</h1>
</div>
</section>Desktop users (viewports 1024px and up) see the div with background-attachment: fixed. They get real parallax. Mobile users see the <img> tag with object-cover. They get a clean, full-bleed background that renders on every device.
The -webkit-transform: translateZ(0) on the mobile image forces GPU compositing in Safari. Without it, we saw occasional rendering delays where the image loaded late or flickered on first paint.
Both layers sit behind the same overlay div, so the visual treatment is identical regardless of which layer is active.
The Gotchas
We hit several edge cases getting this right across sites. Here's what to watch for.
Dark borders above and below parallax sections.
background-attachment: fixed sizes the background to the viewport, not the element. If your section is taller or shorter than the viewport, you get visible gaps where the background image doesn't reach. Fix this by setting background-color to match your overlay color (like #1a1a2e or black), adding background-repeat: no-repeat, using background-position: center top, and setting min-height: 100vh on the section.
Inline styles block media query overrides.
Never put responsive properties like background-size in inline styles. A style="background-size: cover" attribute has higher specificity than any media query in your stylesheet. If you need to change sizing at different breakpoints, put background-size in a CSS class, not inline. We learned this the hard way when a mobile override refused to apply.
Multiple parallax sections on one page.
If you have 3 or 4 parallax sections (we had hero, about, stats, and CTA on one site), the two-layer approach works for each one independently. But if you want a more advanced setup where a single fixed background swaps as the user scrolls through sections, use a dedicated position: fixed div as the background layer. Toggle its background-image based on which section is in the viewport using getBoundingClientRect(). Make each section transparent on mobile so the fixed background shows through.
Test on a real iPhone.
Chrome DevTools mobile emulation does not replicate Safari's background-attachment behavior. The emulator will show your parallax working fine. A real iPhone will show you the gray box. Always test on actual hardware or at minimum use BrowserStack with a real iOS Safari instance.
Where This Is Running
We deployed this two-layer technique on the Tru North Property Partners site. It's running across 4 parallax sections: hero, about, stats, and CTA. Every section uses the same hidden lg:block / lg:hidden pattern.
The site has been live for months. No rendering issues reported on any device. Desktop users get smooth parallax scrolling. iPhone users get full-bleed images that actually show up.
It's not clever. It's two elements and a breakpoint toggle. But it works on every browser we've thrown at it, and that's the only metric that matters.
If you're fighting this on your own site and want to talk through the implementation, we're here.
FAQ
Why does background-attachment: fixed not work on iOS Safari?
Apple disabled it because fixed background compositing is expensive on mobile GPUs. It causes frame rate drops and high memory usage during scrolling. Safari silently ignores the fixed value and falls back to scroll, which often causes the background image to disappear or render incorrectly depending on your other CSS.
Can I detect iOS Safari and apply a CSS fallback?
Not reliably with CSS alone. @supports (background-attachment: fixed) returns true in Safari because the browser technically supports the property; it just doesn't render it correctly on mobile. The cleanest approach is the two-layer method: show a div with background-attachment: fixed on desktop viewports and an <img> tag on mobile viewports using responsive utility classes.
Does this fix work with Next.js and React?
Yes. The HTML structure translates directly to JSX. Use Tailwind's hidden lg:block and lg:hidden classes the same way. For the mobile image, use a standard <img> tag instead of next/image with the fill prop. The next/image fill variant has its own iOS Safari rendering issues with hero backgrounds. A regular <img> with object-cover and -webkit-transform: translateZ(0) is more reliable.
What if I need parallax on mobile too?
True parallax on mobile Safari is not reliable. JavaScript-based scroll transforms stutter during momentum scrolling, and background-attachment: fixed is ignored. The best mobile experience is a static full-bleed image. Users on phones are scrolling fast with their thumbs. They won't miss the parallax effect, but they will notice a missing background image.
We build sites that work on every device, not just the one in your pocket during the demo. Check out our web development work or our custom software builds. Got a rendering bug that's driving you crazy? Let's figure it out.