05: Composing Utilities with @apply – Tailwind CSS v2.0: From Zero to Production

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
a common concern folks have when they start working with tailwind is the sheer amount of classes it puts in your html long series of classes like this one here or maybe our headline down there are raising some concerns about maintainability and how you would go about reusing this same element in multiple places in your project with all these classes so let's take the most extreme example in this page which is a button here and we're going to use this to take a look at tailwind's apply feature which lets you abstract the css component class this sounds like a good candidate to demonstrate the apply feature because we easily have 20 classes here and also a button is something you can imagine yourself reusing over and over in a project so let me grab every class name in here and i will cut that and replace this with a class that will call button btn so when i save all will be broken but now let's head over to our css file and in here i'll create this button class now for now bear with me for a second i will move this before the utilities layer and i'll explain to you why in a second in here instead of defining key value pairs i will use the at apply directive and simply paste all the utilities that i've copied over so what this apply feature will do here is take all these utility classes that we've applied together compose them and then generate a button class btn class with all the styles combined together so if we look at the generated css you can see that we have a btn class and it's applied border radius display inline block the font weight font size line height focus states and all the utilities that we've applied together you can also see that our button looks nice again and the hover state focus state active state everything works now why did i put this button class here and not after the tailwind utilities well we want to be able to override a button class with utilities on a per case basis for example let's say that somewhere where we're using a button class component that we've just created we want to add more padding horizontal so let's add here px10 and you can see the extra spacing here on the left and the right now if i had my button defined after the telling utilities layer let's try that you can see that now we have lost the padding on the left and the right the reason is that the px10 class that we're using here has been defined in the tailwind utilities layer and then later down the css file we define a px5 class which will override the px10 because it comes after in the cascade to make things easier for you and so you don't have to remember where to write your css in the file you can use another tailwind directive at layer the at layer directive lets you specify which of the three tailwind layers you want to write css for so here for example i want to write for the components layer and i can open a block here and move my button declaration inside of that block as soon as i've done that you can see that the padding is back here on the sides and wrapping a button inside the at layer components directive here makes sure it will be generated in the right place in the style sheet which is right at the end of the components layer before the utilities so hey that's pretty cool we've cleaned up our html we've created a nice component class for the button and at this point you might think about going and replacing everything in your html and abstracting component classes for everything now before you go and do that i want to challenge you to think about the trade-offs that you're making here specifically you should think about the fact that you're now moving the complexity and maintainability somewhere else i'll try now to make a little example that illustrates that so let's get rid of our px10 class here and i'm going to duplicate this button and the second button is going to say learn more and let's quickly add a space between utility here with space x and i think one is gonna be fine so now we have two buttons and usually when you have two buttons like this you have a different hierarchy there's a primary button and then a secondary action that you probably want to look a little bit different so let's try to build this we have a button primary and a button secondary so it's all going to be broken now but let's go and fix it so here i'll change the class from btn to btn primary which should fix our first button right and then i'll for now duplicate all of this and call that button secondary so for this one we'll change some of the styles we can keep this but the background will be let's say gray 300 by default on hover it will be a little bit lighter so background gray 200 this remains the same the ring is also gray 300 and finally the active state will be bg gray 400 so let me save that oh and one more thing we don't want the text white here we want the text to be let's go with text gray 800 so we have our two buttons and they do work but i can see a couple of problems already coming up here the first thing is i don't like this shadow here on the light gray background it looks a bit blurry so i really technically just want the shadow on the primary button and have the second one flat this tells me we've probably abstracted too much away in our button and baked a few too many design opinions in it what i really should do is remove the shadow class here for both the buttons let me quickly copy it and delete it and then we're going to manually add it to our button primary here right so now we have the shadow button for the primary and the secondary is flat similarly because this is the secondary button and not the primary action we likely don't want the attention grabbing hover liftoff effects that we've got with the translate here so once again we want the first button the primary one to have this hover effect and the other one should be just flat and change background color without moving so one more time i'm going to find the class to remove here it's hover translate y 0.5 i'll copy that and i'll remove it in both buttons but i will also remove the transform and transition classes here now once again let's go in our primary button and add the hover effect and we will also add the transform and transition classes okay so now we have a nice primary button with a nice lift-off effect and a shadow where the secondary button is a little bit more subtle perfect the next fairly obvious problem is we now have a lot of duplication in our css it's quite clear that both buttons share a lot of common styles so why don't we abstract a core button component that has all the styles shared by both and then create modifiers for the primary and secondary buttons so up here i'll bring back the that btn class so in there we're going to grab everything that's common to both buttons so i want the inline block the padding and the rounded corners so i'll grab this tree and here i will add apply and paste these we don't want the background color the hover background color but we do want the focus outline none focus ring and ring offset so i'll add these here i do not want the ring color or opacity or active state or the text color but i want everything after that so uppercase tracking wide font weight font size so let me also paste these right there and now well i need to go and remove whatever has been used and abstracted to the common button from both so for both button i will remove everything up to here i will keep the colors but remove the outline and ring and ring offset then i want to keep all of these which are colors and basically want to remove everything after the text color so from uppercase to text base for both these two buttons so we should be good now we've broken slightly our button once again because they're missing the btn class that has the common styles for both my buttons here i will add the btn class let's take a look it all works very nice so that's starting to look solid we have no duplication in our html we have no duplication in our css because we've abstracted the common classes to a btn class but even in this situation i can think of at least three subtle problems that could arise over time the first one readability now i know this might sound strange because for telling newcomers seeing a bunch of classes like this sounds more like clutter than useful information but if you take them one by one and look at them you actually get all the information that you need to know what the ui will look like we have a margin top of level six the font size is two 2xl the weight is bold the color is gray 900 and then on a small breakpoint we increase the margin top to 8 we change the font size to 4xl on the large breakpoint we change it to 3xl etc there's a lot of useful declarative information here pretty sure that if you say work on another project for three months and come back to this one you'll immediately know what's happening here in this heading if in three months you context switch back to this project there's a big chance that you'll need to go hunt in another file to understand what btn and btn primary do one of the main productivity gains of the tailwind workflow is you never leave your html file i guarantee you that after working like this for a while anything that makes you go away from your html file to do something will feel like friction finally every time you abstract a css component class with apply you generate more css for your output file you get the sense of removing duplication from your html but this duplication actually manifests itself back in the css file so the bottom line is the apply feature is here for people to use it i'm not saying you should never use it but i also recommend to not go overboard with it a good recommendation or rule to follow when using apply is to stick to a single html element something like a button a headline or a form input whenever you find yourself trying to abstract bigger components like a card component with an image a heading some text there's likely a better way to handle this this is exactly what we're going to look at in the next video
Info
Channel: Tailwind Labs
Views: 54,737
Rating: undefined out of 5
Keywords:
Id: TrftauE2Vyk
Channel Id: undefined
Length: 10min 1sec (601 seconds)
Published: Tue Feb 16 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.