Tailwind-Merge Is Incredibly Useful — And Here's Why!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
here's a quick demo of the Tailwind merged utility library and why I think it's super useful [Music] I have a contrived example here but that's plenty enough to drive the point home so I have a button it's just an xjs page that Imports a button component and then renders it here and in the components folder I have these button components and really all it does is return a button and we have a set of class names passed to it now let's say for some important reason in one instance where you consume the button you need you must have the button have a peel shape with the rounded full class so you really want to kind of override the default Styles and pass a class name here and go rounded full if I look at my button now nothing has changed you can see we still have the rounded LG class and no sign of the rounded full class that was passed to it the reason that happens is in our button you can see we have these rest props attribute here which basically represents everything except the children props that we pass to the button and gets passed here but then we redefine the class name attribute and therefore override it completely the pattern of spreading the props before the class name attribute here means that you lock the ability for the user to override the default starts and that might be something that you do absolutely intentionally in that case I use a really really wants to be able to override the Styles so let's move the rest props after the class name attributes and see what happens in that case and whoops a button doesn't look that great now a button does have the rounded full class but we've completely overwritten the default classes from the button and steamrolled over it with our rounded full class that's definitely not what we wanted to do we sort of wanted to merge the classes from the button with the class that we passed to it and well there's a way to do this a common pattern you'll see is to create a JavaScript function let's call it merge classes and you can see that copilot knows exactly what I'm trying to do it can receive an array of strings and then it will filter by truthy values and then join with a space effectively taking multiple groups of classes and then combining them together for us so let's try that in our button component we need to receive the class name at attributes and it's defaulted to an empty string and I'll add it to the type here class name question mark to make it optional and set it as a string and now we're going to use our merge classes function in the buttons class name attributes merge classes and I'll close the function here so we pass the component classes first and then we will pass the class name attributes received from the consumer second now my button has all the default button Styles applied but also the rounded full class that I passed when consuming the button component and it might look like everything's just fine but there is a big and sneaky problem here if we look at the classes applied to the button element there is a rounded full class that we've passed to the button component but there's also the rounded LG class from the default Styles and these two are technically applying a different value to the same CSS property you can see them both here applying a border radius value right now the rounded full wins because it's defined three lines later in the CSS literally right after and that's ultimately why rounded full wins here not because it's merged after the default classes in the react component but because of the source order in the CSS that's how the Cascade works right now rounded full was generated after a rounded LG because we've reached for this class after when building a project and the just-in-time engine has added this class after the one that already existed now let's watch what happens if I restart my Dev server to regenerate the CSS I will stop the dev server and restart it with npn run Dev and now I will refresh the page and whoops we're back to rounded LG you can see this time the rounded LG class wins as it was defined after the rounded full class in the CSS and so as much as possible Tailwind tries to be super clever about the order in which it generates the CSS to avoid these sort of problems but it's inevitable that you will face problems like this if you start applying conflicting classes to the same elements let's look at another example so for the background color here we have BG Emerald 600 and let's say that for my snowflake component here I need the background to be blue so BG blue 600 and yep the button has a blue background until I hover over it this is sort of what we were expecting and you sure understands that the reason is that the blue color is defined after the emerald color and therefore the blue wins BG blue comes last because we've just applied this class right now while we're in development mode but I have a funny feeling that Tailwind orders the color classes by alphabetical order by default so let's restart the server and see what happens once again stop the server restart it refresh the site and we're back to Emerald and blue is not applied and sure enough if I check the CSS this time Emerald is generated after so let's try instead of blue to have a color that starts after e so I'll go BG purple 600 right there let's switch this to purple right now it's definitely gonna win because we've just generated that color and therefore it's after the emerald one but if I restart the server I feel like this one is going to stay purple but I'm not sure actually let's refresh and yep it is still purple so my theory that the colors are generated by alphabetical order seems to stand I'm actually not 100 sure but it sure looks like it okay this is not a knock on telling CSS at all it has literally no way to know in which order the colors should come to work in your specific scenario like I mentioned before it's very clever about stuff like hover states breakpoints to make sure that the overrides happen in a logical way but when it comes to color it just has to make a decision and output the colors that you use to try and protect you against problems like this detailing intellisense is actually going to warn you when you use two conflicting classes so BG red 500 and you can see that immediately it's squiggling it and saying BG red applies the same CSS property as BG purple and once again to be 200 clear this is not the order in which the classes come that Define what color the element will be it is the CSS so order we're getting a warning but this will still work I believe the red color will win because R comes after p in the alphabet yep but it has nothing to do with the fact that red comes after purple in the class order if I had it here exactly the same would happen and actually you can see that the prettier class loading plugin has put BG red back at the end to tell me that this is defined after in the CSS but believe me if I turn the plugin off and I had the red class here before like this the same color would happen red would still win now we get this warning here because we are playing two classes in the same class string but we don't get the same warning here because we actually sneakily passing emerald and then purple here in the class name but the Tailwind intellisan extension is looking for Strings it doesn't see purple 600 background color here so cannot flag that it's going to conflict with that one so ideally we'd have a tool that prevents us from stepping on the rake and getting hit in the face right there there and this is exactly what Tailwind merge is so if you look at a merge classes function here that joins groups of classes together this is a very basic and minimal implementation of one of the things that Tailwind merge can do for you you may have heard of utility libraries that do something like this slightly more advanced something like class names or clsx here I'm on the clsx a GitHub repo and you can see that essentially it's going to do the same thing merge groups of classes but it works with objects arrays and can handle more complex scenarios I already have it installed in this demo project so at the top I could import clsx from crsx and you can name this whatever you want CN for class names and then I could delete my merge classes function here and instead of using merge classes I could use CN and you can see it's expecting also an array of class strings so now if I save the exact same thing happens so we have a button default classes and then the classes we pass to the button components merge together but we still have these conflicting classes of rounded LG and run it full and then BG purple and BG emerald and you know what let me quickly switch back to BG blue 600 since purple wins anyway and restart my server once again so we can better demonstrate how telwyn merge is actually going to fix this problem so now it's blue but when I refresh we should go back to Emerald because blue is defined before yeah all right and now with this understanding out of the way it's finally time to look at Tailwind merge Tailwind merge works very similarly to clsx outside of the fact that it has named exports but the big big difference is it's going to merge the classes without style conflicts it will decide for you when there are conflicting classes that the one that was passed last will always win and the other will actually be removed and not part of the class list in the HTML elements for example here we have p-5 p-2 and p-4 all of them conflict but the last one pass is p-4 and so the only class that will be applied to the element is p-4 I also already have it installed on this project but you can install it with npm install Tailwind Dash merge and once you've done that let me start the server again let's go in the button component at the top and instead of CN from clsx we will import a named export from Tailwind merge you will see that we have two functions available twine and TW merge so in situations where you want to just merge classes without doing any of the conflict resolution you can use twjoin just like you would use clsx so here TW join with the exact same syntax and everything still works but we still once again have that duplication of conflicting properties but now and I know you've been waiting for this let's try the TW merge function that will resolve the conflict for us I will select both instances of twjoin and use TW merge instead nothing else changes and before I go back to the browser you tell me what color and what's border radius the button will have right now when I visit it you got it let's check it out well done congratulations you had guessed blue background and rounded full border radius you can see in the classes here that rounded LG or BG Emerald 600 is nowhere to be found we have this one but this is the active class this is different the conflicting classes that were passed first have been removed from the class list which is fantastic and this little detail right there is the core focus of Tailwind merge and it's incredibly useful especially if you work in component libraries where you expect users to pass class names that should override the styles of the default components now what do you think would happen if I pass the class name prop first in my TW merge and then the button starts well hopefully you understand now that because these classes are merged last PG Emerald 600 and rounded LG will now win over BG blue 600 and run it full and yep Emerald button with rounded LG and we cannot see PG blue 600 or rounded full and anywhere in the class list let's bring that back after the default classes and remember how I mentioned that the BG Emerald 600 class was removed because it conflicts with BG blue 600 but we still have the hover and active Emerald colors the cool thing is telling merge works with every Tailwind features like State modifiers like hover or active chained modifiers arbitrary values arbitrary properties all of it so here we consume the button component let's go hover VG pink 600 and active BG yellow 600 not the greatest style for States but that should do the trick to show us that it works on however the button is Ping 600 and on active it's yellow 600 and there are no conflicting classes in our elements the colors that were applied by default have been replaced with the ones we passed after and that is telling merged superpower alright I highly encourage you to check out the docs like I mentioned it supports modifiers stacked modifiers arbitrary values arbitrary properties arbitrary variants works with important postfix pretty much anything that exists in tailwind and you can take it much further by passing specific configuration to change the behavior there's a lot more to it but in a nutshell rather than teach you the library I wanted to show you why this is a useful library and actually just make you aware that when you pass classes to overwrite style sometimes it might look like it works but you might hit some sneaky problems alright that's it for this video thanks for watching and I'll see you in the next one bye foreign [Music]
Info
Channel: simonswiss
Views: 14,988
Rating: undefined out of 5
Keywords:
Id: tfgLd5ZSNPc
Channel Id: undefined
Length: 12min 58sec (778 seconds)
Published: Tue May 30 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.