# Why I use Alpine.js

> Why I use Alpine.js to add small sprinkles of interactivity to HTML, like closing a modal on an outside click, without reaching for a big frontend framework.

Author: Flavio Copes | Published: 2024-01-15 | Canonical: https://flaviocopes.com/why-i-use-alpinejs/

Alpine.js is a great little library to add "[JavaScript](https://flaviocopes.com/javascript/) sprinkles of interactivity".

That's what JavaScript was created for in the first place: add more life to HTML pages (rather than, for example, run in the browser an entire application framework used to render HTML).

Alpine is concerned with the client-side state, with tiny little bits of JS.

For example tracking the value of an input box, or opening a modal, etc.

You could also just use "vanilla" JavaScript DOM APIs for this, but for some things, Alpine simplifies a lot our job.

I like this a lot paired with server-side HTML generation using [Astro](https://flaviocopes.com/astro-introduction/), and client-server interactions handled through htmx. Alpine is the perfect fit for this stack.

But _why do I use it?_

Let me answer with practical examples of how I used it to solve problems.

One need I had was to close a modal defined in a `dialog` tag when I clicked outside of it.

Using vanilla JavaScript you'd have to do something like this:

```javascript
function onClickOutside(element, callback) {
  document.addEventListener('click', (event) => {
    if (!element.contains(event.target)) {
      callback()
    }
  }, true)
}

const targetElement = document.querySelector('#yourElementId')

onClickOutside(targetElement, () => {
  document.querySelector('dialog').close()
})
```

You need to also come up with a good `id` name for your element, and think where to put this JavaScript.

With Alpine.js, all this JavaScript can be turned into 1 line you put directly on the element:

```javascript
@click.outside.capture="document.querySelector('dialog').close()"
```

It’s much less code, it’s declarative, I don’t have to create an `id` I’ll use just for this, and the logic is local to the HTML element involved (LoB = Locality of Behavior).

Another example is showing/hiding a mobile menu when pressing a “hamburger” icon, kinda typical pattern.

With Alpine you define a `showMenu` var on a container element.

I’ll simulate the hamburger icon with a `show/hide` button.

```html
<div
  x-data='{showMenu : false}'>
	<button
	  @click='showMenu = !showMenu'>
	  show/hide
	</button>
  <div x-show='showMenu'>
    ...the menu
  </div>
  ...the rest of your app
</div>
```

Click the button to show the menu content, click again to hide it.

Those were just 2 simple examples, but I hope you got the gist.

If you want a quick reference of all the Alpine directives with live examples, check my free [Alpine.js cheatsheet](https://flaviocopes.com/tools/alpine-cheatsheet/).
