MDX Scoped Styles in Astro

Astro's scoped `<style>` blocks do not penetrate MDX `<Content />` output. Any styles that need to reach MDX-rendered HTML must live in global CSS or use `:global()` selectors. This is a framework-level constraint, not a bug to work around.

Tags

MDX Scoped Styles in Astro

The Lesson

Astro's scoped <style> blocks do not penetrate MDX <Content /> output. Any styles that need to reach MDX-rendered HTML must live in global CSS or use :global() selectors. This is a framework-level constraint, not a bug to work around.

Context

A multi-topic regulatory compliance site used Astro 5 with @astrojs/mdx to render content pages. Each topic's landing page was an Astro page component ([topic]/index.astro) that imported and rendered an MDX file via <Content />. The page component contained scoped <style> blocks for layout grids (.value-grid, .service-overview-grid, .service-overview-card, .cta-section).

What Happened

  1. Page components were built with scoped styles targeting CSS classes used inside the MDX content.
  2. When rendered, the MDX content appeared unstyled — grid layouts collapsed, cards lost spacing, CTAs lost formatting.
  3. Investigation revealed that Astro's scoping mechanism adds unique data-astro-cid-* attributes to elements in the component's own template, but <Content /> renders its HTML outside that scope. The scoped selectors never match.
  4. The fix moved all 82 lines of affected styles from the scoped <style> block in [topic]/index.astro to global.css, where they apply regardless of component boundaries.
  5. No :global() wrapper was needed because the styles were already targeting class names that were globally unique to the design system.

Key Insights

Examples

Breaks — scoped style in the page component:

<!-- [topic]/index.astro -->
<Content />
<style>
  .value-grid { display: grid; grid-template-columns: repeat(3, 1fr); }
</style>

Works — style in global.css:

/* global.css */
.value-grid { display: grid; grid-template-columns: repeat(3, 1fr); }

Applicability

Applies to any Astro project rendering content collections, MDX files, or external HTML via <Content /> or set:html. Does not apply to components that only render their own template markup — scoped styles work correctly there.

Related Lessons