Skip to content

TailwindCSS and WordPress

Published on May 18, 2023

Being able to choose the entire dev stack of client websites is not always a luxury I have, however, choosing the type of code I write was rarely ever mandated. Historically, if I was tasked with building a custom theme, it would always include Advanced Custom Fields and use the underscores.me starter theme. A lovely, hackable starting point that stays out of your way. I’d been doing it this way since 2016. Unfortunately, support for _underscores has all but diminished. Fortunately, there’s a solution that was built just for me [citation needed].

_tw

“_tw lets WordPress developers add Tailwind to their workflow while otherwise diverging as little as possible from longstanding WordPress theme development practices.” That’s how Greg Sullivan, the developer of _tw describes it. I won’t go into detail about it as the documentation is great, and it takes no time to spin up a WordPress site these days with tools like Local. _tw is my go-to for generating custom WordPress themes and I think you should try it out.

Less thinking, more doing

Let’s create a button component using Advanced Custom Fields and Tailwind and compare it to how I’ve done it before with Sass.

<!-- Tailwind button -->
<button type="button" class="rounded-md bg-sky-100 text-slate-950 hover:bg-sky-300 active:bg-sky-400">
  <?php the_field('button_text'); ?>
</button>
<!-- Button with Sass -->
<button type="button" class="primary-button">
  <?php the_field('button_text'); ?>
</button>

<style>
  .primary-button {
    background-color: rgb(224 242 254);
    border-radius: border-radius: 0.375rem;
    color: rgb(2 6 23);
    &:hover {
      background-color: rgb(125 211 252);
    }
    &:active {
      background-color: rgb(56 189 248);
    }
  }
</style>

Both code snippets will give you the same end product, but look at how many less lines it takes with Tailwind. At face value, it doesn’t seem like a big difference, but consider this: how do you debug, and how do you update code you’ve written?

One of the most common ways I debug styles is to have the dev console open and inspect away. Find the class name to refactor, go to the scss file and then fix it. Whoops! Looks like it was broken because it was actually a fix for another page where the class name was being used.

I love CSS specificity. It’s a straightforward ruleset to follow, and pro or con–game the system. I pride myself on never using the !important flag when writing CSS. That said, I don’t talk about the many times I’ve done this:

.button {
  // button styles
  &.primary-button {
    // primary button styles
  }
}
body { // add some specificity points lol
  .page-id-201 { // another point just in case
    .button {
      // page specific button styles
      &.primary-button {
        // primary button specific styles for this specific page
      }
    }
  }
}

Of course I would never do that…

But here’s the deal, .page-id-201 means nothing to me. Sure I can add a comment “Contact Page” or something, but that’s solving a problem for a problem. Now do that 100 times for a 300 page website. Don’t get me started on why naming things is the hardest thing in programming.

Managing classes and remembering classes gets in my way. Spending time to read the code to debug takes time. Being able to reduce that time means more satisfying code. Little to no chance of changing all the things you didn’t have eyes on when you’re just adding utility classes.

So Tailwind is my preferred way to “write CSS” these days, but I’m still trying out some things. If you’re using ACF to manage content fields in WordPress, how does this feel:

<?php
// Get a button theme from the admin to determine the style of button
// ACF radio field to choose themes of an element
// Options are primary & secondary
$theme = get_field('button_theme');
$buttonClasses = '';

if ($theme == 'primary') : $buttonClasses = "bg-blue-500 text-white rounded-md hover:bg-blue-900 active:bg-blue-950";
elseif ($theme == 'secondary') : $buttonClasses = "bg-red-500 text-yellow-100 rounded-lg hover:bg-red-700 active:bg-red-800";
else : $buttonClasses = "rounded bg-black text-white"; 
endif;
?>

<button type="button" class="<?php echo $buttonClasses; ?>">
  <?php the_field('button_text'); ?>
</button>   

I’m still working through articulating why I prefer this way, but one things for certain is it feels a lot smoother during development. Collaboration is also streamlined as well. When pairing with another dev, it’s just nice to be on the same page, or file in this case. Everything is contained, confidence is high. Extending the component isn’t a chore, whether it’s adding a variant or adjusting the style of a current type of button.

The other method I’ve been trying is using @apply for custom classes so the markup looks a bit cleaner. I go back and forth because despite the separation of concerns thing, it’s nice to live in one file at a time when first building things out and then refactoring after the fact if needed. The classes can now easily map with ACF:

<?php
// Get a button theme from the admin to determine the style of button
// ACF radio field to choose themes of an element
// 'button_theme' ACF returns one of [primary, secondary, default] 
$theme = get_field('button_theme');

<button type="button" class="<?php echo $theme; ?>">
  <?php the_field('button_text'); ?>
</button>   
button.primary {
  @apply bg-blue-500 text-white rounded-md hover:bg-blue-900 active:bg-blue-950;
}
button.secondary {
  @apply bg-red-500 text-yellow-100 rounded-lg hover:bg-red-700 active:bg-red-800;
}
button.default {
  @apply rounded bg-black text-white
}

I’m struggling with this because it’s not a vast improvement over just writing CSS normally, but I’m still preferring to write Tailwind utilities even if it’s separated. I’ll stick with one eventually.

I love writing CSS. It’s most likely the language I’ve spent the most time writing. It’s funny how much effort I’ve been putting in to write less CSS these days. I blame NextJS for including Tailwind in their create-next-app.

If you liked reading through this, see why I’m Obsessed with Tailwind CSS.