I’m just getting acquainted with Tailwind and generally liking it. I like it as a design system, but I can see why it has its haters. I could easily write two articles, one extolling its virtues and another it’s faults.
I want to address one big complaint: the number of classes and repetition. I will use a ‘timeline’ to illustrate. Taken from Tailwind Elements
<ol class="border-l border-gray-300">
<li>
<div class="flex flex-start items-center pt-3">
<div class="bg-gray-300 w-2 h-2 rounded-full -ml-1 mr-3"></div>
<p class="text-gray-500 text-sm">01.07.2021</p>
</div>
<div class="mt-0.5 ml-4 mb-6">
<h4 class="text-gray-800 font-semibold text-xl mb-1.5">Title of section 1</h4>
<p class="text-gray-500 mb-3">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque scelerisque diam non nisi semper, et elementum lorem ornare. Maecenas placerat facilisis mollis. Duis sagittis ligula in sodales vehicula.</p>
</div>
</li>
<li>
<div class="flex flex-start items-center pt-2">
<div class="bg-gray-300 w-2 h-2 rounded-full -ml-1 mr-3"></div>
<p class="text-gray-500 text-sm">13.09.2021</p>
</div>
<div class="mt-0.5 ml-4 mb-6">
<h4 class="text-gray-800 font-semibold text-xl mb-1.5">Title of section 2</h4>
<p class="text-gray-500 mb-3">Libero expedita explicabo eius fugiat quia aspernatur autem laudantium error architecto recusandae natus sapiente sit nam eaque, consectetur porro molestiae ipsam an deleniti.</p>
</div>
</li>
<li>
<div class="flex flex-start items-center pt-2">
<div class="bg-gray-300 w-2 h-2 rounded-full -ml-1 mr-3"></div>
<p class="text-gray-500 text-sm">25.11.2021</p>
</div>
<div class="mt-0.5 ml-4 pb-5">
<h4 class="text-gray-800 font-semibold text-xl mb-1.5">Title of section 3</h4>
<p class="text-gray-500 mb-3">Voluptatibus temporibus esse illum eum aspernatur, fugiat suscipit natus! Eum corporis illum nihil officiis tempore. Excepturi illo natus libero sit doloremque, laborum molestias rerum pariatur quam ipsam necessitatibus incidunt, explicabo.</p>
</div>
</li>
</ol>
We can simplify this by looping over a data array in a component like this.
---
const data = [
{
date: "01.07.2021",
title: "Title of section 1",
body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque scelerisque diam non nisi semper, et elementum lorem ornare. Maecenas placerat facilisis mollis. Duis sagittis ligula in sodales vehicula.",
},
{
date: "13.09.2021",
title: "Title of section 2",
body: "Libero expedita explicabo eius fugiat quia aspernatur autem laudantium error architecto recusandae natus sapiente sit nam eaque, consectetur porro molestiae ipsam an deleniti.",
},
{
date: "25.11.2021",
title: "Title of section 3",
body: "Voluptatibus temporibus esse illum eum aspernatur, fugiat suscipit natus! Eum corporis illum nihil officiis tempore. Excepturi illo natus libero sit doloremque, laborum molestias rerum pariatur quam ipsam necessitatibus incidunt, explicabo.",
},
];
---
<ol class="border-l border-gray-300">
{
data.map((element) => (
<li>
<div class="flex flex-start items-center pt-3">
<div class="bg-gray-300 w-2 h-2 rounded-full -ml-1 mr-3" />
<p class="text-gray-500 text-sm">{element.date}</p>
</div>
<div class="mt-0.5 ml-4 mb-6">
<h4 class="text-gray-800 font-semibold text-xl mb-1.5">
{element.title}
</h4>
<p class="text-gray-500 mb-3">{element.body}</p>
</div>
</li>
))
}
</ol>
Another option is to create a component for each Timeline element like this.
---
const props = Astro.props;
---
<ol class="border-l border-gray-300">
<li>
<div class="flex flex-start items-center pt-3">
<div class="bg-gray-300 w-2 h-2 rounded-full -ml-1 mr-3"></div>
<p class="text-gray-500 text-sm">{props.date}</p>
</div>
<div class="mt-0.5 ml-4 mb-6">
<h4 class="text-gray-800 font-semibold text-xl mb-1.5">
{props.title}
</h4>
<p class="text-gray-500 mb-3"><slot /></p>
</div>
</li>
</ol>
And use it like this.
---
import TimelineElement from "./TimelineElement.astro";
---
<ol class="border-l border-gray-300">
<TimelineElement date="01.07.2021" title="Title of section 1">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque scelerisque
diam non nisi semper, et elementum lorem ornare. Maecenas placerat facilisis
mollis. Duis sagittis ligula in sodales vehicula.
</TimelineElement>
<TimelineElement date="13.09.2021" title="Title of section 2">
Libero expedita explicabo eius fugiat quia aspernatur autem laudantium error
architecto recusandae natus sapiente sit nam eaque, consectetur porro
molestiae ipsam an deleniti.
</TimelineElement>
<TimelineElement date="25.11.2021" title="Title of section 3">
Voluptatibus temporibus esse illum eum aspernatur, fugiat suscipit natus!
Eum corporis illum nihil officiis tempore. Excepturi illo natus libero sit
doloremque, laborum molestias rerum pariatur quam ipsam necessitatibus
incidunt, explicabo.
</TimelineElement>
</ol>
Finally, we can create Custom Styles in Tailwind. We need some Astro config to make this happen.
astro.config.mjs
import {
defineConfig
} from 'astro/config';
// https://astro.build/config
import tailwind from "@astrojs/tailwind";
// https://astro.build/config
export default defineConfig({
integrations: [tailwind({
// Example: Disable injecting a basic `base.css` import on every page.
// Useful if you need to define and/or import your own custom `base.css`.
config: {
applyBaseStyles: false
}
})]
});
Add src/styles/global.css
and append some Custom Styles
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.timeline-disk {
@apply bg-gray-300 w-2 h-2 rounded-full -ml-1 mr-3;
}
.timeline-date {
@apply text-gray-500 text-sm
}
.timeline-title {
@apply text-gray-800 font-semibold text-xl mb-1.5
}
}
We can use the styles like this.
---
---
<ol class="border-l border-gray-300">
<li>
<div class="flex flex-start items-center pt-3">
<div class="timeline-disk"></div>
<p class="timeline-date">01.07.2021</p>
</div>
<div class="mt-0.5 ml-4 mb-6">
<h4 class="timeline-title">Title of section 1</h4>
<p class="text-gray-500 mb-3">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque
scelerisque diam non nisi semper, et elementum lorem ornare. Maecenas
placerat facilisis mollis. Duis sagittis ligula in sodales vehicula.
</p>
</div>
</li>
<li>
<div class="flex flex-start items-center pt-2">
<div class="timeline-disk"></div>
<p class="timeline-date">13.09.2021</p>
</div>
<div class="mt-0.5 ml-4 mb-6">
<h4 class="timeline-title">Title of section 2</h4>
<p class="text-gray-500 mb-3">
Libero expedita explicabo eius fugiat quia aspernatur autem laudantium
error architecto recusandae natus sapiente sit nam eaque, consectetur
porro molestiae ipsam an deleniti.
</p>
</div>
</li>
<li>
<div class="flex flex-start items-center pt-2">
<div class="timeline-disk"></div>
<p class="timeline-date">25.11.2021</p>
</div>
<div class="mt-0.5 ml-4 pb-5">
<h4 class="timeline-title">Title of section 3</h4>
<p class="text-gray-500 mb-3">
Voluptatibus temporibus esse illum eum aspernatur, fugiat suscipit
natus! Eum corporis illum nihil officiis tempore. Excepturi illo natus
libero sit doloremque, laborum molestias rerum pariatur quam ipsam
necessitatibus incidunt, explicabo.
</p>
</div>
</li>
</ol>