ScopedCss class

A compiled scoped CSS stylesheet bundle providing deterministic class name isolation.

Generated via scopedCss or ScopedCss.compile. Parses author CSS and rewrites every local class selector so that it is suffixed with a unique, deterministic hash derived from the stylesheet source and an optional component name prefix (e.g. .card becomes .card__a1b2c3d or .btn_card__a1b2c3d).

Determinism across SSR and Browser Backends

The scoping transformation is a pure function over strings with zero browser DOM or Flutter dependencies. The exact same ScopedCss instance or identical input string produces bit-for-bit identical class names, class maps, and CSS text on both the server (SSR via renderToHtml) and the client (browser DOM mounting via mount), guaranteeing zero hydration mismatch or style flashing.

Embedding node (or style) in a component tree injects a <style> element into the DOM in the browser or emits <style>...</style> directly into the SSR HTML stream.

Selector Scoping Rules

  • Scoped Local Classes: All local class selectors (.title, .btn-primary, .item:hover, .nav > .item) are automatically rewritten with the scoped suffix.
  • Global Escape Hatch (:global): Class selectors wrapped inside :global(...) (e.g. :global(.theme-dark) .card or .button:global(.active)) are unwrapped and preserved verbatim without scoping. Use this to style against ambient theme classes, body attributes, or external third-party classes.
  • Preserved Selectors: Element/type selectors (div, p, span, h1), ID selectors (#header, #app), root selectors (:root), and universal selectors (*) are deliberately left untouched.
  • Nested At-Rules: Rules inside @media, @supports, @container, and @layer blocks are parsed and scoped recursively.
  • Keyframe Preservation: Animation stops (from, to, and percentages like 0%, 50%, 100%) inside @keyframes and @-webkit-keyframes blocks are intentionally not rewritten, preserving standard CSS animation definitions.
  • At-Rule Declarations: Declaration blocks inside @font-face, @page, and @property are preserved verbatim without selector rewriting.

Pragmatic Parser Capabilities & Limitations

ScopedCss is a pragmatic, high-performance selector rewriter rather than a full CSS AST parser or CSS validator:

  • It assumes structurally valid CSS with balanced delimiters ({}, (), [], "", '', /* */).
  • It does not validate CSS property names or values.
  • Exotic selectors with unquoted commas inside pseudo-functions may not split cleanly.
final styles = scopedCss('''
  .card {
    padding: 16px;
    background: #14141a;
    border: 1px solid #27272a;
    border-radius: 8px;
  }
  .card:hover {
    border-color: #6366f1;
  }
  .title {
    font-size: 18px;
    font-weight: 600;
    color: #ffffff;
  }
  :global(.theme-dark) .card {
    background: #09090b;
  }
''', name: 'card');

BloomNode cardWidget(String titleText) => Div(
  className: styles['card'],
  children: [
    styles.node,
    H1(className: styles['title'], text: titleText),
  ],
);

Constructors

ScopedCss(String rawCss, {String? name})
Creates a ScopedCss instance by compiling rawCss with an optional component name.
factory
ScopedCss.compile(String rawCss, {String? name})
Compiles rawCss into a scoped stylesheet with class name mappings.
factory

Properties

classes Map<String, String>
Lookup map from author class names (e.g. 'title') to generated scoped class names (e.g. 'card_title__a1b2c3d').
final
css String
The transformed CSS stylesheet with all local class selectors scoped.
final
hash String
The deterministic 7-character hex hash derived from the CSS content and name.
final
hashCode int
The hash code for this object.
no setterinherited
name String?
The optional human-readable component name prefix (e.g. 'card', 'button').
final
node StyleNode
The StyleNode descriptor containing the transformed css, ready to drop into a BloomNode tree.
final
rawCss String
The raw, un-scoped CSS source provided by the author.
final
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
style StyleNode
Alias for node for convenient stylesheet embedding.
no setter

Methods

call(String className) String
Functional lookup shorthand — equivalent to this[className].
cx(List<Object?> parts) String
Composes a class list resolving author class names to their scoped equivalents.
get(String className) String
Looks up the generated scoped class name for author className.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toString() String
A string representation of this object.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited
operator [](String className) String
Looks up the generated scoped class name for author className.