Alpine.js x-ref Directive — Complete Guide with Examples
In this tutorial, you'll learn about the Alpine.js x-ref directive. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
The Alpine.js x-ref directive assigns a name to a DOM element so you can reference it directly in Alpine expressions using the $refs magic property.
What You'll Learn
By the end of this tutorial, you'll use x-ref to access DOM elements, read their properties, integrate with third-party libraries, and manage focus and measurements.
Why It Matters
Sometimes you need direct access to a DOM element: to focus an input, measure its dimensions, scroll to it, or pass it to a third-party library. Alpine's reactivity handles state, but x-ref bridges the gap to raw DOM access.
Real-World Use
Doda Browser's search bar uses x-ref to auto-focus the input when the user presses Ctrl+K. The ref provides direct access to the input element for calling .focus() without needing document.querySelector.
Where This Fits in Your Learning Path
flowchart LR
A["x-html Directive"] --> B["**x-ref Directive**"]
B --> C["x-teleport Directive"]
C --> D["x-init & x-effect"]
D --> E["Advanced Alpine Patterns"]
style B fill:#f97316,stroke:#c2410c,color:#fff
style A fill:#e5e7eb,stroke:#9ca3af,color:#374151
style E fill:#22c55e,stroke:#16a34a,color:#fff
What is x-ref?
x-ref assigns a reference name to an element. You access it via $refs.name in any Alpine expression within the same component.
Think of x-ref like putting a sticky note on an item. Instead of searching through the room (the DOM) every time you need it, the sticky note tells you exactly where it is.
<div x-data>
<input type="text" x-ref="nameInput" placeholder="Enter name">
<button @click="$refs.nameInput.focus()">Focus Input</button>
</div>
Expected output: Clicking the button places focus on the input field.
Reading Element Properties
Use $refs to read element properties like value, offsetHeight, or scrollTop.
<div x-data="{ scrollPos: 0 }">
<div x-ref="scrollContainer" @scroll="scrollPos = $refs.scrollContainer.scrollTop" style="height:100px;overflow:auto" class="border p-2">
<div style="height:300px">
Scroll down to see position
</div>
</div>
<p>Scroll position: <span x-text="scrollPos"></span></p>
</div>
Expected output: As you scroll the container, the scroll position updates in real time.
Integrating with Third-Party Libraries
Pass $refs elements to external libraries like charts or date pickers.
<div x-data x-init="() => {
// Simulate initializing a chart on the canvas
const ctx = $refs.canvas.getContext('2d')
ctx.fillStyle = 'blue'
ctx.fillRect(10, 10, 100, 50)
}">
<canvas x-ref="canvas" width="200" height="100" class="border"></canvas>
</div>
Expected output: A blue rectangle drawn on the canvas element.
Managing Focus with $nextTick
When you need to focus an element after a state change, use $nextTick to wait for Alpine to update the DOM.
<div x-data="{ editing: false, name: 'Alice' }">
<template x-if="editing">
<input x-ref="editInput" x-model="name" @keydown.escape="editing = false"
x-init="$nextTick(() => $refs.editInput.focus())">
</template>
<button @click="editing = true" x-show="!editing">Edit</button>
<p x-text="name"></p>
</div>
Expected output: Clicking Edit replaces the name with an input that is immediately focused. Pressing Escape cancels editing.
Common Mistakes
1. Trying to access $refs before the element exists
If the element is behind an x-if or x-show, $refs may be undefined. Always use optional chaining or check existence.
2. Using $refs outside an Alpine expression
$refs is only available inside Alpine expressions (x-text, x-init, @click, etc.). It is not available in external script tags.
3. Using $refs between different components
Each component has its own $refs scope. You cannot access a ref from a parent or sibling component directly.
4. Forgetting that $refs is not reactive
$refs provides a reference to the DOM element itself, not a reactive property. Changes to the element's properties do not trigger Alpine updates.
5. Using the same ref name multiple times
If multiple elements share the same x-ref name, $refs.name returns the last one in the DOM. Use unique names.
Practice Questions
How do you access a referenced element? Use
$refs.refNamein any Alpine expression within the same component.What can you do with a $refs reference? Call DOM methods (focus, click, scroll), read properties (value, offsetHeight, scrollTop), and pass to libraries.
Why use $nextTick with $refs? $nextTick ensures the DOM has updated before accessing the ref, which is necessary after Alpine creates or modifies elements.
Is $refs available across components? No. Each component has its own isolated $refs scope.
Can you use x-ref on SVG elements? Yes. x-ref works on any DOM element, including SVG.
Challenge
Build an inline editor that switches between text display and an input on click. Use x-ref and $nextTick to auto-focus the input when it appears. On Enter or blur, save and switch back.
FAQ
Mini Project
Build a draggable panel using x-ref. The panel header is the drag handle. Use mouse events to read the mouse position and apply it as CSS transform on the panel element via $refs.
<div x-data="{ dragging: false, offsetX: 0, offsetY: 0, posX: 0, posY: 0 }"
@mousemove="if (dragging) { posX = $event.clientX - offsetX; posY = $event.clientY - offsetY }"
@mouseup="dragging = false">
<div x-ref="panel"
:style="`transform: translate(${posX}px, ${posY}px); cursor: ${dragging ? 'grabbing' : 'grab'}`"
class="absolute w-64 p-4 bg-white shadow-lg rounded-lg border">
<div @mousedown="offsetX = $event.offsetX; offsetY = $event.offsetY; dragging = true"
class="font-bold mb-2 pb-2 border-b" style="cursor: grab">
Drag me
</div>
<p>This panel can be dragged around the page.</p>
</div>
</div>
What's Next
Continue with advanced directives:
| Tutorial | What You'll Learn |
|---|---|
| x-teleport Directive | Move elements to different parts of the DOM |
| x-init Directive | Run initialization code in components |
Related topics: DOM API reference, event handling.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro