# Choose how to deliver CSS

> Pick between a shared stylesheet and per-component styles, then follow the page that implements it.

Pick the CSS delivery that fits: one shared sheet for utility classes, or per-component styles for rules one component owns. The table decides it; the linked pages do it.

## Decide in one table

A shared stylesheet is one `CSSStyleSheet` object adopted by many shadow roots. The top three rows deliver one; the bottom two give each component its own copy.

| Shape                             | Use when                                                                     | What an edit does                             | Page                                                      |
| --------------------------------- | ---------------------------------------------------------------------------- | --------------------------------------------- | --------------------------------------------------------- |
| `?css-sheet`                      | many components share a sheet and you want it cached as its own `.css` asset | restyles every adopter in place, no re-render | [?css-sheet](/guides/stylesheets/css-sheet/)              |
| `urlSheet()`                      | the same, but you need a custom fetch or code that runs without this plugin  | restyles every adopter in place, no re-render | [urlSheet()](/guides/stylesheets/url-sheet/)              |
| `?raw` into one shared module     | many components share a sheet and first paint must not flash                 | restyles every adopter in place, no re-render | [Component styles](/guides/stylesheets/component-styles/) |
| `?hmr-url` `<link>`               | rules one component owns, kept as a real `.css` asset                        | re-renders that component                     | [Component styles](/guides/stylesheets/component-styles/) |
| `?raw` or `?inline` + `unsafeCSS` | rules one component owns, shipped in the JS chunk                            | re-renders that component                     | [Component styles](/guides/stylesheets/component-styles/) |

A re-render is cheap for one component’s own rules and expensive for a layer every component adopts. [CSS delivery](/concepts/css-delivery/) has the measurements behind that.

## Shared sheet for Tailwind or UnoCSS

A generated utility sheet is the case the top rows exist for. Every component adopts the same object, so a regenerated file restyles the whole app without re-rendering anything.

Choose by where the bytes should live. `?css-sheet` and `urlSheet()` keep the CSS as a separate, content-hashed `.css` asset, at the cost of FOUC: a brief flash of unstyled content while the stylesheet is still loading. The inline shared module ships the bytes in a JS chunk. There is no fetch and no flash, but the CSS is not cacheable on its own.

Cancel the flash

Add `<link rel="preload" as="style" href="…">` to the document head. The fetch is then already in flight when the first component mounts.

## Compose a shared sheet with component styles

`static styles` takes an array, so the two shapes stack. Put the shared sheet first and the component’s own `css` block after it, and the later rules win at equal specificity.

```ts
import {LitElement, html} from 'lit';
import {customElement, property} from 'lit/decorators.js';
import utilitySheet from './hmr-utility-sheet.js';

/**
 * Button styled via utility classes from a shared stylesheet — simulates a
 * Tailwind/UnoCSS workflow. All utility consumers update in place when the
 * generated CSS changes (e.g. a new theme color), without re-rendering.
 *
 * Approach benefits/problems: see `hmr-utility-sheet` (fetched shared sheet).
 */

@customElement('hmr-utility-btn')
export class HmrUtilityBtn extends LitElement {
  static override styles = [utilitySheet];

  @property()
  variant: 'blue' | 'red' = 'blue';

  private renders = 0;

  override render() {
    const bgClass = this.variant === 'blue' ? 'bg-blue' : 'bg-red';
    return html`
      <button
        class="${bgClass} text-white font-bold py-2 px-4 rounded border-none cursor-pointer"
      >
        <slot></slot>
      </button>
      <span class="font-mono text-xs" id="badge">renders: 0</span>
    `;
  }

  override updated() {
    this.renders++;
    this.setAttribute('data-renders', String(this.renders));
    const badge = this.renderRoot.querySelector('#badge');
    if (badge !== null) {
      badge.textContent = `renders: ${this.renders}`;
    }
  }
}
```

## Related

[CSS delivery](/concepts/css-delivery/)Why one shared sheet beats N copies, with numbers.

[Share one stylesheet with ?css-sheet](/guides/stylesheets/css-sheet/)The zero-boilerplate shared sheet, start to finish.
