Skip to content

Interaction case · Phase 1 refactor

Scoped CSS Without the Scope ​

Pass·VitePress 1.6.4

TL;DR ​

Sixteen project pages each carried a 70-line <style scoped> block, and both home pages carried 246 lines of inline CSS. The obvious move — paste everything into one stylesheet — would have removed the scope and let selectors such as pre, details and table leak across the site. The safe move was to keep the selectors and move the boundary into the CSS itself.

Context ​

The duplicated block covered:

  • .project-detail layout and typography
  • .stats-box tables
  • details / summary disclosure widgets
  • pre / code blocks
  • .status-published badges

Vue's scoped attribute had been doing the isolation work. A global stylesheet has no such attribute, so the isolation has to be expressed in the selectors.

The boundary risk ​

SelectorReach if left globalMitigation
preEvery code block on the site.project-detail pre
detailsHome page and future docs.project-detail details
summaryEvery disclosure widget.project-detail summary
tableAll tables, including new eval reportsKeep table styling in shared base.css
.stats-boxLow collision risk, but still owned by one page typeKept as a shared primitive

Test design ​

  1. Extract the 16 project blocks and the two home blocks without rewriting declarations.
  2. Split the result by responsibility: tokens, base, cards, home, projects.
  3. Scope element selectors under .project-detail.
  4. Diff the old and new rule sets with PostCSS:
    • selectors in old but not new
    • selectors in new but not old
  5. Rebuild and check that every project page still renders its tables, disclosures and code blocks.

Evidence ​

CheckResult
Pages migrated16
Inline <style> blocks removed18
Old CSS rules108
New CSS rules108
Missing selectors0
Added selectors0
BuildPassed, 21 pages

Verdict ​

Pass. Rule parity was checked at the selector level, not by eyeballing the page. The only intentional behavioural change was a responsive breakpoint unification (640px → 768px), recorded as a residual risk.

Residual risk: a selector-level diff cannot detect a changed declaration inside an unchanged selector. Visual spot checks covered both locales and a sample project page, but not every project at every viewport.

Reusable rule ​

Do not "globalize" scoped CSS by deleting the scope. Move the scope into the selector, then prove parity with a rule-level diff.

Crystaria (with Paw and Kyle)