Use plain JavaScript also known as Vanilla JS to make your server side rendered pages dynamically the way you can do it in Vue JS with only 8,4kb costs. Sounds great? Try Alpine.js.
Alpine.js - Originally developed for Livewire
Alpine.js was originally built for Livewire, a full-stack framework for Laravel. Livewire uses Alpine.js to get the dynamic parts done.
Alpine.js was first released as version 0.1.0 by Caleb Porzio on 29 Nov 2019 and the version 1.0 was released on 19 Dec 2019 - quite fresh for my understanding 😁.
Alpine.js is my alternative to jQuery but no alternative to Vue js. I use Alpine.js to make html dynamically the way I love it with Vue JS. Thanks to Vanilla JavaScript you don’t need a special framework anymore but to make frontend development easier and more comfortable you need the perfect piece of a puzzle to glue things together - with a low cost of data.
How Alpine.js works
With Alpine.js you can use data binding models, show and hide or even don’t render elements to the DOM. Event handling is as easy as it is in Vue JS and there are also loops and conditions - even transitions are easy to use.
Alpine.js offers you the reactive and declarative nature of big frameworks like Vue JS or React for a much lower price of bandwidth. The typical use case for Alpine.js is if you have server side rendered pages from Laravel or Kirby CMS and you want to add dynamic parts to it. Dynamic parts like dropdowns, buttons, navigation, image galleries, paginations or modals. The syntax is very similar to Vue JS but Alpine.js has no virtual dom. So if you want to use for-loop you have to create new DOM nodes with .
Alpine.js - Easy to set up and no build process
Starting with Alpine.js is extremely easy. Add the link to Alpine.js form a CDN into the head of your HTML file and be sure that you have defer as attribute in your link.
<script
src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js"
defer
></script>
The attribute “defer” means that the browser will execute the script after the document has been parsed. After loading the 8,4kb from a CDN you can use the magic of Alpine.js in your HTML code. Now you can replace jQuery with declarative rendering - what is that?.
Basic example in Alpine.js
Take a look on my basic example of Alpine.js - no separate javascript file - no script tag - play around on Codepen :
Data binding, conditions and loops
Everything starts in Alpine.js with x-data. It tells the framework to initialize the new component with this data object. Similar to the data object in Vue JS. You add the object right there or from a reusable function.
In more complex situations you will love x-init. This gives you the ability to call a function with an object as parameter right after Alpine.js has made its initial updates to the DOM. For interactions Alpine.js provides a lot of predefined events. You can add a click to an element, prevent the default behaviour or do exactly the opposite call a function if you clicked outside of the element.
<div x-data="{click: false}">
<a href="#" @click.prevent="click=!click;alert('Hello Alpine.js: ' + (click ? 'true' : 'false'))">
Don’t click me
</a>
<a href="#" @click.away="click:false;alert('Hello Alpine.js')">
Catch me if you can
</a>
</div>
Try this more complex example of an accordion with Alpine.js and Tailwind CSS with some random data from JSONPlaceholder.
Plugins for Alpine.js
In some comparisons between jQuery and Alpine.js you will find the question about plugins. Do Alpine.js have plugins? Well yes and no would be the right answer.
To build a component with Alpine.js is relatively simple. You just need to copy and paste some code and that’s it - or should it be. Every Alpine component ist just a function making them relatively uncomplicated to share by including the code on different pages. Because any magic properties are added when Alpine initializes so you can rely on this.
The Alpine.js community is growing fast and you can already find websites with a lot of reusable components and toolboxes. You can find Accordions, Carousels, Forms, Galleries, Modals, Navigation, Paginations or Tables on sites like Alpine Toolbox.
State management in Alpine.js
Since the beginning I was working with Alpine.js I was asking myself: Is there a good way to exchange data between different components on the page - something like Vuex, or Redux.
Wouldn’t it be amazing if the values could be stored in the local storage so you have access to this data every time someone is switching to this page? Well you can have an object stored in the window object and you can save and fetch data from it. This is fine if you just have to handle basic functionalities but it doesn’t feel smooth and right to solve it this way.
So after some research I found Spruce - A lightweight global state management layer for Alpine.js - and it does exactly what I was looking for. If you are dealing a lot with static websites and want to have a lean and lightweight approach try out Spruce with Alpine.js - you will love it. You can find out more about Spruce and Alpine.js in my article “Lightweight state management for Alpine.js” - come and dive into the details.
How to get access to data from different AlpineJS components
The best way to use x-cloak in Alpine JS
TA-Styled-Plugins
Furthermore you might check out my image gallery and my pagination for articles, content or lists. Most TA-Styled-Plugins are used on my website and all are published on my GitHub account under the MIT licence - so free for commercial use.
- TA-Gallery - A light-weight, responsive and mobile first image gallery based on Tailwind CSS and Alpine.js.
- TA-Pagination - A light-weight, responsive and mobile first pagination for content, based on Alpine.js and Tailwind CSS.
- TA-YouTube - A YouTube video wrapper with auto playback, aspect ratio and privacy settings.
- TA-Analytics - An easy and customizable Google Analytics “blocker”.
- TA-Foodtrucks - An easy way to show the next food truck and street food dates in your area.
TA-Foodtrucks example: Codepen works fine with Alpine.js, Tailwind CSS and plugins.
Upgrade to Alpine.js version 3
There are some breaking changes in Alpine.js version 3 if you are planning to upgrade from version 2.
- $el is now always the current element
- No need for an extra call of x-init=”init()” - Version 3 automatically evaluates the init() functions defined in your data object
- x-show.transition is now x-transition
- x-if no longer supports x-transition
- x-data does have a cascading scope - this means you can access all element children - even if inside another or a nested x-data component.
- x-spread is now x-bind
- IE11 no longer supported - Important - If you still want to support IE11 you should stay with version 2.
You can find the full upgrade from V2 guide on the official documentation.
Dive into Alpine.js
You can find a lot of great introductions to Alpine.js on YouTube.
If you have a Scrimba account you can enjoy Andre’s “Learn Alpine.js” course and if you are a member of laracast you have to check out the the courses Building Alpine.jsby Caleb Porzio (Creator of Alpine.js) and Alpine.js Essentials.
All links in a practical list
Related articles
How to get access to data from different AlpineJS components
The best way to use x-cloak in Alpine JS
TA-Gallery - responsive and mobile first image and content gallery
Various topics
Hugo - The world’s fastest static website engine
Are you searching for a really fast static website generator and do you want to improve your SEO and web vitals? Then you have to take a look at the JAMstack architecture.
Tailwind CSS - my CSS framework of choice
If you’re sick of tweaking the CSS framework you are using, don’t want to override unwanted styles anymore and are a big fan of modularisation, then Tailwind CSS was made for you.
Alpine.js – like Tailwind CSS for JavaScript
Use plain JavaScript also known as Vanilla JS to make your server side rendered pages dynamically the way you can do it in Vue JS with only 8,4kb costs. Sounds great? Try …
VueJS javascript framework and why I love it
Several years ago I started building web apps with React JS and I reached the point where I was thinking to myself, does it always have to be so complex even for smaller …