Styling Astro Apps with Tailwind CSS
Published: 2023-05-23 23:36:16

by [Jude Miracle](https://blog.openreplay.com/authors/jude-miracle)

<blockquote><em>Tailwind CSS is a popular utility-first CSS framework that greatly benefits developers when developing user interfaces. It allows developers to quickly and easily add styles to their applications without writing much CSS code. This article will teach you to take advantage of it to the fullest extent!</em></blockquote>

In this guide, we'll go through how we can install and use [Tailwind CSS](https://tailwindcss.com/) with [Astro](https://astro.build/), an all-in-one web framework that has been gaining popularity for its lightweight nature and blazing-fast, content-focused websites. It contains the right building blocks out of the box, such as helpful utility classes, JIT mode, scroll snap API, and more, enabling developers to get up and running in minutes. Additionally, we'll learn how to make API requests in Astro by building a demo Astro application, whose styling will be done with Tailwind CSS.


## Why use Tailwind CSS?

Tailwind CSS speeds up the creation and maintenance of your application's code by employing utility classes to regulate your application's padding, margin, color, font, shadow, and other features. It helps improve team efficiency by reducing the time they switch between files and writing custom CSS classes. Because it promotes a uniform approach, it also makes debugging our styles simpler.

It makes building complex responsive layouts easy; thanks to the help of utility classes, you can use any number of breakpoints to make your design come alive conditionally without the need for Global Styles. 

Tailwind CSS is highly customizable. It has a built-in default configuration that can be simply customized by making adjustments to the `tailwind.config.js` file. Its configuration file allows developers access to everything (including color schemes and stylesheets). It also opens a world of opportunities for third parties by allowing developers to extend or add custom plugins.


## Setup a new Astro project

To create an Astro application, run the command below on your terminal:



```
// NPM
npm create astro@latest

// YARN
yarn create astro
```


This command will guide you through each stage of creating your new Astro project. You can select from different official starter templates or create a new project from an existing Astro GitHub repository by running the command below:

```
// NPM
npm create astro@latest -- --template <github-username>/<github-repo>
    
// YARN
yarn create astro --template <github-username>/<github-repo>
```


Note: you can also browse their collection of themes and starters to find themes for landing pages, blogs, portfolios, and more!

If all goes well and you will be presented with the message "Ready for liftoff!", move to the newly created project folder using the `cd` command to begin using Astro:

```
cd <project name>
```

Next, to view your new website in action, run the following command in your terminal:

```
yarn run dev
```
    
If no other application is running on port 3000, the command above starts a local development server.

Visit [http://localhost:3000/](http://localhost:3000/)  to see the app in action.

![-](https://blog.openreplay.com/images/styling-astro-apps-with-tailwind-css/images/qGMCSfH.png)


## Integrating Tailwind CSS into our Astro app

Tailwind CSS works well with Astro, and it is also easy to integrate it into your application. To integrate it into our newly created Astro project, run the command below in the terminal:

```
yarn astro add tailwind
```


The installation is automated using the `astro add` command line tool. The command above creates a `tailwind.config.cjs` configuration file, and will automatically set up the appropriate package (@astrojs/tailwind) in your `astro.config.mjs` file. This will allow us to customize Tailwind CSS to standard.


```javascript
import { defineConfig } from "astro/config";
import tailwind from "@astrojs/tailwind";

export default defineConfig({
  // ...
  integrations: [tailwind()],
});
```


With this, our `.astro`, React, Vue, Svelte, and other files can now use Tailwind CSS classes. Now let's include the classes in the `h1` and `span` tags of our `pages/index.astro` file to verify that our installation worked as expected:


```html
<h1 class="text-blue-600 bg-black tracking-tight">
  Welcome to
  <span class="text-yellow-500">Astro</span>
</h1>
```
    

Now restart the development server to see the changes.

![-](https://blog.openreplay.com/images/styling-astro-apps-with-tailwind-css/images/MkiL4Ar.png)



Alternatively, you can manually add Tailwind CSS to your Astro site or app by installing the following dependencies:

```
npm install @astrojs/tailwind tailwindcss
```


Then integrate Tailwind CSS into your `astro.config.*` file using the `integrations` property:


```javascript
import { defineConfig } from "astro/config";
import tailwind from "@astrojs/tailwind";

export default defineConfig({
  // ...
  integrations: [tailwind()],
});
```
## Building and Styling our Astro application with Tailwind CSS

In this section, we'll create and style a simple Astro application that makes an API call to the [Consumet API](https://docs.consumet.org/) and fetches a list of top-airing anime. We'll style and display the results using Tailwind CSS.


> Consumet is a search engine API for gaining access to data and links for numerous forms of entertainment, including movies, novels, anime, and other media.

Our final application should appear as follows:


![-](https://blog.openreplay.com/images/styling-astro-apps-with-tailwind-css/images/5u2pnHE.png)



## Creating a Layout

We'll use the `Layout` component to create our navigation section. It will contain our app logo and search input for our application's landing page. Inside your `layouts/Layout.astro` file, add the following code:

```javascript
---
export interface Props {
  title: string;
}
const { title } = Astro.props;
---
```
The `Astro.props` object is a container that stores any values passed as attributes to a component.

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg"/>
    <meta name="generator" content="{Astro.generator}" />
    <title>{title}</title>
  </head>
  <body class="w-full">
    <nav
      class="py-4 px-[200px] border-gray-200 bg-gradient-to-tr from-gray-700 via-gray-900 to-black"
    >
      <div class= "flex flex-wrap items-center justify-between mx-auto">
        <a href="#" class="flex items-center">
          <span class= "self-center text-xl font-semibold whitespace-nowrap text-white"
            >Tailwind CSS Anime Hub</span
          >
        </a>
        <div class= "hidden w-full md:block md:w-auto">
          <input
            type= "search"
            id= "search"
            class="block w-full p-4 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg"
            placeholder= "Search"
          />
        </div>
      </div>
    </nav>
    <slot />
  </body>
</html>
```

The class name `w-screen` sets the body of our to `100vw`. We added `flex` to set our logo and input field side by side.



<div style="background-color:#efefef; border-radius:8px; padding:10px; display:block;">
<hr/>
<h3><em>Session Replay for Developers</em></h3> 
<p><em>Uncover frustrations, understand bugs and fix slowdowns like never before with <strong><a href="https://github.com/openreplay/openreplay" target="_blank">OpenReplay</a></strong> — an open-source session replay suite for developers. It can be <strong>self-hosted</strong> in minutes, giving you complete control over your customer data.</em></p>
<img alt="OpenReplay" style="margin-top:5px; margin-bottom:5px;" width="768" height="400" src="https://raw.githubusercontent.com/openreplay/openreplay/main/static/openreplay-git-hero.svg" class="astro-UXNKDZ4E" loading="lazy" decoding="async">
<p><em>Happy debugging! <a href="https://openreplay.com" target="_blank">Try using OpenReplay today.</a></em><p>
<hr/>
</div>



## Hero component

Now, let's build our `Hero` component and add styles to it. In the components folder, create a file `Hero.astro` and the code below:


```html
<header class="bg-gradient-to-tr from-gray-700 via-gray-900 to-black w-full">
  <div class="py-16 px-[200px] text-white">
    <h1 class="text-4xl mb-4">Welcome to our Anime Hub</h1>
    <p>
      It was built using API generated from
      <a
        href="https://docs.consumet.org/"
        class="py-1 px-3 text-gray-700 bg-white rounded"
      >
        Consumet
      </a>
    </p>
  </div>
</header>;
```


In the code above, we added a background color for our `Hero` section using the following class names `bg-gradient-to-tr`, `from-gray-700`, `via-gray-900`, `to-black`, and we also specified a large font  `text-4xl` to our `h1` tag and padding top and bottom of 4rem using `py-16` and padding left and right of 200px using `px-[200px]` to our `div`. The `text-4xl` class increases the font size to 36px, `text-white` changes the text color to white, and `py-16` adds a padding of 64px to the top and bottom of the text.

## Building our `Card` component

Next, we'll build a simple `Card` component that will house the cover image, title, and URL of the anime. The data rendering here will be fetched from the index page. Now in our components folder, create a file `Card.astro` and add the code below:


```javascript
---
const { anime } = Astro.props;
---
```


```html
<a
  href={anime.url}
  class="group h-72 md:h-96 flex justify-end items-end bg-gray-100 overflow-hidden rounded-xl shadow-lg relative hover:shadow-xl"
>
  <figure class="w-full h-full flex object-cover object-center absolute inset-0 group-hover:scale-110 transition duration-200 text-transparent">
    <img src={anime.image} alt={`${anime.title} cover image`} />
  </figure>
  <div class="bg-gradient-to-t from-black via-transparent to-transparent opacity-20 absolute inset-0 pointer-events-none group-hover:opacity-0 transition duration-200" />
  <span class="inline-block text-gray-200 text-xs md:text-sm border border-gray-500 rounded-lg backdrop-blur relative px-2 md:px-3 py-1 mr-3 mb-3 group-hover:opacity-0 transition duration-200">
    {anime.title}
  </span>
</a>;
```


In the code block above, Astro allows us to write javascript and Typescript code within the --- block. It also allows us to use `Astro.props` to pass data throughout our Astro component. We then styled our app using Tailwind CSS classes. We used the `object cover` and `object-center` to make the cover image take the full width and height we specified on the `a` tag and position it at the center. We added a gradient background and used the `backdrop-blur` class to make the background at least partially transparent and blurring. The `sm`, `md`, `lg`, and `xl` prefixes are used to build components and layouts for different screen sizes.


## Fetching and organizing our Data

Now, we'll use our index page to fetch anime from Consumet, then create categories to organize them. First, let's import our components and layout by adding the following code block to our `pages/index.astro` file:

```javascript
---
import Layout from "../layouts/Layout.astro";
import Card from "../components/Card.astro";
import Hero from "../components/Hero.astro";

const response = await fetch(
  "https://api.consumet.org/anime/gogoanime/top-airing"
);
const data = await response.json();
const animes = data.results;
---
```

Based on the code above, we imported our components, and we then used the `fetch()` function to make an API request for the Consumet API. The fetch method is executed at build time, and the components will have access to the data to create dynamic HTML.

```html
<Layout title= "Anime Hub.">
  <main>
    <Hero />
    <ul
      role= "list"
      class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4 md:gap-6 xl:gap-8 max-w-screen-xl px-4 md:px-8 mx-auto"
    >
      {animes.length ? (
        animes.map((anime) => <Card anime="{anime}" />)
      ) : (
        <p>No anime at the moment</p>
      )}
    </ul>
  </main>
</Layout>;
```

Here we wrapped our site with the `Layout` component. We use the `ul` tags to iterate over the data from the API and display it between the `Card` components. The `sm:grid-cols-3` sets the grid to 3 columns on a small screen size, while `lg:grid-cols-4` sets the grid to 4 columns on a larger screen size. In the event that no anime is available from our API, we have also added a notice. Even though this is exceedingly unlikely, it is good practice.

In the end, we have this nice-looking layout and animation of our site.

![-](https://blog.openreplay.com/images/styling-astro-apps-with-tailwind-css/images/owXkkSz.gif)



Although this application is quite simple, Tailwind CSS has a ton of different classes that can be utilized to make it much more complex. Visit the official [documentation](https://tailwindcss.com/docs/installation) for further details on all of the Tailwind CSS classes that are offered and how to use them.

## Conclusion

Overall, Tailwind CSS is a powerful and flexible tool that makes it easy to add styles to your Astro applications. By using the classes it provides, you can quickly and easily create a consistent and polished look for your app without having to write a lot of CSS yourself. Its utility-first approach, customization options, low specificity, and fast development make it a popular choice for building modern and responsive user interfaces.