Angular & Tailwind: Q&A

Preston Lamb
ngconf
Published in
6 min readMay 5, 2021

tldr;

I recently led a workshop on Angular and Tailwind for ng-conf 2021. The purpose was to introduce Angular developers to Tailwind, including how to implement it in your app and how to use Tailwind. A couple weeks after the event, an attendee reached out with a couple of questions so I decided to write an article about it. Hopefully, this will be helpful to others who are using Tailwind in enterprise apps, or really any size apps.

The questions were:

1. What are the big differences between Bootstrap and Tailwind?
2. What are my thoughts on the amount of CSS in templates with Tailwind, and alternate solutions?

I’ll tackle each of those to the best of my ability in this article.

Comparing Bootstrap vs. Tailwind Usage

Bootstrap is a great CSS framework and there’s a reason it’s been as popular as it has been for nearly a decade. It provides an easy way for those who don’t have much design skill to end with a decent looking application. However, there are some minor downsides to Bootstrap. One thing is that Bootstrap sites tend to have a familiar look and feel. You can usually go to a site and tell that it’s been built using Bootstrap. Another downside is that Bootstrap has specific classes for particular components that you have to remember for each of those components. For example, if you want to put a card on the page, here’s the HTML and classes:

<div class=”card” style=”width: 18rem;”>
<img src=”…” class=”card-img-top” alt=”…”>
<div class=”card-body”>
<h5 class=”card-title”>Card title</h5>
<p class=”card-text”>Some quick example text to build on the card title and make up the bulk of the card’s content.</p>
<a href=”#” class=”btn btn-primary”>Go somewhere</a>
</div>
</div>

As you can see, there is a .card class on the enclosing div, as well as .card-body, .card-title, and .card-text classes. What do these classes do exactly? I don’t know, except that they add some style to those particular elements. The style on those elements can’t really be reused elsewhere; for example, if you want to use an .accordion. The .accordion classes are different than the .card classes, even if they result in similar output. Now, what does this mean for you as a developer? It means that memorizing the classes for your application is more difficult because there are different classes for every component, as well as all the utility classes that Bootstrap provides.

The final difficult part about Bootstrap, historically, has been that overwriting the default Bootstrap styles is nearly impossible. There are many !importants littered throughout the Bootstrap style files. In addition, the specificity of certain elements is deep. For example, it’s not uncommon to see a CSS rule like this:

.card > .card-body > p.card-text {
font-size: 16px !important;
}

So not only is there a !important, the rule is very specific. In the end, it’s hard to overwrite Bootstrap styles.

Now, Tailwind has similarities to Bootstrap in that it makes it easy for the average developer to produce a good looking application. It also uses utility classes like Bootstrap does, but it only uses utility classes. You won’t find card-specific classes anywhere because the folks at Tailwind don’t know how you want your card to look. Each card you make can look different if you want. If you want three variants, make three variants. It’s completely up to you. This flexibility is refreshing. Nobody will come to your site and say, “This is a Tailwind site.” They will have no idea. The sky is the limit for how to design your site.

What’s With All the Classes?

The second question is another that I have received a few times, and that is, “How do you deal with all the classes littered throughout your HTML?” And honestly, it’s a good question. If you’ve never seen a sample of some HTML with CSS classes, here’s one for you:

<footer class=”bg-white” aria-labelledby=”footerHeading”>
<h2 id=”footerHeading” class=”sr-only”>Footer</h2>
<div class=”max-w-7xl mx-auto py-12 px-4 sm:px-6 lg:py-16 lg:px-8">
<div class=”xl:grid xl:grid-cols-3 xl:gap-8">
<div class=”space-y-8 xl:col-span-1">…</div>
<div class=”mt-12 grid grid-cols-2 gap-8 xl:mt-0 xl:col-span-2">…</div>
</div>
<div class=”mt-12 border-t border-gray-200 pt-8">
<p class=”text-base text-gray-400 xl:text-center”>

</p>
</div>
</div>
</footer>

There are a lot of classes mixed in there! And this is just a small example, a little over 10 lines of HTML. So, how do I deal with that? It’s simple: I just do. It took a little while, but I finally realized that having all the classes looks a little crazy when developing a page or component, but it really doesn’t matter. I can use all the utility classes provided by Tailwind, or write custom CSS. I can have long strings of classes or long files of SCSS for each component or my app. I’ve decided that overall, it’s much easier to add a whole bunch of classes to my HTML rather than write the custom CSS.

Now, there is somewhat of a middle ground. It does seem kind of crazy to apply a color and underline to every single a tag in the app. Or, more complicated, apply the same classes over and over again to every button. How can we solve this problem? Let’s look at 3 ways:

@apply

The first is the apply directive that you can use in SCSS files. This directive lets you apply (hence the name) certain Tailwind classes to a CSS selector. Here’s an example:

a {
@apply text-blue-500 text-underline;
}

This rule will target all a tags and apply a color and underline to them. That way you don’t need to add those classes in the HTML files.

theme()

The next method is using the theme function in SCSS files. Its purpose is similar to apply, but is used with specific CSS rules. You can view the specifics at the link, but here’s an example of how to use it:

.btn-blue {
background-color: theme(‘colors.blue.500’);
}

In this case, a custom CSS class is created, called .btn-blue, and the background of the button is set to the blue 500 variant.

Angular Directives

The last option available specifically to Angular developers is to create and use an attribute directive. Attribute directives provide the ability to change the appearance or behavior of DOM elements and Angular components. With the attribute directive, you could apply all the required classes for a button, and provide the color of the button as the input to the directive. That way you ensure that all the buttons in your application are the same each time a button is used. Here’s an example of an attribute directive for a button:

@Directive({
selector: "[myButton]",
})
export class ButtonDirective implements OnInit, OnChanges {
private defaultClasses: string = DEFAULT_BUTTON_STYLES;
@Input("myButton") buttonColor: string;
@HostBinding("class")
elementClass: string = `${this.defaultClasses}`;
ngOnInit() {
this.setColor();
}
ngOnChanges(change: SimpleChanges) {
if (change?.myButton?.currentValue !== change?.myButton?.previousValue) {
this.setColor();
}
}
setColor() {
if (this.buttonColor) {
this.elementClass = `${this.defaultClasses} ${
BUTTON_COLOR_STYLES[this.buttonColor] || ""
}`;
} else {
this.elementClass = `${this.defaultClasses}`;
}
}
}

To use the directive:

<button myButton=”orange”>Hey there!</button>

This would make the directive apply the default button styles, and then the orange classes that you’ve selected as well.

Conclusion

Tailwind is a great option for developing Angular applications. There are some things that you may have to overcome (like all the classes) but for me, the benefits outweigh the downsides. The flexibility that Tailwind provides makes building applications really nice. For me, Tailwind is the way to go. It will surely not be the last CSS framework I use, but it is my current choice.

Now that you’ve read this article and learned a thing or two (or ten!), let’s kick things up another notch!
Take your skills to a whole new level by joining us in person for the world’s first MAJOR Angular conference in over 2 years! Not only will You be hearing from some of the industry’s foremost experts in Angular (including the Angular team themselves!), but you’ll also get access to:

  • Expert panels and Q&A sessions with the speakers
  • A friendly Hallway Track where you can network with 1,500 of your fellow Angular developers, sponsors, and speakers alike.
  • Hands-on workshops
  • Games, prizes, live entertainment, and be able to engage with them and a party you’ll never forget

We’ll see you there this August 29th-Sept 2nd, 2022. Online-only tickets are available as well.
https://2022.ng-conf.org/

--

--

Preston Lamb
ngconf
Editor for

Full Stack JavaScript Developer | Angular | Node.js | www.prestonlamb.com | @plambweb