That’s the pattern behind most of these reports. Stripe’s own pages are built to be responsive, so the fault usually sits in the page around them: font sizes, a viewport tag, a container with a fixed height, or a speed plugin that delays Stripe’s script. Here is how to find which one, and the fix for each.
Quick answer: Most Stripe checkout mobile layout bugs come from your site, not Stripe. Set card field text to at least 16px so iPhones don’t zoom, use a standard viewport meta tag, remove global CSS that targets iframes or inputs, and don’t give embedded checkout a fixed height. Exclude js.stripe.com from script-delay plugins, then test on a real iPhone and Android phone.
Table of Contents
First, Which Stripe Checkout Are You Using?
The fix for a broken Stripe mobile checkout depends on how Stripe appears on your site, because each setup gives your code a different amount of control over the layout.
| Setup | What customers see | Who controls the mobile layout |
|---|---|---|
| Stripe-hosted Checkout or Payment Links | A full page on checkout.stripe.com or your custom domain | Stripe. Your site’s CSS can’t touch it |
| Embedded Checkout | Stripe’s checkout form inside a container on your page | Stripe inside the form, you for the container around it |
| Payment Element or other Elements | Card and payment fields placed into your own checkout page | Mostly you, plus Stripe’s Appearance settings |
| A plugin such as WooCommerce Stripe | Usually the Payment Element inside your theme’s checkout | Your theme and the plugin’s settings |
If the problem only happens on hosted Checkout, jump to the section on in-app browsers and contacting Stripe. For everything else, the fixes below apply.
Stripe Checkout Mobile Layout Bug: Symptoms and Causes
| What you see on mobile | Most likely cause | Fix |
|---|---|---|
| iPhone zooms in when you tap the card field | Field text smaller than 16px | Fix 1 |
| Page scrolls sideways or looks tiny | Missing or wrong viewport meta tag, or a fixed-width wrapper | Fix 2 and Fix 3 |
| Card fields squashed, cut off or the wrong height | Global CSS rules on iframe or input elements | Fix 3 |
| Embedded checkout cut off, Pay button hidden | Container or modal with a fixed height or overflow hidden | Fix 4 |
| Payment method tabs cramped or overlapping | Tabs layout on a narrow screen | Fix 5 |
| Fields never appear, or appear after a long delay | A speed plugin delaying or combining Stripe’s script | Fix 6 |
| Only broken inside Instagram, Facebook or TikTok | The app’s in-app browser | Fix 6 |
Fix 1: Stop iPhones Zooming Into the Card Field
Safari on iPhone zooms the page when someone taps a form field with text smaller than 16px. On a checkout, that zoom often pushes the layout sideways and hides the Pay button. Stripe’s fields sit inside iframes, so your normal CSS can’t resize their text. Set it through the Appearance settings when you create Elements:
const elements = stripe.elements({
clientSecret,
appearance: {
theme: 'stripe',
variables: {
fontSizeBase: '16px'
}
}
});
Apply the same 16px minimum to your own name, email and address fields. If you use a plugin, look for a font size or appearance option in its settings first. Don’t fix this by blocking zoom in the viewport tag, because that stops people with poor eyesight from zooming at all.
Fix 2: Check the Viewport Meta Tag
Without a viewport tag, phones render your checkout as a shrunken desktop page. Make sure the head of your checkout page includes this line, and only once:
<meta name="viewport" content="width=device-width, initial-scale=1">
Themes and page builders sometimes add a second tag with a fixed width, or with maximum-scale=1. Open your page source on the checkout page and search for “viewport”. If you find more than one, remove the extra.
Fix 3: Remove Global CSS That Hits Stripe’s Iframes
Stripe Elements are iframes, and some themes style every iframe on the site, usually for video embeds. A rule like the one below gives every card field a fixed height and breaks the layout on small screens.
/* Common theme rule that breaks Stripe fields */
iframe {
width: 100%;
height: 400px;
}
/* Safer: limit it to video embeds only */
.video-embed iframe {
width: 100%;
height: 400px;
}
Look for the same problem with rules on input, button, form or a global min-width. Also check the checkout wrapper itself. A fixed width such as 500px, or negative margins on a row, creates sideways scrolling on any phone narrower than that. Use max-width instead of width, and let the container shrink.
Fix 4: Give Embedded Checkout a Flexible Container
Embedded Checkout grows taller as customers move through it, for example when a 3D Secure step or an address form opens. If its container has a fixed height or overflow hidden, the bottom of the form, including the Pay button, gets cut off.
- Remove fixed heights from the element you mount checkout into, and from its parents.
- In a modal, use a max-height with overflow-y set to auto, so the modal scrolls instead of clipping.
- Avoid 100vh on phones. Mobile browser toolbars change the visible height. Use 100dvh, or let the content set the height.
- Check for scroll locking. Some modal scripts lock page scrolling on iOS, which also stops customers reaching the bottom of the form.
On a small screen, the simplest option is often to skip the modal and give checkout its own page.
Fix 5: Use the Accordion Layout on Small Screens
The Payment Element can show payment methods as tabs or as an accordion. With several methods turned on, such as cards, Apple Pay, Google Pay, Klarna and bank payments, tabs get cramped on a narrow phone. The accordion stacks them vertically, which fits mobile better.
const paymentElement = elements.create('payment', {
layout: {
type: 'accordion',
defaultCollapsed: false
}
});
paymentElement.mount('#payment-element');
Turning off payment methods your customers don’t use also shortens the form. Our guide to Stripe custom UI checkout covers more of the Payment Element’s layout and styling options.
Fix 6: Speed Plugins and In-App Browsers
On WordPress sites, speed and caching plugins are a common cause of a broken mobile checkout. Settings that delay, defer, combine or minify JavaScript can stop Stripe’s script loading until the customer scrolls or taps, so the card fields appear late, jump around or never show. Stripe’s script must load from js.stripe.com, not from a combined or locally hosted copy.
- Exclude js.stripe.com and your Stripe plugin’s scripts from “delay JavaScript”, “defer” and “combine” settings.
- Exclude the cart and checkout pages from page caching.
- Clear the plugin and CDN cache after each change, then test again in a private window.
If checkout only breaks when people tap your link inside Instagram, Facebook or TikTok, the cause is that app’s built-in browser, which handles pop-ups, wallets and redirects differently. You can’t fix the app, but you can test your links there, prefer a full checkout page over a pop-up, and show a small “Open in browser” hint on your checkout page.
How to Test Stripe Mobile Checkout
- Use Chrome DevTools device mode for a quick first check at 360px and 390px widths.
- Test on a real iPhone in Safari. Tap every field, because the zoom bug only shows on focus.
- Test on a real Android phone in Chrome.
- Rotate to landscape and open the keyboard, then check the Pay button is still reachable.
- Open your product link inside Instagram or another app you advertise on.
- Complete a payment in test mode with Stripe’s test cards, including one that triggers 3D Secure.
Our Stripe getting started checklist covers the other tests to run before you take live payments.
When the Problem Is Stripe’s Side
If hosted Checkout or a Payment Link looks broken on every phone and browser, and your own code isn’t involved, check Stripe’s status page first. If everything is running normally there, contact Stripe support with the device, browser version, a screenshot and the Checkout Session ID. That’s rare. In most cases we’ve fixed, the cause was one of the six fixes above.
If you’d rather not dig through theme CSS yourself, our website development team fixes and tests checkout pages on real devices.
FAQs
These are the questions store owners and developers ask most about Stripe checkout on mobile.
Why does my Stripe checkout zoom in on iPhone?
Safari zooms when a form field’s text is smaller than 16px. Set fontSizeBase to 16px in the Elements Appearance settings, and use at least 16px for your own fields too.
Is Stripe Checkout mobile responsive?
Yes. Stripe-hosted Checkout, Embedded Checkout and the Payment Element are all built to adapt to small screens. Layout problems almost always come from the page around them.
Can I change the CSS of Stripe hosted Checkout?
No. You can set your logo, colors, font and shapes in the Dashboard’s Branding settings, but you can’t add custom CSS to a Stripe-hosted page.
Why are my Stripe card fields cut off on mobile?
Usually a global CSS rule sets a fixed height or width on iframes or inputs, or the container uses overflow hidden. Limit those rules to the elements that need them.
Why doesn’t the Stripe payment form load on my phone?
A speed plugin may be delaying or combining Stripe’s script. Exclude js.stripe.com and your Stripe plugin’s files from JavaScript optimization, exclude checkout from caching, and clear the cache.
Why does Stripe checkout break inside Instagram?
Instagram, Facebook and TikTok open links in their own browser, which handles pop-ups and wallets differently. Use a full checkout page instead of a pop-up, and test your links inside the apps you advertise on.
Should I put Stripe checkout in a modal on mobile?
It works if the modal scrolls, with a max-height and overflow-y set to auto. A dedicated checkout page is simpler and avoids most mobile layout bugs.
How do I test Stripe checkout on mobile without real payments?
Use test mode or a sandbox with Stripe’s test card numbers on real phones. Include a test card that triggers 3D Secure, because that step adds height to the form.
Conclusion
Jordan’s fix took one afternoon. His new theme set all inputs to 14px and gave every iframe a fixed height. We scoped the iframe rule to video embeds, set the Stripe fields to 16px and excluded js.stripe.com from his speed plugin’s script delay. iPhone sales were back to normal the following week.
A Stripe checkout mobile layout bug is almost always a fixable conflict on your own page. Work out which checkout you use, match the symptom to the fix, and test on real phones before and after. Which symptom are you seeing on your checkout right now?











