Skip to content

fix(core): replace nested CSS selectors with flat selectors in preview iframe#34057

Open
mibragimov wants to merge 1 commit intostorybookjs:mainfrom
mibragimov:fix/issue-34036
Open

fix(core): replace nested CSS selectors with flat selectors in preview iframe#34057
mibragimov wants to merge 1 commit intostorybookjs:mainfrom
mibragimov:fix/issue-34036

Conversation

@mibragimov
Copy link

@mibragimov mibragimov commented Mar 7, 2026

Summary

Replace all nested CSS selectors in base-preview-head.html with flat, fully-qualified selectors to prevent a global * style leak caused by incorrect CSS nesting flattening.

Root Cause

The CSS nested selector * { background: white; color: black; } inside .sb-errordisplay_main was being incorrectly flattened by some CSS post-processors and build tools (e.g. Vite with CSS minification, PostCSS) into a global * { background: #fff; color: #000; } rule. This leaked out of the Storybook error display block and overrode all user styles in the preview iframe.

The same problem affected .sb-nopreview_main's & * { ... } nested rule.

This is a CSS nesting syntax issue: while modern browsers support @layer-nested CSS natively, many CSS post-processing tools (including some versions of PostCSS/cssnano/lightningcss used by Vite) do not correctly handle arbitrary nesting and may de-nest the * selector to the root scope.

Fix

Replace all nested CSS selectors in base-preview-head.html with flat, explicit selectors:

  • .sb-errordisplay_main * { ... } instead of nesting * { ... } inside .sb-errordisplay_main
  • .sb-errordisplay_main ol { ... }, .sb-errordisplay_main h1 { ... }, etc. instead of & ol, & h1 nested forms
  • .sb-nopreview_main * { ... } instead of & * { ... } inside .sb-nopreview_main

The flat selector approach is unambiguous, universally supported, and safe across all CSS processors.

Testing

This is a static HTML/CSS file with no associated unit tests. The fix can be verified by:

  1. Building Storybook and inspecting the generated base-preview-head.html
  2. Checking that no global * { background: ... } rule appears in the built CSS
  3. Verifying that the error display and no-preview overlays still display correctly

Closes #34036
Closes #33947
Closes #33735

Summary by CodeRabbit

  • Refactor
    • Improved CSS selector specificity and organization for error display and preview blocks to enhance styling isolation and maintainability.

…w iframe

The CSS nested selector syntax `* { ... }` inside `.sb-errordisplay_main`
was being incorrectly flattened by some CSS post-processors and build tools
(e.g. Vite, PostCSS) into a global `* { background: #fff; color: #000; }`
rule that leaked into the story iframe and overrode user styles.

Replace all nested CSS selectors in base-preview-head.html with flat,
fully-qualified selectors that are unambiguous and safe across all CSS
processors. The same issue applied to `.sb-nopreview_main`'s `& *` rule.

Fixes storybookjs#34036
Fixes storybookjs#33947
Fixes storybookjs#33735
@mibragimov mibragimov marked this pull request as ready for review March 7, 2026 14:25
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 7, 2026

📝 Walkthrough

Walkthrough

CSS selectors in the nopreview and error display blocks are refactored from broad/nested patterns to scoped class-specific variants. Changes target code/core/assets/server/base-preview-head.html, converting generic selectors to .sb-nopreview_main and .sb-errordisplay_main scoped rules with equivalent properties.

Changes

Cohort / File(s) Summary
CSS Selector Scoping
code/core/assets/server/base-preview-head.html
Refactored nopreview and error display CSS selectors from broad/nested patterns (e.g., & *, & ol, & h1) to scoped class-specific equivalents (.sb-nopreview_main *, .sb-errordisplay_main ol, etc.). Reorganized related blocks under parent scoped selectors with no functional logic changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@code/core/assets/server/base-preview-head.html`:
- Around line 225-228: The CSS selector targeting the error stack doesn't match
the actual markup: update the rule that currently targets ".sb-errordisplay_main
.sb-errordisplay pre" so it actually matches the <pre> which has class
"sb-errordisplay_code" directly under ".sb-errordisplay_main"; change the
selector to target ".sb-errordisplay_main pre.sb-errordisplay_code" (or
".sb-errordisplay_main .sb-errordisplay_code") and keep the existing white-space
properties to ensure the error stack override is applied to the correct element.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ab0a5d23-4a98-46cf-be29-f60b2f5f6119

📥 Commits

Reviewing files that changed from the base of the PR and between 8a7f39a and 0a66dcd.

📒 Files selected for processing (1)
  • code/core/assets/server/base-preview-head.html

Comment on lines +225 to 228
.sb-errordisplay_main .sb-errordisplay pre {
white-space: pre-wrap;
white-space: revert;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix the pre selector; it no longer matches the error markup.

In code/core/assets/server/base-preview-body.html:84-119, the <pre> itself has class="sb-errordisplay_code" and sits directly under .sb-errordisplay_main, so .sb-errordisplay_main .sb-errordisplay pre never applies. That leaves the error stack white-space override unscoped again.

Suggested fix
-  .sb-errordisplay_main .sb-errordisplay pre {
+  .sb-errordisplay_main .sb-errordisplay_code {
     white-space: pre-wrap;
     white-space: revert;
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.sb-errordisplay_main .sb-errordisplay pre {
white-space: pre-wrap;
white-space: revert;
}
.sb-errordisplay_main .sb-errordisplay_code {
white-space: pre-wrap;
white-space: revert;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/core/assets/server/base-preview-head.html` around lines 225 - 228, The
CSS selector targeting the error stack doesn't match the actual markup: update
the rule that currently targets ".sb-errordisplay_main .sb-errordisplay pre" so
it actually matches the <pre> which has class "sb-errordisplay_code" directly
under ".sb-errordisplay_main"; change the selector to target
".sb-errordisplay_main pre.sb-errordisplay_code" (or ".sb-errordisplay_main
.sb-errordisplay_code") and keep the existing white-space properties to ensure
the error stack override is applied to the correct element.

@valentinpalkovic
Copy link
Contributor

Hi @mibragimov,

Due to a recent high volume of unreviewed AI-generated PRs, we are randomly requesting verification and proof that the implemented fix actually works. Please provide a simple GIF/Video or image of how the bugfix works, optimally with before-and-after comparisons.

Thank you for your understanding!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Blocked

Development

Successfully merging this pull request may close these issues.

2 participants