storybook
storybook copied to clipboard
Firefox zoom implementation breaks position: fixed elements in Docs
Describe the bug
In Firefox, the zoom feature uses transform
styles (see https://github.com/storybookjs/storybook/pull/12845) - unfortunately this breaks positioning on elements that require position: fixed
when in the "Docs" view.
Normally a position: fixed
element's position would correspond to the viewport but in Firefox it corresponds to the element with the transform
style.
The issue is present regardless of actually using the zoom feature. I have tried to disable the zoom feature (related feature request: https://github.com/storybookjs/storybook/issues/16771) in the hopes that it might also remove the styling used for zoom, however, the styling remains.
To Reproduce I created a simplified reproduction of the issue here: https://github.com/idesigncode/bug-storybook-firefox-position-fixed
To view the issue, open the story in Docs view in both Firefox and another browser.
System System: OS: macOS 12.0.1 CPU: (8) x64 Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz Binaries: Node: 14.17.3 - ~/.nvm/versions/node/v14.17.3/bin/node Yarn: 3.1.0 - /usr/local/bin/yarn npm: 7.20.0 - ~/.nvm/versions/node/v14.17.3/bin/npm Browsers: Chrome: 96.0.4664.55 Edge: 95.0.1020.53 Firefox: 94.0.1 Safari: 15.1 npmPackages: @storybook/addon-actions: ^6.4.0-rc.7 => 6.4.0-rc.7 @storybook/addon-docs: ^6.4.0-rc.7 => 6.4.0-rc.7 @storybook/addon-essentials: ^6.4.0-rc.7 => 6.4.0-rc.7 @storybook/addon-links: ^6.4.0-rc.7 => 6.4.0-rc.7 @storybook/react: ^6.4.0-rc.7 => 6.4.0-rc.7
Additional context My actual use case is documenting a tooltip component that uses fixed positioning to stay within the window.
Here's some screenshots of the simplified example:
Chrome ✅
Firefox ❌
Firefox (with the transform style disabled) ✅
@idesigncode Thanks for a great bug report! I have done some work on the zoom feature in the past and I might be able to help.
Going through your examples I can't really see an obvious solution to the problem but I'm going to fire up my development environment over the weekend and see what I can figure out.
@idesigncode Are you interested in figuring out a solution for this issue too?
Hey @Tomastomaslol, all good, yeah the solution isn't obvious to me either...
For my specific use case I would be happy to disable the zoom feature on the affected stories as long as that also removed the transform
style.
Happy to help test and be involved in the discussion but I'm not familiar with the source code.
Is the story rendered graphically in code?
I had a look at this and the behaviour is inconsistent across the 2 browsers.
@idesigncode, Could you please explain your use case? To me, the behaviour in firefox looks more correct than in chrome. I would expect the element you are previewing to be positioned relative to the "story wrapper".

In the attached screenshot I added a green box around what I consider to be the "story wrapper." 🙂
@Tomastomaslol, sure thing:
My use case is documenting a tooltip component that is always visible within the window (if opened). This is achieved by using position: fixed
and calculating the appropriate top/left values in relation to the viewport.
The calculated values are based off getBoundingClientRect which essentially is expecting the first document
ancestor to be what I would call the "positioning origin".
In Firefox, the first ancestor with the transform
style kind of becomes the "positioning origin" and so the calculated vertical and horizontal positioning values are no longer correct.
It may be worth noting that all other browsers I've tested this in behave like Chrome so Firefox does appear to be the odd-one-out in regards to this issue.
How can I contribute to this project? I have moderate knowledge of HTML CSS and Javascript!
@Monk102 https://storybook.js.org/docs/react/contribute/how-to-contribute
can you guys provide me a simple website code ?😣
Hey @idesigncode could you please suggest me , how do I start contributing to this project .I am new to the world of open source contribution. Please help me
Hey @idesigncode could you please suggest me , how do I start contributing to this project .I am new to the world of open source contribution. Please help me
https://storybook.js.org/docs/react/contribute/how-to-contribute
Is this still an active problem?
@Stroudnat Yes, I'm not aware of any recent changes to resolve this.
Thanks @idesigncode just got around to cloning everything and looking at issue repos so Ill check back if I see anything!
@idesigncode in our Design System, to fix this issue with Firefox we used React's createPortal
to work this out.
@konsalex sounds interesting... is that in Storybook or the component itself? Can you provide any code examples?
@idesigncode I implemented this in the component it's self. Cannot share code example at the moment, but in a higher level
Before it was a
<ForwardRef>
<PopoverComponent />
</ForwardRef>
which was breaking with getBoundingClientRect, and the approach of wrapping it with a portal like this,
const Portal = ({ children, container }: PortalProps) => {
return ReactDOM.createPortal(children, container);
};
solve the issue
Test
I do not expect there is an ideal fix here as the inconsistency lies in the browsers' implementation of the transform
style...
But if I may propose an alternative: only apply the transform
style if the zoom feature is not disabled.
I believe the zoom feature is the only reason to use the transform
style in the first place, so applying it while this feature is disabled seems unnecessary.
This bug also affects the measuring tool when zooming. That is probably a bigger problem, because for small components zooming when measuring is quite a common workflow.
In chrome it is correctly placed, though blurry:
In firefox it is not scaled correctly and offset:
Recreated in a default react storybook: https://github.com/bodograumann/storybook-zoom-measure
I would like to look into it and fix. Pls confirm if anybody looking into.
I started to look into
Is this still an issue with 7.0 beta?
@ndelangen Yes, I've just tested by upgrading the above reproduction repo (locally) and it is still an issue.
👋 I've just encountered this issue and cannot seem to find any workaround! It happens in Chrome as well. It's fine in story mode because the story uses the whole document as a canvas, but has broken in Docs. Strangely, this was working until the recent upgrade of 7.1
This is an issue for us in Chrome as well. Components using position: fixed
render incorrectly inside Canvas doc blocks because of the wrapper div having a transform
property in it. This CSS is new on 7.1.
.css-1rj4uy6 {
height: 68px;
transform-origin: top left;
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
transform: scale(1);
}
Implemented a (hopefully) temporary fix in our global stylesheet for Storybook:
.docs-story div[scale] {
transform: none !important;
}
@stefanpearson @wfigueroa-chwy indeed that's an issue with 7.1.0
, created a separate issue for this, with reproduction here:
https://github.com/storybookjs/storybook/issues/23586
This bugfix has introduced the current behaviour: https://github.com/storybookjs/storybook/pull/21303
I'm honestly a little conflicted. On the one hand, I understand your problem, but on the other hand, I believe that the container inside the docs page should be decapsulated from the environment, and elements should not break out of it. Now, you could adjust the height of the container on the Docs page so that modals find a place there as soon as they are triggered. What do you think? Do I overlook something?
This bugfix has introduced the current behaviour: #21303
I'm honestly a little conflicted. On the one hand, I understand your problem, but on the other hand, I believe that the container inside the docs page should be decapsulated from the environment, and elements should not break out of it. Now, you could adjust the height of the container on the Docs page so that modals find a place there as soon as they are triggered. What do you think? Do I overlook something?
The issue is, or at least in the scenario I've encountered, a popover component that uses position:fixed (e.g. with Floating UI) now loses it's positioning, because transform and fixed positioning do not work together. This means the component is fully broken in docs mode, and not as a fault of the component.
@stefanpearson that's true, but position: fixed
was inconsistent between browsers also, so some popovers would work in Chrome, but would not work in Safari/Firefox .
That's problematic because the majority of popover components in most web apps are implemented with position: fixed, either with portalling or with the native dialog element appearing in the top layer. Perhaps this could get better with the arrival of the new Popover API (absolute everything in the top layer?), but alas we're not there yet.
However, the scale transform does make sense for the zoom feature, so I don't expect a rollback. Perhaps there is now a need to disable zoom (and remove the transform) for individual stories that will certainly break? The only other option we have is to implement the CSS hack outlined by @wfigueroa-chwy above, to ensure our users don't assume our components are broken.