Listicle / Reference 10 min read

Eight Mobile Safari Bugs That Break Shopify Themes

Most Shopify traffic is mobile and a large share of that is iOS Safari. These eight issues account for most of the "it looks broken on my iPhone" emails.

TS
ThemeSync Team
WHERE THESE EIGHT ISSUES ACTUALLY BITECHROMEFIREFOXiOS SAFARIbackdrop-filterOKOKNeeds prefixgap on flex containersOKOKOlder iOSposition: stickyOKOKQuirks100vh full-height heroOKOKClippedAutoplay video heroPlaysPlaysBlockedclip-pathOKOKNeeds prefixDate & number input stylingOKOKOverriddenScroll momentum / overscrollOKOKDiffersValid CSS everywhere. Silently ignored in one place.

Why this is worth a dedicated pass

For most Shopify stores the majority of sessions are mobile, and a large share of those are iOS Safari. That makes it the highest-traffic rendering engine on the store and the one least likely to be sitting on the developer's desk.

The unifying property of everything below: it's all valid CSS. No linter complains, no console error appears, no build step fails. Safari simply ignores a property, or interprets it differently, and the page renders wrong without telling anyone.

Commercially, this is the worst place to have a bug. It's on the device most of your client's revenue comes through, and it will be found by the client on their own phone β€” which is the single most damaging way for a defect to be discovered.

The four CSS issues

1. backdrop-filter without the prefix

Frosted-glass headers are everywhere in modern Shopify themes. Safari still wants -webkit-backdrop-filter. Without it the blur simply doesn't happen β€” and because these headers are usually semi-transparent, the result is page content scrolling visibly through the navigation.

Prefix first, standard second
.site-header {
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  background: rgba(255, 255, 255, 0.72);
}
Always ship a fallback background. If the blur doesn't apply, a translucent header over text is unreadable. Give it enough opacity to survive without the blur.

2. gap on flex containers, older iOS

Flexbox gap arrived late in Safari. On older iOS versions it's ignored on flex containers, so a product grid built with display: flex; gap: 16px renders with every card flush against its neighbour.

It works on grid in more versions than flex, which is why one grid on the page looks fine and another doesn't β€” a genuinely confusing symptom.

Feature-detect rather than guess
.product-grid > * { margin: 0 8px 16px; }

@supports (gap: 1rem) {
  .product-grid { gap: 16px; }
  .product-grid > * { margin: 0; }
}

3. position: sticky quirks

Older Safari needs -webkit-sticky. Beyond the prefix, sticky silently does nothing if any ancestor has overflow: hidden β€” true in every engine, but Safari is where you notice, because sticky headers and sticky add-to-cart bars are mobile patterns.

Prefix, then check ancestors
.sticky-atc {
  position: -webkit-sticky;
  position: sticky;
  bottom: 0;
}
/* An ancestor with overflow:hidden will kill this silently. */

4. clip-path without the prefix

Angled section dividers and shaped image masks need -webkit-clip-path. Without it Safari renders the unclipped element β€” usually a rectangle where a diagonal should be, often overlapping the section below.

These four are statically detectable. A scan over your CSS for a standard property without its -webkit- partner catches all of them before a browser is involved.

The four behavioural issues

5. 100vh and the address bar

The classic. iOS Safari treats 100vh as the viewport height with browser chrome hidden, so a full-height hero is taller than the visible area. Your CTA sits under the address bar, and on a product hero that's the buy button.

Dynamic viewport units with a fallback
.hero {
  height: 100vh;   /* fallback for older browsers */
  height: 100dvh;  /* actual visible viewport */
}

Also worth knowing: dvh changes as the address bar collapses on scroll, so anything animating against it can jitter. For sticky elements, svh (smallest viewport height) is often the steadier choice.

6. Autoplay video that doesn’t

Video heroes are common and iOS blocks autoplay unless conditions are met. Miss one attribute and the client sees a black rectangle or a still frame where you designed motion.

All four attributes are required
<video autoplay muted loop playsinline poster="hero.jpg">
  <source src="hero.mp4" type="video/mp4">
</video>

playsinline is the one people forget β€” without it iOS may take the video fullscreen. And muted is non-negotiable: audio means no autoplay, full stop. Always set a poster so the fallback is a designed frame rather than black.

7. Form controls Safari restyles

iOS applies its own appearance to selects, date and number inputs, and search fields β€” rounded corners, inner shadows, its own arrows. Your carefully styled variant selector looks like a system control.

Reset the appearance before styling
.variant-select {
  -webkit-appearance: none;
  appearance: none;
  border-radius: 8px;
  background-image: url("data:image/svg+xml,...");  /* your own arrow */
}

Related and worth setting once: font size below 16px on an input causes iOS to zoom the whole page on focus. On a checkout or search field that feels like a bug to the user.

8. Scroll behaviour and overscroll

Momentum scrolling, overscroll bounce and scroll-behavior: smooth all behave differently in Safari. Scroll-linked effects β€” parallax sections, headers that transform on scroll β€” are where this shows up, often as jitter rather than an outright break.

Also: a modal that doesn't lock body scroll will let the page behind it scroll on iOS even when it doesn't elsewhere. Use overscroll-behavior: contain on scrollable overlays.

Testing this without a drawer full of iPhones

You need two layers, because they catch different things.

WHAT EACH TESTING LAYER CATCHESWEBKIT VIA PLAYWRIGHTmost of itβœ“Vendor prefix failures β€” blur, clip-path, stickyβœ“Flex gap and layout differencesβœ“Font rendering and metric shiftsβœ“Free, fast, repeatable on every buildβœ—No real address bar collapseβœ—Autoplay policy not identicalA REAL iOS DEVICEthe last mileβœ“Actual dvh behaviour on scrollβœ“True autoplay and media policyβœ“Touch, tap delay, momentum feelβœ“Real performance on older hardware⚠Slower, harder to automate⚠Worth reserving for final checks

The practical split: run WebKit captures on every build, because it's free and catches the prefix and layout class. Reserve real-device checks for pre-launch on the two or three templates that carry the revenue β€” home, product, cart.

A pass that takes ten minutes

  1. Scan the CSS for standard properties missing their -webkit- partner. Catches issues 1, 3 and 4 with no browser.
  2. Capture in WebKit at phone width. Catches 2 and most of 1, 3, 4 visually.
  3. Grep for 100vh and confirm each has a dvh or svh companion.
  4. Check every <video> for all four autoplay attributes plus a poster.
  5. On a real iPhone: scroll the homepage top to bottom, add to cart, open the cart drawer. That's where 5, 6 and 8 surface.
Test on a small phone, not a big one. A 390px-wide viewport with a cookie banner and a chat bubble is where sticky bars and full-height heroes actually fail. Testing on the largest current iPhone hides most of it.

How ThemeSync covers this

  • WebKit is a first-class capture engine. Screenshots run through Chromium, Firefox and WebKit, so Safari rendering is part of the normal pass rather than a special exercise.
  • A code scan flags the prefix issues directly. Static rules check for backdrop-filter without -webkit-backdrop-filter, flex gap against older Safari, position: sticky without -webkit-sticky, clip-path and appearance without prefixes, and ::placeholder gaps β€” each with severity, file and line.
  • Phone, tablet and desktop presets are built in. Captures run at iPhone, iPad, Android and desktop sizes at the right pixel ratios, so small-viewport failures are visible.
  • Real Safari on real devices is available for the last mile. When you need genuine iOS behaviour on the revenue templates, that runs against real hardware rather than an emulation.
  • Overlays can be dismissed before capture. Auto-close cookie banners and popups to get clean screenshots, or leave them to see what the customer actually meets.

Takeaways

  • All eight of these are valid CSS. Nothing errors β€” Safari just ignores or reinterprets it.
  • Prefix backdrop-filter, clip-path, position: sticky and appearance, and always ship a fallback for the blur.
  • Feature-detect flex gap with @supports rather than assuming support.
  • Never use bare 100vh for a full-height hero. Use dvh, or svh for sticky elements.
  • Autoplay video needs autoplay muted loop playsinline and a poster. playsinline is the one that gets missed.
  • Reset -webkit-appearance on form controls, and keep input font size at 16px or above to stop focus zoom.
  • WebKit captures catch most of it cheaply; save real-device checks for home, product and cart.
  • Test at 390px with the overlays on. That's where it actually breaks.

Catch Safari bugs before your client’s iPhone does

ThemeSync captures every template in Chromium, Firefox and WebKit across phone, tablet and desktop, and statically flags missing vendor prefixes with file and line.

Try ThemeSync Free →