This is a re-opened issue of Issue: 1227
It's not possible to scroll the iframe where the components is show on an iOS device.
To fix this, add this to the container around the iframe:
overflow: auto;
-webkit-overflow-scrolling: touch;
A dirty workaround:
Create a file called manager-head.html in the .storybook folder and put this dirty css in it:
<style>
/* Make the iframe scroll on iOS */
.Pane.horizontal.Pane1>div>div+div {
overflow: auto;
-webkit-overflow-scrolling: touch;
}
</style>
would you mind opening a PR to fix this? thanks!
@Sandstedt 's fix is not enough.
My case: I am using newest stable 4.0.x.
I had added <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> tag to both manager-head.html and preview-head.html.
I tried debugging it remotely with Safari Debugger and adding various width, max-width, min-width, overflow: auto;, -webkit-overflow-scrolling: touch; wherever it's possible, and it just didn't work. Still the scroll on iOS was broken.
The reason is you can't force the iframe's document to have a certain width on iOS (1, 2). The only way is to force it from the document inside. For example, in preview-head.html you can add:
<style>
body {
max-width: 100vw;
}
</style>
Then only you will prevent iframe from being wider than how it should be, and thus scroll will be working better.
But this will still break position: fixed in the iframe. And the scroll still works very weirdly for me. If I browse the story directly by /iframe.html link, then all is okay. So I know it's the storybook / iOS / iFrame fault.
I think there should be a way to let the stories be opened in a separate tab (directly, without the <iframe> thing). For example, any click in the storybook sidebar could just act like that. This could be enabled only when some configuration flag is enabled and the device is running on iOS.
@jtomaszewski I will see if I can come upp with a working solution during the weekend and make a pull request. But I don't think it's a good solution to open it in a new tab. Then you loose access to the navigation and the bottom panel. In our projects we use that panel for ex Knobs to trigger actions and change values, so we still need that panel in the iOS version.
It should be an easy fix. Just need to have time for it :)
P.S. As a workaround if anybody's interested, we created a simple preview panel addon, which shows a 'Preview in a new window' button. It always opens the tab in the same new window so you can easily go back and forth between the tabs on your mobile ;)
Looks like that:

Code (storybook ~4.0.0):
import React from 'react';
import addons from '@storybook/addons';
class PreviewPanel extends React.PureComponent {
state = {
url: undefined,
};
componentDidMount() {
const { api } = this.props;
api.onStory(this.handleStory);
}
componentWillUnmount() {}
handleStory = () => {
const { api } = this.props;
this.setState({
url: `${window.location.origin +
window.location.pathname.replace('index.html', '')}iframe.html${
api.getUrlState().url
}`,
});
};
render() {
const { active } = this.props;
const { url } = this.state;
if (!active) {
return null;
}
if (!url) {
return 'Waiting for a story to be initialized...';
}
return (
<div
style={{
width: '100%',
padding: '15px',
fontFamily:
'-apple-system, ".SFNSText-Regular", "San Francisco", BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", "Lucida Grande", Arial, sans-serif',
WebkitFontSmoothing: 'antialiased',
}}
>
<a
href={url}
target="storybook-preview"
style={{
color: '#333',
display: 'block',
textAlign: 'center',
borderRadius: '3px',
backgroundColor: 'rgb(247, 247, 247)',
textDecoration: 'none',
fontSize: '16px',
lineHeight: '3',
}}
>
Preview in new window
</a>
</div>
);
}
}
addons.register('preview', api => {
const channel = addons.getChannel();
addons.addPanel('preview/panel', {
title: 'Preview',
render: ({ active }) => (
<PreviewPanel active={active} channel={channel} api={api} />
),
});
});
You'll be glad to hear that will be a standard feature in Storybook 5, see #4086
@ndelangen did this end up getting implemented?
The 'eject' button IS implemented, yes.
I'm unsure of the scrolling in iOS bug described.
OK, I think let's leave this open and someone can get back to us as to whether it is fixed. It isn't a particular focus of v5 so I will remove from the milestone.
Just tried V5 Beta2 and confirm it's not fixed, so still a 馃悰
@larsenwork thanks for checking, sad to hear the issue is still present. I'll try to take a look asap.
Can I reproduce this in the iOS simulator?
I did some digging, I'm able to scroll in iOS simulator a little bit, but it's buggy.
But the cause is this bug: https://bugs.webkit.org/show_bug.cgi?id=149264
WebKit is "frame flattening" which is causing the iframe to be sized differently than expected. (it auto-sizes, overriding any styles we throw at it).
This causes very annoying bugs, like:
If you component has 100vh paddingTop..
Then the iframe will be initially be sized to fit the styles storybook supplies.
Then the iframe will be resized to encompass all content inside..
Then this causes the vh to change.
Then the component gets redrawn because of the css rule
Now if WebKit would keep updating the size of the iframe element, it would just keep on growing. So it doesn't.
It seems WebKit, just "flattens" sometimes, It seems in some cases it resizes/reflows correctly.
As you can imagine this causes a TON of bugs.
Unfortunately there nothing we can do about this. Iframes cannot be scrolled on iOS, and the "flattening" is buggy because otherwise the iframe's size would potentially explode.
TLDR:
So as long as your component/element doesn't respond to the height of the iframe it seems to mostly works OK.
@ndelangen great digging! And yes, it's a webkit thing and not storybook specific.
Just some further details should anyone be interested:
My main issue has also been when the layout I'm testing is 100% height e.g.
html, body, #root {
height: 100%;
}
and then some element inside it should scroll
.sidebar {
overflow-y: scroll;
}
even though is shouldn't be scrollable the body "catches" the scroll-swipe-gesture and insists on doing the webkit scroll bounce.
Doing something like:
html, body, #root {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
helps a bit but it's still buggy
Most helpful comment
P.S. As a workaround if anybody's interested, we created a simple preview panel addon, which shows a 'Preview in a new window' button. It always opens the tab in the same new window so you can easily go back and forth between the tabs on your mobile ;)
Looks like that:
Code (storybook
~4.0.0):