Alpine.js

Your new, lightweight, JavaScript framework.

Get started →
<script src="//unpkg.com/alpinejs" defer></script> <div x-data="{ open: false }">  <button @click="open = true">Expand</button>  <span x-show="open">  Content...  </span> </div>

Simple.

Lightweight.

Powerful as hell.

Alpine is a rugged, minimal tool for composing behavior directly in your markup. Think of it like jQuery for the modern web. Plop in a script tag and get going.

Alpine is a collection of 15 attributes, 6 properties, and 2 methods.

There is no better way to get a feel for what Alpine is and what it can do, than by seeing it for yourself:

x-data

Declare a new Alpine component and its data for a block of HTML

<div x-data="{ open: false }">  ... </div>
x-bind

Dynamically set HTML attributes on an element

<div x-bind:class="! open ? 'hidden' : ''">  ... </div>
x-on

Listen for browser events on an element

<button x-on:click="open = ! open">  Toggle </button>
x-text

Set the text content of an element

<div>  Copyright ©  <span x-text="new Date().getFullYear()"></span> </div>
x-html

Set the inner HTML of an element

<div x-html="(await axios.get('/some/html/partial')).data">  ... </div>
x-model

Synchronize a piece of data with an input element

<div x-data="{ search: '' }">  <input type="text" x-model="search">  Searching for: <span x-text="search"></span> </div>
x-show

Toggle the visibility of an element

<div x-show="open">  ... </div>
x-transition

Transition an element in and out using CSS transitions

<div x-show="open" x-transition>  ... </div>
x-for

Repeat a block of HTML based on a data set

<template x-for="post in posts">  <h2 x-text="post.title"></h2> </template>
x-if

Conditionally add/remove a block of HTML from the page entirely

<template x-if="open">  <div>...</div> </template>
x-init

Run code when an element is initialized by Alpine

<div x-init="date = new Date()"></div>
x-effect

Execute a script each time one of its dependencies change

<div x-effect="console.log('Count is '+count)"></div>
x-ref

Reference elements directly by their specified keys using the $refs magic property

<input type="text" x-ref="content"> <button x-on:click="navigator.clipboard.writeText($refs.content.value)">  Copy </button>
x-cloak

Hide a block of HTML until after Alpine is finished initializing its contents

<div x-cloak>  ... </div>
x-ignore

Prevent a block of HTML from being initialized by Alpine

<div x-ignore>  ... </div>
$store

Access a global store registered using Alpine.store(...)

<h1 x-text="$store.site.title"></h1>
$el

Reference the current DOM element

<div x-init="new Pikaday($el)"></div>
$dispatch

Dispatch a custom browser event from the current element

<div x-on:notify="...">  <button x-on:click="$dispatch('notify')">...</button> </div>
$watch

Watch a piece of data and run the provided callback anytime it changes

<div x-init="$watch('count', value => {  console.log('count is ' + value) })">...</div>
$refs

Reference an element by key (specified using x-ref)

<div x-init="$refs.button.remove()">  <button x-ref="button">Remove Me</button> </div>
$nextTick

Wait until the next "tick" (browser paint) to run a bit of code

<div  x-text="count"  x-text="$nextTick(() => {"  console.log('count is ' + $el.textContent)  }) >...</div>
Alpine.data

Reuse a data object and reference it using x-data

<div x-data="dropdown">  ... </div> ... Alpine.data('dropdown', () => ({  open: false,  toggle() {  this.open = ! this.open  } }))
Alpine.store

Declare a piece of global, reactive, data that can be accessed from anywhere using $store

<button @click="$store.notifications.notify('...')">  Notify </button> ... Alpine.store('notifications', {  items: [],  notify(message) {  this.items.push(message)  } })

I hope you find Alpine to be a breath of fresh air. Silence among noise.

- Caleb