or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration.mdcss-features.mdindex.mdstyle-merging.mdstyle-sets.mdstylesheet-management.md
tile.json

stylesheet-management.mddocs/

Stylesheet Management

Low-level stylesheet management with support for CSS rule injection, caching, serialization, and specialized Shadow DOM handling.

Capabilities

Core Stylesheet Class

Main stylesheet management class for CSS rule injection and caching.

/**
 * Core stylesheet management class
 */
class Stylesheet {
  /**
   * Creates a new Stylesheet instance
   * @param config - Optional configuration for stylesheet behavior
   * @param serializedStylesheet - Optional serialized stylesheet state for SSR
   */
  constructor(config?: IStyleSheetConfig, serializedStylesheet?: ISerializedStylesheet);

  /**
   * Get singleton instance of Stylesheet
   * @param shadowConfig - Optional shadow DOM configuration
   * @returns Stylesheet instance
   */
  static getInstance(shadowConfig?: ShadowConfig): Stylesheet;

  /**
   * Insert a CSS rule into the stylesheet
   * @param rule - CSS rule string to insert
   * @param preserve - Whether to preserve rule during reset
   * @param stylesheetKey - Optional key for targeted insertion
   */
  insertRule(rule: string, preserve?: boolean, stylesheetKey?: string): void;

  /**
   * Generate a unique CSS class name
   * @param displayName - Optional display name for debugging
   * @returns Generated unique class name
   */
  getClassName(displayName?: string): string;

  /**
   * Get all generated CSS rules
   * @param includePreservedRules - Whether to include preserved rules
   * @returns CSS rules as string
   */
  getRules(includePreservedRules?: boolean): string;

  /**
   * Cache a class name with its associated data
   * @param className - Class name to cache
   * @param key - Lookup key for the class
   * @param args - Original style arguments
   * @param rules - Generated CSS rules
   */
  cacheClassName(className: string, key: string, args: IStyle[], rules: string[]): void;

  /**
   * Retrieve class name from cache key
   * @param key - Lookup key
   * @returns Cached class name or undefined
   */
  classNameFromKey(key: string): string | undefined;

  /**
   * Retrieve original style arguments for a class name
   * @param className - Class name to look up
   * @returns Original style arguments or undefined
   */
  argsFromClassName(className: string): IStyle[] | undefined;

  /**
   * Retrieve CSS rules for a class name
   * @param className - Class name to look up
   * @returns CSS rules array or undefined  
   */
  insertedRulesFromClassName(className: string): string[] | undefined;

  /**
   * Get current class name cache
   * @returns Object mapping keys to class names
   */
  getClassNameCache(): { [key: string]: string };

  /**
   * Set stylesheet configuration
   * @param config - New configuration options
   */
  setConfig(config?: IStyleSheetConfig): void;

  /**
   * Reset stylesheet state
   */
  reset(): void;

  /**
   * Reset only the cached keys
   */
  resetKeys(): void;

  /**
   * Serialize stylesheet state for SSR
   * @returns Serialized stylesheet data
   */
  serialize(): string;

  /**
   * Register callback for rule insertion events
   * @param callback - Function to call when rules are inserted
   * @returns Unsubscribe function
   */
  onInsertRule(callback: Function | InsertRuleCallback): Function;

  /**
   * Register callback for stylesheet reset events
   * @param callback - Function to call when stylesheet is reset
   * @returns Unsubscribe function
   */
  onReset(callback: Function): Function;
}

Usage Examples:

import { Stylesheet, InjectionMode } from "@fluentui/merge-styles";

// Custom stylesheet with configuration
const customStylesheet = new Stylesheet({
  injectionMode: InjectionMode.insertNode,
  defaultPrefix: "my-app",
  namespace: "my-namespace"
});

// Insert custom CSS rules
customStylesheet.insertRule(`.custom-class { color: red; }`, true);

// Generate class names
const className1 = customStylesheet.getClassName("button");
const className2 = customStylesheet.getClassName("header");

// Get all generated CSS
const cssRules = customStylesheet.getRules();

// Monitor rule insertion
const unsubscribe = customStylesheet.onInsertRule((rule) => {
  console.log("Rule inserted:", rule);
});

Shadow DOM Stylesheet

Specialized stylesheet class for Shadow DOM environments with constructable stylesheet support.

/**
 * Specialized stylesheet for Shadow DOM environments
 */
class ShadowDomStylesheet extends Stylesheet {
  /**
   * Creates Shadow DOM stylesheet instance
   * @param config - Configuration options including inShadow flag
   * @param serializedStylesheet - Optional serialized state
   */
  constructor(config?: IStyleSheetConfig, serializedStylesheet?: ISerializedStylesheet);

  /**
   * Get singleton Shadow DOM stylesheet instance
   * @param shadowConfig - Shadow DOM configuration
   * @returns ShadowDomStylesheet instance
   */
  static getInstance(shadowConfig?: ShadowConfig): ShadowDomStylesheet;

  /**
   * Get map of adopted stylesheets
   * @returns Map of stylesheet keys to ExtendedCSSStyleSheet
   */
  getAdoptedSheets(): Map<string, ExtendedCSSStyleSheet>;

  /**
   * Register callback for sheet addition events
   * @param callback - Function called when sheets are added
   * @returns Unsubscribe function
   */
  onAddSheet(callback: AddSheetCallback): Function;

  /**
   * Insert rule with Shadow DOM handling
   * @param rule - CSS rule to insert
   * @param preserve - Whether to preserve during reset
   */
  insertRule(rule: string, preserve?: boolean): void;
}

Usage Examples:

import { ShadowDomStylesheet, makeShadowConfig } from "@fluentui/merge-styles";

// Create shadow configuration
const shadowConfig = makeShadowConfig("my-component", true, window);

// Get Shadow DOM stylesheet
const shadowStylesheet = ShadowDomStylesheet.getInstance(shadowConfig);

// Monitor sheet additions
shadowStylesheet.onAddSheet(({ key, sheet }) => {
  console.log(`Sheet added: ${key}`, sheet);
});

// Insert rules into Shadow DOM
shadowStylesheet.insertRule(`.shadow-style { background: blue; }`);

// Get adopted sheets
const adoptedSheets = shadowStylesheet.getAdoptedSheets();

Utility Functions

Additional utilities for stylesheet management.

/**
 * Clone CSSStyleSheet from source to target
 * @param srcSheet - Source stylesheet to clone from
 * @param targetSheet - Target stylesheet to clone to
 * @returns The target stylesheet
 */
function cloneCSSStyleSheet(srcSheet: CSSStyleSheet, targetSheet: CSSStyleSheet): CSSStyleSheet;

Configuration Types

interface IStyleSheetConfig {
  /** CSS rule injection strategy */
  injectionMode?: InjectionMode;
  /** Default prefix for generated class names */
  defaultPrefix?: string;
  /** Namespace for CSS rules */
  namespace?: string;
  /** Whether stylesheet is in Shadow DOM */
  inShadow?: boolean;
  /** Window object reference */
  window?: Window;
  /** RTL mode flag */
  rtl?: boolean;
  /** Custom class name cache */
  classNameCache?: { [key: string]: string };
  /** Content Security Policy settings */
  cspSettings?: ICSPSettings;
  /** Key for stylesheet identification */
  stylesheetKey?: string;
  /** @deprecated Legacy rule insertion callback */
  onInsertRule?: (rule: string) => void;
}

interface ICSPSettings {
  /** Nonce value for CSP compliance */
  nonce?: string;
}

interface ISerializedStylesheet {
  /** Cached class name to arguments mapping */
  classNameToArgs: Stylesheet['_classNameToArgs'];
  /** Class name generation counter */
  counter: Stylesheet['_counter'];
  /** Key to class name mapping */
  keyToClassName: Stylesheet['_keyToClassName'];
  /** Preserved CSS rules */
  preservedRules: Stylesheet['_preservedRules'];
  /** All generated rules */
  rules: Stylesheet['_rules'];
}

/** Extended CSSStyleSheet with metadata */
type ExtendedCSSStyleSheet = CSSStyleSheet & {
  bucketName: string;
  metadata: Record<string, unknown>;
};

/** Callback for sheet addition events */
type AddSheetCallback = ({ key, sheet }: {
  key: string;
  sheet: ExtendedCSSStyleSheet;
}) => void;

/** Callback for rule insertion events */
type InsertRuleCallback = ({ key, sheet, rule }: {
  key: string;
  sheet: CSSStyleSheet;
  rule: string;
}) => void;

Injection Modes

Different strategies for CSS rule injection:

const InjectionMode = {
  /** No injection - use getRules() to read styles */
  none: 0,
  /** Insert rules using insertRule API */
  insertNode: 1,
  /** Append rules using appendChild */
  appendChild: 2,
} as const;

type InjectionMode = (typeof InjectionMode)[keyof typeof InjectionMode];

Usage Examples:

import { Stylesheet, InjectionMode } from "@fluentui/merge-styles";

// Server-side rendering - no injection
const ssrStylesheet = new Stylesheet({
  injectionMode: InjectionMode.none
});

// Client-side with insertRule API
const clientStylesheet = new Stylesheet({
  injectionMode: InjectionMode.insertNode
});

// Legacy appendChild method
const legacyStylesheet = new Stylesheet({
  injectionMode: InjectionMode.appendChild
});

Feature Detection Constants

Constants for browser feature detection:

/** Browser supports constructable stylesheets */
const SUPPORTS_CONSTRUCTABLE_STYLESHEETS: boolean;

/** Browser supports modifying adopted stylesheets */
const SUPPORTS_MODIFYING_ADOPTED_STYLESHEETS: boolean;

Server-Side Rendering Support

Stylesheet serialization and hydration for SSR:

// Server-side: serialize stylesheet state
const stylesheet = Stylesheet.getInstance();
// ... generate styles during SSR
const serializedState = stylesheet.serialize();

// Client-side: hydrate with serialized state
const hydratedStylesheet = new Stylesheet(
  { injectionMode: InjectionMode.insertNode },
  JSON.parse(serializedState)
);