Skip to content
🚧 Early alpha — building the foundation. See the roadmap →

Nova theme CSS layout fix

Created Updated

Every custom HTML/CSS diagram across all concept pages had alignment issues — elements appeared shifted left, cards were uneven heights, content seemed narrower than the container. This is a common pattern reported across many Astro Starlight + Nova theme deployments.

Initially blamed padding-inline-start: 2rem on .sl-markdown-content. This was wrong — Nova only adds that padding to <dd> elements (definition list descriptions), not to the markdown content container. The padding override we added was a no-op.

Cause 1: Nova’s overflow-x: hidden on .main-pane

Section titled “Cause 1: Nova’s overflow-x: hidden on .main-pane”

Nova’s TwoColumnContent.astro adds overflow-x: hidden on .main-pane. Starlight base does NOT do this.

Effect: Any diagram with internal padding that pushes its total rendered width beyond the .sl-container boundary gets silently clipped on the right side. This creates the APPEARANCE of left-shifting because the right edge is invisibly cut off.

File: node_modules/starlight-theme-nova/src/components/TwoColumnContent.astro

CSS default is content-box. When a div has width: 100% plus padding: 1rem, its actual rendered width is 100% + 2rem — exceeding the container. Combined with Cause 1, this content gets clipped.

Cause 3: Starlight’s markdown.css inter-paragraph margin (THE MAIN CULPRIT)

Section titled “Cause 3: Starlight’s markdown.css inter-paragraph margin (THE MAIN CULPRIT)”

Starlight core’s markdown.css adds margin-top: var(--sl-content-gap-y) (1rem = 16px) between every adjacent non-inline sibling inside .sl-markdown-content:

.sl-markdown-content :not(inline) + :not(inline) {
  margin-top: var(--sl-content-gap-y);
}

This is designed for paragraph spacing. But it ALSO applies inside our grid/flex containers — giving the 2nd, 3rd, etc. children 16px extra margin-top. This made every first card appear 16px taller than its siblings. This is NOT a Nova bug — it’s Starlight core behavior affecting ANY theme.

In docs/src/styles/brand.css — three rules:

/* 1. Prevent overflow from width:100% + padding */
.sl-markdown-content div { box-sizing: border-box; }

/* 2. Prevent Starlight's inter-paragraph margin inside custom containers */
.sl-markdown-content [class*="oe-"] > *,
.sl-markdown-content [class*="il-"] > *,
/* ... all custom prefixes ... */
{ margin-top: 0; }

/* 3. Hide sidebar scrollbar (94+ pages overflow) */
#starlight__sidebar { scrollbar-width: none; }

Why no !important: brand.css is unlayered CSS. Nova uses @layer nova. Unlayered CSS automatically beats all @layer rules — !important is unnecessary.

Verified with Playwright (all heights in px):

  • Change cards: 285, 285, 285 (was 397, 381, 381) — EQUAL
  • EMC steps: 85, 85, 85 — EQUAL
  • Temporal boxes: 83, 83 (was 115, 99) — EQUAL
  • SCD cards: 224, 224, 224 (was 368, 352, 352) — EQUAL
  • Sidebar scrollbar: hidden

The DOM wrapper chain in Starlight + Nova:

.main-frame          ← padding-inline-start: var(--sl-content-inline-start)
  .main-pane         ← overflow-x: hidden (Nova adds this)
    main
      .content-panel ← padding: 1.5rem var(--sl-content-pad-x)
        .sl-container ← max-width: var(--sl-content-width) [50rem with Nova]
          .sl-markdown-content ← NO padding from Starlight or Nova

Nova also sets --sl-content-width: 50rem (wider than Starlight’s default 45rem).

For future Starlight projects (with ANY theme)

Section titled “For future Starlight projects (with ANY theme)”

When adding custom HTML/CSS diagrams to Starlight content:

  1. box-sizing: border-box on all custom divs — prevents overflow when using width: 100% + padding
  2. margin-top: 0 on children inside custom containers — prevents Starlight’s inter-paragraph spacing (--sl-content-gap-y) from affecting grid/flex layouts
  3. scrollbar-width: none on #starlight__sidebar if you have many pages (94+)
  4. Do NOT override .main-pane { overflow-x } — it breaks the sidebar layout
  5. No !important needed — unlayered CSS already beats all @layer rules

This applies to Starlight core, not just Nova. Any theme will have this issue if you put custom HTML grids/flexboxes inside markdown content.

Nova shows the sidebar at md: breakpoint (768px) using Tailwind’s md:visible. But at 768-1023px there’s only 468-723px for content after the 300px sidebar — not enough room. Mobile landscape devices (Samsung Galaxy S21 Ultra = ~915px) were particularly affected.

Fix: Media query that hides sidebar and shows hamburger menu at 768-1023px:

@media (min-width: 768px) and (max-width: 1023px) {
  #starlight__sidebar { visibility: hidden !important; }
  .main-frame { padding-inline-start: 0 !important; }
  nova-mobile-menu-toggle { display: flex !important; }
}
  1. Test at 768-1023px — the sidebar should collapse to hamburger, not overlap content