Alpine.js Magic Variables

Understanding $el, $refs, and $root with a Closet Analogy

$el: The Current Outfit

$el refers to the DOM element the Alpine directive is on. It's perfect for an element to modify itself. Here, clicking a button is like "trying on an outfit" — the button styles itself.

Interactive Demo

Code Example

<!-- The button modifies itself on click -->
<button @click="tryOnOutfit($el)">...</button>

<script>
Alpine.data('elDemo', () => ({
  tryOnOutfit(element) {
    // Direct DOM manipulation on the element
    element.innerText = 'Outfit Chosen!';
    element.classList.add('ring-4', 'ring-offset-2');
    // ...
  }
}))
</script>

$refs: Named Storage Areas

$refs lets you access any element within your component that has an x-ref attribute. It's like having labeled bins in your closet; you can grab items from any bin by its name.

Interactive Demo

Use the controls to select items from their storage areas:

👕 Shirt Hanger
👖 Pants Rack
👟 Shoe Box

Code Example

<!-- Control button -->
<button @click="getItem('shoeBox')">...</button>

<!-- Named element -->
<div x-ref="shoeBox">...</div>

<script>
Alpine.data('refsDemo', () => ({
  getItem(refName) {
    // Access a specific element by name
    const area = this.$refs[refName];
    area.classList.add('bg-green-200');
    // ...
  }
}))
</script>

$root: The Entire Closet

$root refers to the root element of an Alpine component. It's useful for a nested element to affect its top-level container. This is like tidying up — an action inside the closet affects the whole closet.

Interactive Demo

This is the closet interior.

A shelf inside the closet.

Code Example

<div x-data="rootDemo"> <!-- This is $root -->
  <div>
    <button @click="tidyCloset($root)">...</button>
  </div>
</div>

<script>
Alpine.data('rootDemo', () => ({
  tidyCloset(rootElement) {
    // Access the component's top-level element
    rootElement.classList.add('bg-purple-100');
    // ...
  }
}))
</script>