← All articles
Using a separate Tailwind configuration for your landing page in Astro

Using a separate Tailwind configuration for your landing page in Astro

  • Written by Yaroslav Lapin on

Introduction

This tutorial will guide you through the steps of introducing a second Tailwind configuration for your landing page in Astro, allowing you to overcome the common challenge of managing different design requirements for different parts of your site.

Astro is an all-in-one web framework that enables you to build websites and web applications with a frontend framework of your choice. Although examples in this tutorial are limited to a static website, you can use the same approach for other frameworks, like Next.js, Nuxt.js, SvelteKit, SolidStart, Qwik, etc., with minor adjustments.

In the previous article of the series, we covered how to set up a custom Tailwind CSS configuration in Astro, going beyond the standard @astrojs/tailwind integration for more control and flexibility. In this article, we’ll apply our learnings to cover an example of employing multiple Tailwind configurations in one Astro project.

Clearly, the most straightforward approach is to use the same Tailwind configuration for the whole project. However, you might find yourself in a situation where you have contradicting requirements - for example, your marketing page and app call for different fonts. (This happens more often than you might think, as different teams tend to move at different velocities.) You may not want to make both pages slower by downloading two sets of fonts, so while using two separate Tailwind configurations is more complex, it might be the right thing to do in your situation.

Example template

If you’d like to play around with the code covered in this tutorial, it’s available at https://github.com/JLarky/astro-tailwind-advanced-template.

Prerequisites

If you don’t have your Astro project set up yet, you’d need to use one where Tailwind CSS is already set up correctly.

As a shortcut, you can quickly get going with our B2B SaaS Kit template. Alternatively, you can use the following minimal Tailwind CSS configuration:

npm create astro@latest -- --template JLarky/astro-tailwind-template ./astro-tailwind
cd ./astro-tailwind

For existing projects, you have to follow our guide on customizing Tailwind CSS in Astro before moving forward. The main requirement is that you are either not using the @astrojs/tailwind integration at all, or at least you are not using it on every page. You can achieve this with the applyBaseStyles: false option in your astro.config.mjs file, which is also covered in the aforementioned article.

Using a separate Tailwind config for your landing page

Suppose, you are launching a new product campaign and need a distinct landing page. Your marketing org hired a stellar designer who came up with nice-looking designs for the page - and even used Tailwind CSS!

Unfortunately, the new designs specify a different color palette and different fonts from the rest of your app. You already have everything working in isolation - say, in a separate project, and are now staring at the challenge of figuring out how to combine the existing app and the new marketing page together.

One option is to create one hybrid Tailwind CSS file.

Another option - one we’ll pursue here - is to have everything working in one project while keeping the two Tailwind CSS configuration separate.

Create a landing page

Let’s start by creating a new file for our landing page - src/pages/new-product-landing.astro - with the following content:

---
import Layout from '../layouts/Layout.astro';
---

<Layout title="New Product Landing">
  <main class="container mx-auto">
    <h1 class="text-3xl mt-4 font-heading">New Product Landing</h1>
  </main>
</Layout>

Now, run npm run dev and navigate to http://localhost:3000/new-product-landing. The page is using your main Tailwind configuration - let’s see how we can make it use a different one.

Create a new Tailwind config

Next, create a new file called tailwind.landing.config.cjs in the root of the project, with the following content:

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './src/pages/new-product-landing.astro',
    './src/layouts/Landing.astro',
    './src/components/landing/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}',
  ],
  theme: {
    extend: {
      fontFamily: {
        heading: ['"Comic Sans MS"', 'sans-serif'],
      },
      colors: {
        best: '#ff0000',
      },
    },
  },
};

Let’s narrow in on what’s happening here. In the new Tailwind file, theme.extend.colors and theme.extend.fontFamily represent the designs that we got from the marketing org. Obviously, with a really simple example like the one we have here, we could have easily just expanded our main Tailwind configuration, but real-world scenarios are rarely this simple.

The content property allows us to limit the resulting CSS bundle size by including only the Tailwind classes used in the pages matching the content filter.

For most websites, the content property will not have a major consequence on performance. However, in general, it’s a good idea to make sure your content property only includes those files that actually use Tailwind. If you begin to add Tailwind classes in a file outide the content scope, you’ll see it right away, since the classes you add won’t have any effect.

In our case, we’re including only the new-product-landing.astro page and all the components from the src/components/landing directory. You’d need to adjust this if you’re using common components from other directories.

Exclude landing from the main CSS bundle

Similarly, we need to adjust the content property in our main tailwind.config.cjs file in order to exclude the new landing:

/** @type {import('tailwindcss').Config} */
module.exports = {
	content: [
		'./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}',
+		'!./src/pages/new-product-landing.astro',
+		'!./src/layouts/Landing.astro',
+		'!./src/components/landing/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}',
	],
};

Although not widely known, the content property supports excluding patterns. By specifying the patterns we used in the new tailwind.landing.config.cjs, but with a ! in front, we’re ensuring Tailwind classes used in the new landing page are not included in the main CSS bundle.

Again, we’re bothering with content just to optimize the resulting CSS bundle size - none of it will have any effect on functionality. If it makes sense in your scenario, you can safely skip these steps.

Create a new Tailwind CSS file

Next, let’s create a new Tailwind style file src/styles/tailwind.landing.css with the following content:

@config "../../tailwind.landing.config.cjs";

@tailwind base;
@tailwind components;
@tailwind utilities;

Here, we’re using the @config directive - a feature added in Tailwind CSS v3.2 - that lets you specify a particular Tailwind configuration in a CSS file.

Create a new layout for landing

Since our existing layout is using the main CSS file, we need to create a new layout component for the new landing page.

Let’s create a src/layouts/Landing.astro file with the following content:

---
import '../styles/tailwind.landing.css';
export type Props = {
  title: string;
};
const { title } = Astro.props;
---

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width" />
    <meta name="generator" content={Astro.generator} />
    <title>{title}</title>
  </head>
  <body class="text-best">
    <slot />
  </body>
</html>

As you can see, we imported the new tailwind.landing.css and we’re now using the text-best class for text color.

Use the new layout

Finally, in src/pages/new-product-landing.astro, we need to switch to using the new layout:

---
- import Layout from '../layouts/Layout.astro';
+ import Layout from '../layouts/Landing.astro';
---

<Layout title="New Product Landing">
	<main class="container mx-auto">
		<h1 class="text-3xl mt-4 font-heading">New Product Landing</h1>
	</main>
</Layout>

If you open http://localhost:3000/new-product-landing, you should see the new heading font and best color from the new design. Amazingly, these changes are completely isolated from the rest of your app!

Conclusion

Turns out, Tailwind CSS offers a way to create separate configurations for different pages.

The approach allows developers to use different fonts, color pallettes, animations, and other design elements for specific pages without touching the rest of the app. Doing so may improve the performance of your app by reducing the CSS bundle size, while making the codebase easier to maintain.

Such separation of concerns is especially important for websites built with Astro, since it’s one of the only tools where multiple frontend frameworks can coexist within the same project, making it possible to house a marketing website, blog, docs, app, support - and so on - in a single repo.

If you liked this article, check out the other articles in the series:

Also, check out our Astro templates:

If you’re curious about Fogbender, a good place to start is a post about customer triage rooms.