Skip to content

Choosing directive vs. attribute

The directive decides where. The attribute decides when.

  • Reach for wire:ghost when you’re marking up a specific element and want the skeleton scoped to exactly that subtree — the common case for a single table, card grid, or panel.
  • Reach for #[Ghost] when you want a whole component’s behavior configured without touching its view at all — ideal for bulk-migrating many existing components, or for method-level overrides tied to specific actions rather than specific markup.

Scope the skeleton to one element’s subtree, right in the view:

<div wire:ghost.delay.100ms>
<h2>{{ $product->name }}</h2>
<p>{{ $product->description }}</p>
</div>

They compose: put #[Ghost(mode: 'freeze')] on the class as the default, then a wire:ghost.delay.50ms directive on one particularly slow-loading element inside it to override just that host’s timing. The precedence cascade in /docs/ghost-attribute resolves the combination.

If you’re migrating 60 legacy components without touching any view — put #[Ghost] on the base class they share: under the default strategy: 'opt-in', the inherited attribute instruments every subclass, so no strategy: 'global' is needed; add directive-level overrides only where a specific element needs different timing or mode than the rest of its component.