Skip to content

fix: prevent code blocks flash in dark mode (AI-assisted)#12221

Open
titojuanc wants to merge 2 commits into
facebook:mainfrom
titojuanc:main
Open

fix: prevent code blocks flash in dark mode (AI-assisted)#12221
titojuanc wants to merge 2 commits into
facebook:mainfrom
titojuanc:main

Conversation

@titojuanc

@titojuanc titojuanc commented Jul 2, 2026

Copy link
Copy Markdown

Pre-flight checklist

  • I have read the Contributing Guidelines on pull requests.
  • If this is a code change: I have written unit tests and/or added dogfooding pages to fully verify the new behavior.
  • If this is a new API or substantial change: the PR has an accompanying issue (closes #0000) and the maintainers have approved on my working plan.

Motivation

Fixes #11566

When loading a page in dark mode, code blocks briefly flash with light theme colors before switching to the correct dark colors. This happens because prism-react-renderer's <Highlight> applies syntax colors as inline styles on every token <span> (e.g. style="color: #e3116c"). Inline styles have higher specificity than any CSS selector, so the [data-theme="dark"] attribute — already set by Docusaurus's blocking inline script before hydration — could not override them.

This is a follow-up to #11967, which was closed after review. This PR addresses the two issues raised by @slorber:

  1. Token colors still flashed — the previous PR only fixed the container background via CSS variables, but left token colors driven by inline styles.
  2. CSS was inlined in every HTML page — the previous PR injected a <style> tag via injectHtmlTags(), adding weight to every SSR page even those without code blocks.

What changed (AI-assisted)

packages/docusaurus-theme-classic/src/index.ts

  • Added generatePrismCSS(), which produces CSS rules for both themes:
    • CSS custom properties (--prism-background-color, --prism-color) for the container.
    • Per-token rules scoped under [data-theme='light'] .token.<type> and [data-theme='dark'] .token.<type>.
  • The file is written asynchronously in loadContent() to generatedFilesDir/docusaurus-theme-classic/prism-theme.css.
  • The path is registered in getClientModules() so the bundler includes it in the site CSS bundle — loaded once and cached by the browser, not repeated in every HTML page.
  • The injectHtmlTags() headTags with the inline <style> was removed entirely.

packages/docusaurus-theme-classic/src/theme/CodeBlock/Content/index.tsx

  • Introduced BARE_PRISM_THEME = {plain: {}, styles: []} passed to <Highlight theme={BARE_PRISM_THEME}>. This suppresses all inline styles on token spans while preserving Prism's token class names (e.g. token keyword), which the generated CSS then targets.

packages/docusaurus-theme-common/src/utils/codeBlockUtils.tsx and src/internal.ts

  • Removed getPrismCssVariables and its re-export, as it is no longer used anywhere.
  • Removed the now-unused PrismThemeEntry, CSSProperties, and PrismTheme imports from codeBlockUtils.tsx.

Test Plan

  1. Configure a Docusaurus site with different light and dark Prism themes:
    prism: {
      theme: prismThemes.oneLight,
      darkTheme: prismThemes.oneDark,
    }
  2. Switch the site to dark mode.
  3. Hard-reload any page containing code blocks.
  4. Observe that code blocks render immediately with the correct dark colors — no flash of light theme colors.
  5. Navigate to a page with no code blocks and confirm via DevTools that no Prism CSS is inlined in the HTML — it is only present in the bundled CSS file.

Test links

Deploy preview: https://deploy-preview-_____--docusaurus-2.netlify.app/
//then i'll edit this, dw

Related issues/PRs

titojuanc added 2 commits July 2, 2026 15:43
- Generate Prism theme CSS (vars + token rules) to a file in
  generatedFilesDir via loadContent() and register it via
  getClientModules() so it is bundled once in the site CSS, not
  inlined in every HTML page.
- Use BARE_PRISM_THEME in <Highlight> to suppress inline styles on
  token spans; colors are now applied via [data-theme] CSS selectors.
- Remove unused getPrismCssVariables, PrismThemeEntry and related
  imports from codeBlockUtils and internal.ts.

Fixes facebook#11566
@meta-cla meta-cla Bot added the CLA Signed Signed Facebook CLA label Jul 2, 2026
@netlify

netlify Bot commented Jul 2, 2026

Copy link
Copy Markdown

[V2]

Built without sensitive environment variables

Name Link
🔨 Latest commit 3389bd9
🔍 Latest deploy log https://app.netlify.com/projects/docusaurus-2/deploys/6a46b4fc3b4c8f000996844b
😎 Deploy Preview https://deploy-preview-12221--docusaurus-2.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@slorber slorber added the Argos Add this label to run UI visual regression tests. See argos.yml GH action. label Jul 3, 2026
@slorber

slorber commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

That looks like an interesting solution, thanks. The preview seems to work as expected.

I'll review this more carefully later

@argos-ci

argos-ci Bot commented Jul 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ⚠️ Changes detected (Review) 13 changed Jul 3, 2026, 2:27 PM

@slorber

slorber commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Although maybe not that problematic, our visual regression tools reported visual diffs on code blocks: https://app.argos-ci.com/meta-open-source/docusaurus/builds/1781/overview

For example, you can see that " are not colored the same:

CleanShot 2026-07-03 at 16 41 25@2x

I would expect this PR to preserve the exact same colors as before, or this means there's a bug somewhere in your logic, that may be more impactful in some cases.

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

Labels

Argos Add this label to run UI visual regression tests. See argos.yml GH action. CLA Signed Signed Facebook CLA

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Code blocks flashes in dark mode

2 participants