Let's build together an Image searching with these two awesome libraries: Alpine.js and Tailwind CSS
Introduction
Alpine.js is a light, simple, and powerful JavaScript library that is heavily inspired by Vue.js.
Alpine.js is a collection of 14 attributes, 6 properties, and 2 methods; you can think of it as jQuery for the modern web.
However, unlike jQuery — which provides imperative DOM APIs, Alpine.js provides a declarative way to bind data to the DOM using the x-bind directive.
Alpine.js is very beginner-friendly, you barely need to know any JavaScript to get up and running with it.
Like Tailwind CSS which provides a way to build great designs without leaving your HTML, Alpine.js also provides a way to make our DOM interactive without leaving our HTML.
We would be building our Image searching with these two awesome libraries.
Let’s get started with the prerequisite in the next section.
Prerequisite
- Basic knowledge of HTML and CSS
- Basic knowledge of Tailwind CSS
- Basic knowledge of Alpine.js
Getting Started
To get started, first, we will set up our server.
Follow the steps below to create the server:
- Create an npm project and install all the needed dependencies:
In this project, our only dependency is the live-server package; it is a little development server with live reload capability.
- Add our scripts:
Open the package.json file and edit the scripts section as follows:
Now we can start our sever by using: npm start.
- Create application files:
In our application folder, create an index.html file
Add these codes to the index.html file:
In our application boilerplate above, we added both Alpine.js and Tailwind CSS using CDN. Although there are other methods for this — like using npm, CDN satisfies our current needs.
Also, in our code above we have organized our application into two main sections namely the hero section and the footer section. Both of these are wrapped by the container div and the main div — that is the div with the class container and main.
Lastly, added responsive padding to our app container to control the padding of an element at a specific breakpoint using the utility classes below:
With these in place, we can start building our app in the next section.
Building Our Image Searching App
Fetching data and declaring initial state
In this section, we would first declare our app state and construct our Pixabay API for fetching images.
In Alpine.js, we must declare our state in the wrapper components that encapsulates all the component we want to have access to the state. So in this application, we would declare our state in the body element using the x-data directive.
The x-data directive is evaluated as a JavaScript object. And when used on a component to declare state, it provides reactive data for that component and its children.
In other to keep our code clean we would return the object for x-data from the imageGallery function — which we would create later.
To fetch images from Pixabay, we need to get an API key and construct our URL.
Pixabay has a base URL — https://pixabay.com/api/ that takes many parameters. However, in this article, we only need the following:
- Key: your API Key
- q: A URL encoded search term, not more than 100 characters. If omitted all images are returned.
- image_type: This parameter is a string used to filter results by image type. Its values include all, vector, illustration, and photo. The default value is all.
- per_page: The is an integer that determines the number of images per page. It accepts values between the range of 3 - 200. The default value is 20.
- page: The returned search results are paginated and this integer is used to set the page number.
Our constructed URL should look like this:
This URL construct simply says search for all types of food images and returns 36 images per page.
We would use this URL with the x-init directive. The x-init directive enables us to hook into the initialization phase of a component. Hence we can run an expression when the component is initialized. It is used with the x-data directory to set the initial value of a component state.
Now add the following code to the body element — to declare our state, and create the imageGallery function as seen below:
In the code above, the x-init directive fetches data from Pixabay and stores it in the x-data directive before the component is processed. Next, we will move to create our search component in the next section.
Creating the search component
In the hero section add the add code to style the app title:
The code above centralizes the title across the vertical and horizontal axis using these Tailwind CSS flexbox classes:
Below the title add the following code for the search component:
In the code above, our search component is a flex container with three flex items namely: the button component, the input component, and the select component. The search component is wrapped with two components, with the outer component having top padding of 2rem — from the class pt-8.
The custom button component — the search glass, uses the shorthand syntax — @click of the x-on directive to listen for click events. The x-on directive attaches an event listener to an element. In our code above, @click is equivalent to x-on:click. When the button is clicked, the getImages function is called and a new API call is made to Pixabay using the user input as parameters.
Alpine.js also, makes it easy to listen for keyboard events — such as keydown and keyup events, on specific keys. And we are listening for the Enter key event inside our input component by using the .enter modifier as seen below:
So when the Enter key is pressed the getImages method is called. We would create the getImages method in a moment.
The x-model directive is used in the input component to sync the value of q with the component data. Lastly, the select component uses the x-model to bind the value of the image_type to the component data.
The Tailwind utility class, outline-none is used to hide the default browser outline on focused elements throughout our search components.
Now our search component looks like this:
To create the getImages method update the imageGallery function as seen below:
The getImages method uses the same URL construct we used with the x-init directive. However, it uses the component data — user inputs as the values for the parameters. Since we can fetch data from Pixabay we can now start building our image grid.
Building the image grid
Below the code for the search component, add the following code for the image grid:
In the code above, we made our grid responsive by using the {screen}: prefix with the grid-template-columns utility to control the columns of a grid at a specific breakpoint as seen below:
Also, we used the x-for directive to create our image grid by iterating through the images array in the component data. The x-for directive enables us to create a new DOM element by iterating through a list. In Alpine.js, the x-for directory must be declared on a template tag that has only one root element.
Finally, we set the values of the HTML attributes — of the a and img elements by using the x-bind directive. Since the x-bind directive enables us to set HTML attributes on an element based on a JavaScript expression we can reactively bind HTML attributes as seen below:
- :href sets the image link to the value of image.largeImageURL
- :src sets the image src to the value of image.largeImageURL
- :alt sets the image alt to the value of image.tags
With the image grid built we can proceed to add the code for the footer.
The footer
To create the footer add the following code below the image grid — between the “Footer starts” and the “Footer ends” comments:
From the code above, we see that our footer is a flex container that centralizes its flex items vertically and horizontally using the following Tailwind CSS utility classes:
Now our final apps looks like this:
Conclusion
Alpine.js is lightweight; lighter than jQuery. At 7KB — gzipped, Apine.js gives us the reactivity and declarative nature of big frameworks such as React and Vue but at a fraction of their size.
As we have seen in this article, Alpine.js is a great way to easily add interactivity to our UI.
It has a shallow learning curve and you can pick it up with very little JavaScript knowledge.
And following this article, you should be ready to start using Alpine.js in your next project.
You can play with the code for this app on Codepen or get the full source code on Github.
Also, you can easily tryout the live version on Netlify.