Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Reusing styles

A product card takes a dozen classes. If you copy its markup twenty times, every change — say, a different corner radius — has to be made twenty times. In Tailwind such repetition is removed not in CSS but in templates: the markup is written once and the data is filled in.

A loop instead of copies

When cards follow each other, build them in a loop from an array of data. The card markup is written once:

<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
 
<div id="catalog" class="grid grid-cols-3 gap-4"></div>
 
<script>
  const products = [
    { name: 'Headphones', price: 79 },
    { name: 'Speaker', price: 45 },
    { name: 'Charger', price: 19 },
  ];
 
  document.getElementById('catalog').innerHTML = products.map((product) => `
    <div class="rounded-xl bg-white p-4 shadow">
      <h2 class="font-semibold">${product.name}</h2>
      <p class="text-gray-600">$${product.price}</p>
    </div>
  `).join('');
</script>

Below the code are three identically styled cards. To change the shadow on all of them, you fix one line of the template.

A template component

In React, Vue or Svelte a repeated piece goes into a component. For example, in a Vite project with React, the file src/components/ProductCard.jsx:

// src/components/ProductCard.jsx
export default function ProductCard({ name, price, image }) {
  return (
    <div className="overflow-hidden rounded-xl bg-white shadow-lg">
      <img src={image} alt={name} className="h-40 w-full object-cover" />
      <div className="p-4">
        <h2 className="font-semibold text-gray-900">{name}</h2>
        <p className="mt-1 text-gray-600">${price}</p>
      </div>
    </div>
  );
}

It is used like a regular tag, with the data passed as attributes:

// src/App.jsx
import ProductCard from './components/ProductCard.jsx';
 
export default function App() {
  return (
    <div className="grid grid-cols-3 gap-4 p-6">
      <ProductCard name="Headphones" price={79} image="/media/photo-400x250.jpg" />
      <ProductCard name="Speaker" price={45} image="/media/photo-400x250.jpg" />
    </div>
  );
}

The card's classes live in one file, and the page assembles it with different data. In React the attribute is called className, not class.

Partials on the server

Without a JavaScript framework, backend templates do the same: include in PHP, @include or Blade components in Laravel, {% include %} in Django and Twig. The card goes into a separate file and is included in a loop.

Small repetitions

If three neighbouring menu links share the same classes, there is no need to extract anything: an editor with multiple cursors edits them in a second. A component is worth it when a piece of markup repeats in different places or files.

Common mistake

Moving the card's classes into CSS with @apply right away "to avoid copying". You end up with a .product-card class in a separate file, while the card's markup — image, heading, price — is still copied. What repeats is not a set of classes but a piece of markup, so it is the markup you should extract — into a component or a partial.

Thanks for reading!

Donate to the site — we work hard for you.