Agent context packet

Structured metadata, source alternates, graph links, headings, series position, and diagram inventory for crawlers and agent readers.

Table of contents

  1. Rule
  2. Mechanism
  3. Common collision families
  4. Specificity ladder for fixes
  5. Diagnostic
  6. Related
  7. Sources

Entry facts

Kind
snippet
Maturity
budding
Confidence
high
Origin
ai-drafted (AI-drafted, human-reviewed)
Author
Agent
Directed by
krow
Published
Modified
Words
656 (3 min read)
Tags
css, astro, patterns
Full corpus
/llms-full.txt
Readable corpus
/source/full-corpus/

Graph links

Related css-collision-visualizedastro-mental-model

Tagscss, astro, patterns

Bare Element Selectors vs Library HTML

How bare tag selectors in a global stylesheet collide with third-party library HTML — the box-model stacking trap and a specificity ladder for fixes.

/ directed by / / 3 min read
Topics css astro patterns

Rule

Bare semantic element selectors in global CSS apply to every matching element in the document, including HTML emitted by third-party libraries. Box-model properties (padding, border, margin) on different boxes stack rather than override.

Mechanism

  • A bare tag {} rule has specificity (0,0,1) and matches any element of that type, regardless of ancestry.
  • Library CSS typically sets only the properties it cares about; untouched properties cascade through from the global rule.
  • When both the outer library element and an inner library element carry padding or border, the two box models add — the user sees doubled spacing or a visible double line.

Common collision families

Bare ruleLikely library producerTypical effect
pre { padding, border, background }Syntax-highlighter frames (Expressive Code, Shiki, Prism)Padding stacks against the inner code line; border draws under the frame’s titlebar border; background diverges from the highlighter’s theme.
:not(pre) > code { background, border }Highlighter frame captions, markdown inline code emitted inside library wrappersChip styling applied twice once a library wraps the code in an extra element.
p { max-width: 68ch }Search result cards, highlighter captions, callout bodiesProse measure applied to compact UI cards; text clips short of the container it lives in.
ul, ol { padding-left, max-width }Header nav, mobile menu, footer, sidebar ToC, search facetsStructural lists inherit prose indent and width cap; every component has to override.
blockquote { border-left, padding }Markdown > quotes vs callout directivesNeutral quote renders identical to a styled callout, defeating the semantic distinction.
table, th, td { padding, border }Embedded or library-rendered tablesProse padding on tables that were meant to be dense UI.
a { color, text-decoration }Nav, footer, ToC, breadcrumbs, paginationEvery structural link becomes prose-styled; every component needs an override.
img { max-width: 100% }Logos, icons, fixed-size component imagesIntrinsic-size images get constrained to their container.

None of these are bugs in the libraries — they’re bugs in the global stylesheet’s assumption that every matching element is prose.

Specificity ladder for fixes

  1. Delete. If no legitimate prose consumer exists (e.g. every <pre> on the site is highlighter output with zero raw consumers), the rule has no job. The library owns inner styling via its own config.
  2. Scope to a content wrapper. Move rules into a layout-scoped <style> with :global() targeting a wrapper class on your rendered markdown region. Astro-native, cheap, reversible.
  3. :not() exclusion. Per-library band-aid. Works; doesn’t scale — each new library adds another exception.

Choose the highest-up option the rule permits. Exclusions beat scoping only when you can’t change the wrapper.

Diagnostic

Terminal window
# 1. List bare element selectors in the global stylesheet
grep -E '^[a-z]+[, {]' path/to/global.css
# 2. Count legitimate prose consumers vs library-emitted for each tag
grep -r '<pre' src/ content/ # raw authored <pre>?
grep -rE '<ul>|<ol>' src/ content/ # raw authored lists in prose?
# 3. In DevTools, inspect a library-rendered element.
# Count how many overriding rules the component had to write
# to cancel your global. Each override = a collision you paid for.

Zero legitimate consumers → delete. Many consumers → scope to a content wrapper. A lone outlier → narrow selector or :not().

If you want to see the exact highlighter and tabbed-code producers this warning is about, Interactive Features Showcase exercises them on a live page.

  • CSS Collision Visualized — interactive demo of the <pre> vs highlighter-frame case, plus cards for the other common producers.
  • Astro Mental Model — where scoped <style> and :global() fit in Astro’s component model.

Sources

Diagram

Drag to pan · scroll or pinch to zoom · Esc to close