This new Tailwind feature is scarier than I thought
HTML-код
- Опубликовано: 6 фев 2025
- Tailwind version 4 is a great release, but it kind of breaks one of the best promises that Tailwind makes. I'm a little scared...
Thank you CodeRabbit for sponsoring! Check them out at soydev.link/co..., and make sure to use THEO1MFREE for a month off
SOURCE
nmn.sh/blog/20...
Thank you to Naman (creator of StyleX) for writing such a great post. Give him a follow:
bsky.app/profi...
Check out my Twitch, Twitter, Discord more at t3.gg
S/O Ph4se0n3 for the awesome edit 🙏
The tangent about Tailwind team not liking React in the middle is largely incorrect. Bad assumption I had made based on a few specific conversations. From Adam: “I love React, it’s the only way I will ever build a website again”
x.com/adamwathan/status/1869219313275506961?s=46
People should really be using Vue instead
Theo making 30 min clickbait talk like it was a loquendo tutorial
The clickbait is insane
not really, he covers serious concerns with some of the new features of tailwind v4
Gotta make that cake, still good points
cuz otherwise you wouldn't click on the video and write a comment lol
@@trkishh could you specify what feature is scary exactly? I'm about to block this channel because I want the context in one sentence and then if I'm interested, I'll be happy to watch 30 minutes.
You've been on the internet long enough, you know how it works
guys, hear me out what if we start hating on tailwind and create another CSS library and praise it for a few years and then do it all over and over again 🤩
The problem with that is that it wouldn't make Tailwind Labs/Theo any money
Library on top of Tailwind that simplifies it would be much better. Then we will make Tailwind Compiler on top...
@@DeepTitanic I think Theo would be just fine... does it matter which hype train to ride if it is the longest and thickest at the moment?
unocss is better than tailwind.
@@vipero07 i agree. with unocss you can build your custom tailwind. 😊
0:00 Introduction to Tailwind CSS V4 Critiques
1:34 Code Review Tool Demo with Code Rabbit
3:14 Detailed Tailwind V4 Feature Analysis
7:00 Performance Concerns with CSS Variables
10:00 Critique of Gradients and Design System Concerns
12:30 Analysis of Dangerous New Variants
15:00 Discussion on Descendant and Double Star Variants
18:25 Tailwind Class Name Prefixing and Merge Conflicts
22:40 Accessibility Concerns and REM Units
Generated by Snorvia AI chapter generator
What is Snorvia? I can’t find it on Google.
@@Torbikini It's the tool I use to generate these chapters. You can google "Snovia AI chapter generator" and you should find it.
@@Torbikiniprobably a chrome extension
These seemed really quite helpful, which makes it even weirder that some are good descriptions but are off by a lot. For example, the last chapter starts at 25:47 - not at 22:40 as claimed. But the title is really fitting! Strange.
Edit: oh, 22:40 is when the text of the last chapter first shows up on screen. So maybe it’s ocr, not analyzing the voice. Hm.
Come on enough of clickbaits
1.5x speed time
3x speed time
Thnx for the reminder 😊
5x speed time
Petition to add 5x speed to youtube app
I basically use 1.5x or 2x for everything these days.
16:49 Here, I think writing out the CSS directly is better. It forces the developer to acknowledge the seriousness of what they're attempting to do. It's like how in low-level programming you would write assembly code directly during those rare cases when regular C code doesn't quite cut it, but by going to that level you acknowledge you really need to know what you're doing.
I want to see someone style an entire site using ** and data attributes and all the classes on the body tag.
Total agree on the brackets for arbitrary values. I really like that as a clear indication that you're leaving the world of the sensible Tailwind defaults or custom theme.
Banning ** syntax would be a good rule to add to the tailwind eslint plugin.
slowly becoming a dev lolcow with these titles mate
30 minutes??
Do I have gills and scales? Cus I just got baited
Tailwind is just a class-wrapper for inline styles, so this follows :)
wrong :)
26:08 There's actually a third: the pinch-zoom: it's a magnifying glass that doesn't change/reflow the page
25:19 "To be fair: the language is Javascript"
Well, I actually used tailwind in Java and Kotlin applications.
how is that even possible? can you elaborate on that?
@@giorgos-4515 as he said in the video, tailwind is language agnostic, it parses your html files, and build css. You can serve your content using any languages. I often build my apps using Go, and I like using tailwind for the css, in the end tailwindcss is just building css files and you app is serving html and css files regardless of which language you use
@@vrouilhac so it is basicaclly a build step for css right? i will have to look into this, as i dont intend to write javascript anytime soon.
@@giorgos-4515that’s right, it allows me to focus on building ui without jumping through tons of CSS and focusing on the backend for high quality 👌
yeah, I have used tailwind in a Rust frontend web app with Yew framework which is similar to React. It was a school project, pretty interesting since it works thanks to web assembly. The backend was in Rust too, so it was a fullstack app in a single language, just like we are used to with js. Its definitley nice that tailwind is language agnostic.
17:00 For those specific cases we already have custom selectors in Tailwind v3, e.g. `[&_*]:data-avatar:rounded-full`. We don't need **.
And those selectors already cause problems in real projects. In the next version of Shadcn-Svelte there are those classes used in various components. One of them is Button.
They have a class `[&_svg]:size-4` which sets a size for all svg's (usually icons) inside the component. But that causes problems, because `[&_svg]:size-4` has a higher specificity than, let's say, `size-5` I'd use for an icon.
So the following button will have its icon of size 4, not size 5, despite what the code suggests:
Set time
I'll file a proper issue on GitHub. Nevertheless there might be more issues like this in other projects, because of too much power given to Tailwind.
It’s already happening to me. What’s your suggestion other than using !important
I'm really glad you called out the CMS example as middle ground for the **. The struggle can be real.
And here I am .... back then (once again) when we had to fight about BEM or BOM class name things 😅
There's been a number of times I've had to do some prop drilling in React just to have some tiny component change its styling based on the section that it's in. The double star seems to just make that easier while still retaining clarity (as long as you're naming the data-attribute appropriately).
24:24 "The Tailwind team doesn't like react". But, they created HeadlessUI for React and build a UI kit 'Catalyst' for React? I feel like lot of these new features were added to fix really specific problems they ran into when building Catalyst, a complex component system. And of course with great power comes great responsibility, which is dangerous.
As long as a feature exists, there will exist people who use it
To make any tool good, you have to think how will this feature cause issues
HARD disagree about the point about rem units. Sure, I could maybe see some hypothetical benefit to allowing of allowing users to control font-size and zoom independently - but in reality, its not as easy as just using rem for text and px for everything else. You now have to worry about the million different ways your design is going to break if users have their font-size extra large. Like for example your sidebar now has text that no longer comfortably fits inside of it, if you did everything with rem that isnt a problem because as long as you styled your website responsively that sidebar will just collapse as if its a a narrower viewport. Or hell, I can't imagine the nightmare that would be a top bar navigation where users can make the header text gigantic without any of your media queries kicking in, resulting in elements overflowing off the page or outside of the container.
I don't think its some crazy assumption that If people want larger text, they are going to also need a larger interface for that text to fit inside of. Sure maybe in a perfect world designers and developers could spend countless hours working out ways to make sure their design can gracefully handle independent control of both - but we don't live in a perfect world, and accessibility is already the neglected stepchild on the internet. The move to all rem everything as part of best practices has been a huge improvement for web accessibility because its an easy set it and forget it solution. Promoting mixing rem and px will erase a lot of that progress, and break sites for these users the moment a developer didnt account for the font-size setting.
12:45 Yeah but let's face it, in the real world, there are times when you need to target a descendent that you may not have the ability to directly control via CSS, I had that problem today, it's common.
Guys, you are crazy. The Tailwind becomes one more DSL on top of CSS... do you know how it will end up? It will become too bloated and you will make Tail-TailwindCSS to simplify TailwindCSS.
It is fine to use the simplest TailwindCSS classes that help structure things like margins, paddings, borders, grid spacing, etc. But for everything else - just use plain CSS.
Because you can ignore the cascade it means you can have a large team of "Full stack" devs (Senior backend junior frontend) hacking their way through making components.. using negative margins and important tags. This is what TailWind influencers miss, is that most people are not elite developers and work on real world projects. Tailwind allows these people get something passable done without having to understand the box model.
@@DeepTitanic I think there is a equilibrium line that is incredibly difficult to define, and it also changes depending on the circumstances. I mean the quality of engineering versus the cost of an engineer.
It seems to be fine for most software products where Tailwind is used, because they have no value initially and die pretty quickly without having any impact on the world. Or they are internal business applications that have very obscure and unclear ROI.
But if a product survives the initial reality check, then all those "cheap, fast, and good-looking" solutions become a huge problem. I think it is important not to double down on such solutions at this point, but to hire the right people who will re-implement the product the way it should be done.
@@ВасилийТоррик As someone who has fixed legacy projects often I much prefer it when someone used some atomic css. You have classes set up on the element and you know what it does and where. You can move the element to another place, or even delete it, and in most cases it's fine. When cascading css was in, on the other hand, I spent more time creating a grid of class relationships than fixing the design. And surprisingly more the previous developer was a css wizard the harder it was to change anything.
@DeepTitanic people do that without tailwind, too😂
@@DeepTitanic tailwind is quick and this is the real reason why it is being used. We live in 2024 - knowledge of box model, or deep CSS knowledge should be deep for professionals. Tailwind helps to ship things faster and this is the key reason why it was so widely adopted. Lot better approach than bootstrap for example
The best friend is the one who tells him what is wrong!
Nice work Naman!
The beauty of Tailwind is that it was the WYSIWYG of CSS. You look at a class name and be guaranteed that it does what it says in the name and nothing else. With descendant variants this stops being the case which is why I think its best if it was a plugin instead.
That said, I can't wait for people to slap some stars on body and get confused later.
17:22 there's a plugin called "prose" for wrapping cms content. You should use it instead of slapping ** somewhere random. Of course you can always raw dog your own prose classes, but I think the design of prose is good and worth using
I simply love when Theo curses.
Agree, ...the loss of clarity in not requiring brackets for arbitrary values still feels like a mistake.
tailwind is only useful to splurge out a quick prototype, fight me
What I really fear right now is tailwind forks emerging)
tailwind-merge should work only at build time, then any classes calculated dynamically should be treated outside tailwind merge
This is not always possible across files which is where it’s needed most of the time.
If you want to apply the same styles to your s, just map() them and you should be good
The * and ** syntax can be helpful, but I liked-as you mentioned-how the bracket syntax clearly shows you’re doing something abnormal, like [&>.element]:p-4 or [&_.element]:p-4. It’s bulkier, but that’s okay because we shouldn’t be doing this unless absolutely necessary anyway.
I love tailwind it keeps me employed, all my coworkers say "wow that looks so good", classic bg stone 900 text-blue-500
Theo, I hate the t-shirt but its logo saved the day
I think the (named) group selector was already good enough for styling html we may not have control over. We don't need **
I haven't used Tailwind yet but after watching your videos on it I'm looking to give it a try. Key features for me: HMR, "semantic" classes, somewhat-structured design conventions, and more. However, I am not going to be giving up old-school CSS entirely. Its entire purpose was separation of concerns between doc structure and appearance. Putting p-4 classes on every is inefficient and hard to maintain: if the list is dynamic - server-side or JS - then I can't update the theme without touching that code. .list li { padding: 1rem; } makes way more sense to me.
I suppose that if I go with Tailwind it'll be used like an optimized Bootstrap framework. I'm OK with that.
Stay with vanilla CSS it's easier to work with
Tailwind has increased our productivity. No one in the team has to read through CSS files to see if there are already suitable classes. And no matter which project is being worked on, the classes are identical. No more wondering what to call the CSS classes for this button, that menu, etc.
I also thought Tailwind was just a new stupid trend, but it has improved so much in our company.
I think this is more of a "you" problem in believing those things (structure and appearance) should be considered "concerns" and be separate than some objectively good property of old-school CSS, but you give tailwind a go and check for yourself if it will not make you more productive in writting styles. For me it was a good fit, even if I still like CSS for the raw power it provides.
Well tailwind still lets you use this "old-school css" thing😅
@@michael_1010 You probably don't have an actual web designer that styled the entire site components and you sprinkle CSS here and there, or have a bunch of incoherent CSS chunks all over the place. In that case, yes, I think Tailwind would at least bring some level of sanity.
If you're serious with CSS, then Tailwind is not your friend.
I disagree with the *: being bad. I think, from a component framework perspective it's fine to use in the component. Where it is less fine is when you use it on a parent component for children components. Essentially, if you want to change the padding on all those li it's easier to do on the parent than on all the children, improving maintainability. If the li are in an each or children components, then its bad to use.
** however, makes no sense except if you are trying to style someone else's things that you have no control over. Because you could just put the rounded-full class on the data-avatar element.
Thanks Naman! Great critique, 100% agree.
What?? I don't know if I misunderstood something here. but tailwind must not be in px by any means. it will destroy so that you cannot change the font size in the browser. so just the opposite of what you say. px should only be used in e.g. borders and otherwise you should stick to rem and em, as well as other units such as vh etc!
Dont Think you know Css if you Think pc is better then rem. Px Unit is the worst Unit you can use fir acesibility and scaling off Css!!
The part about rem and px is largely incorrect. Rem scales with font size, while px does not. Try sizing images using px and scaling up/down font size…
I've never heard of stylex before, aften spending a bit of time in the documentation, I was wondering, what are the main advantage of it compare to bare css files?
What are “bare” css files? CSS modules or just completely vanilla CSS? Did you read through the website already?
Feel free to create a discussion topic on the repo and I’ll answer your questions.
The hate on the * variant is making want to set my virtual keyboard aflame.
WHY WOULD YOU EVER DECOUPLE A PARENT WITH A * FROM ITS CHILDREN??? WHY???
Not only is this feature optional, it is specifically designed for this use case, for when parent and children are this intrinsically linked. Any other usage, and the inference of any other usage, is the demonstration of nothing short of a skill issue.
Now let sat a parent needs to be a Server Component and the child needs to be a Client Component. Fellah, just make two different files in the same repository. Problem solved.
It's very questionable to throw away type safety for custom non-standard CSS syntax that will collide with other tools if not handled and isn't type safe at all...
I didn't really understand what was wrong with REM
14:15 Nah, really be it group, siblings or now nth, these are classes that aren't meant to and shouldn't ever be used in different files. If you are writing tailwind blind on a component, I'm not afraid to tell you you're doing shitty work.
So, no move to version 4 in a long time?
Most people will never need to use many of these to style a decent app. If you need to use tailwind for super advanced features, just use css. That's my take.
I would NOT use tailwind without @apply. That's almost like going back to writing styles directly on the element.
The issue I have with using px for spacing is that it can really break the look of a page when you have the non-standard screen sizes. No one should be looking at a page on a 12inch screen, but they do and i have so many defects raised for these silly spacing issues where a row of action cards goes onto 2 rows because we've got a rigid px spacing.
(Yes I know we have overflow, but then they raise a defect for that :D)
13:15 Though the reality of JSX is that if you have the same component a number of times, you end up having to do that in JS and having either a style value or some tailwind added conditionally. I don't find that better than just having nth available, especially as here we still are working in relative terms, just like groups and siblings. In the end, this behavior doesn't apply to other parts of the code, it's specific to where you write it, quite unlike nth when used over a selector in regular CSS where anything with the same class just ends up having the same behavior.
As long as the performance stick will CSS rendering rather render by JS to convert and process the css will have a huge problem in your web page. If it affects, I think this is dangerous and risky
Tbh, not thrilled with this article. It’s full of typos and anecdotes without much backing. Nothing that changed my perspective
refactoringui came after tailwind
There should not be any runtime component necessary, tw-merge is such an abomination. Why not implement variants like in UnoCSS and just switch between classes like btn-active and btn-base. It's so much more logical and removes any runtime overhead.
Tailwind can select direct children like class="[&>*]:p-4" so I think class="[&**]:p-4" gives more of a custom flag than *:p-4 or **:p-4. I do appreciate the functionality for the CMS use case
The last comment by Naman about REM units is so wrong
I really love when people say "X is wrong" without explaining why or how
@@Pstrnil737 imagine a button with a text. Then increase the text size while button remains the same. What will happen?
@@eoz If you set the button height in px and the font size increases you get overflowing text, which is why he said in chat that sometimes you still need to use rem for some heights at 27:33. Is this what he was so wrong about?
Honestly disagree about the tw-merge part. Try making a site without it and you'll see you will never need it. And in the hand full of cases you want to overwrite a style you can use class="!p-2" for example.
TW leaves a lot to be desired - no support for dynamic styling and reusability is really lacking… why is this so popular?
cause is faster to write, easier to learn than normal css for new devs, and all the negative points of css are gone, allowing you to not worry about fixing common css problems but rather actually styling your app. Try to do the same thing with Tailwind and CSS and then let me know. I was skeptical too in the beginning, but after 3 days with Tailwind i was hooked, is soooooo much better. For dynamic styling you just install tailwind-merge and problem solved, super easy to use and powerful, trust me, i have been a dev since CSS was not even a thing, Tailwind is really really good.
15:50
I think this is an overreaction of the thing, many times you use tailwind you will also have both direct and non-direct children of your HTML that [should be] static and not something you freely move, structure is part of many components and you cannot change it and not change the styles as well. For some frameworks as angular that induces huge components with their "separation of html and code" this is also very reasonable to use, as well as with raw html directly. It is not [that] problematic and arguably good for some things.
Hm, actually, I agree with you partially. I don't think the *: is bad, but the **: is really problematic, starts to get more of a "spooky action at a distance" feeling.
My 2 cents, worrying about performance i find it absurd..90% of people here are not going to build massive UIs for millions of people where performance is going to be a priority, no need to be worried about that at all..All the features added could be POTENTIALLY a problem for large teams where you constantly have different devs on a single project, in which case i hope, there are senior devs spotting this issues and notify more junior devs for using it in a not optimal way. For the most, is not gonna cause any problem. Also, this features are so much for edge cases that i don't see people use it so often, so why not..I agree that should support tho tools like tailwind-merge and i agree that maybe some of this features not being atomic, kill the purpose of tailwind, but there are those edge cases where you might find them useful, and we know how annoying is when a tool do not provide you with the necessary things to solve the problem, especially as JS/TS devs in React where you need tons and tons of third party libs.
what's the point of making blog posts about tailwind v4 having harmful features instead of filing pull request or something to disregard the usage of ** entirely?
more footgun to use!
Maybe it's a win for AI generated code. More styles that AI can use.
Also, while it is not an argument that is relevant to Tailwind per se, I think it is important to consider the UX when it comes to shadow dom. There are a lot of video player components and their subcomponents nested in shadow dom, which is a nightmare to apply user styles to. These players are often terrible for accessibility, no decent keyboard controls, an annoying hover animation with an overlay gradient, a tiny seek bar that is impossible to click, ... And so, user needs to write a browser addon and set up a tailored javascript, a somewhat recursive element observer, to wait for lazy loaded elements to apply styles to. Suffice to say, this is prone to breaking, when de website owners decide to change stuff. Moreover, it is hard to change the player, because of tight DRM integration. Also, the picture in picture Firefox player doesn't have good accessibility, subtitles on most websites don't work, ...
* & ** feature is more browser performant. Allows the browser to optimize.
I think these cascading classes are useless. There are comparatively much less use cases for them, and if you do want to use them you could always use arbitrary classes e.g: [&_*]:p-2 === **:p-2
Uglier? Sure, but who cares since it's something that should be used sparingly. Allowing it outside of the bracket syntax will enable more room for misuse.
I was about to pitch BulmaCSS, but I clearly misread the clickbait.
tamagui is the future, not tailwind
Love your content, but lately I've been kinda lazy to watch it, since it's always a 30+ min video.
Look -- any project built which gets traction will get the question to add more customization. So they add customization, and more options and so on. Eventually it's just a big set of tools and people will always find ways to use those tools to shoot themselves in the foot -- and then complain about the tooling just being bad. Use Tailwind, or don't. This constant yammering is so annoying.
I disagree with you on the ** and * features, it should be there for people to use it. Most places won't need, and that's fine.
Tbh reading all these comments about clickbait makes me want to turn off this video after 2 minutes. Sorry theo.
Omg someone actually mentioned dangerouslysetinnerhtml.
What the f is that ? Don't you guys know to sanitiz your innerhtml.
Very bad anti pattern against how js works and Dom works
If you don't know how to prevent XSS attack I judge you are a lazy dev.
Another 30 minutes
Disagreed. You should specifically use * to affect children that should NEVER be imported without their parents. Basically you're using * in cases where you can do otherwise, especially with inputs.
Eslint to block ** is out yet?
Click bait noob
And why would a * child be in a different file EVER. Are you insane.
When using different components?
css mask would be nice. Had to write my own plugin
I see it useful sometimes you works with external ui libraries and want to modify something inherit, like svg, devs need to understand not to use it every time but this is common sense.
Great video! Double star! ⭐⭐
restyle
Sounds like we need a fork 😅
its "n uh - m uh n" not "n uh maa n"
lol these hot takes are all based off the fact devs are stupid and don’t understand atomic css..
This is all nice, but has anyone compared the css file size after the build? v3 was automatically smaller without much intervention. v4 is bigger because it's full of unused CSS variables.
Straight Yap Sesh
Deleted my previous comment, if you came to complain.
Lesson learned.
23:15 can anyone give more detail on what aman and theo are saying about the 'cn' function? I use this in my projects and would like to know why they disagree with using it, but agree on using tailwind-merge. Do they not achieve the same thing?
cn uses tailwind-merge behind the scenes.
Honestly, idk. I like to use cn(), even thought it uses tailwind-merge and clsx under the hood.
@@DeepTitanicdude what are you talking about? Cn() is a utility function which is basically "twMerge( clsx( ...inputs ))". This is going to override your tailwind classes.
Its a custom helper function you can probably find in your lib or utils folder. Its a combination out of clsx and tailwind-merge.
@@gergoradeczki TWM resolves conflicts CN just deals with concatenation. They both can handle conditional statements
Again???
all this guy does is yap, i guess that what it means to be a developer
this guy's comment section is botted lmao, and im not talking about the complaints
It's always so funny to watch how taliwind community fights the exponentially growing problems that tailwind brings them.
Philosophizing about whether another new syntax is good or bad, whether "@apply" is allowed to use or not, how classnames and prefixes are inconsistent, how to use it in a way that won't uncontrollably bloat css bundle...
Instead of just writing normal css + css-modules and being a happy and productive developer.
Exactly! I wonder what percentage of Tailwind users actually know that all features of tailwind (and more) exists in plain css and that scoping is fixed by css modules.
The only advantage tailwind has left is that it provides a good set of base tokens of colors and spacings. You can easily create those yourself as css variables and just stick to those.
@@paragateoslo Another advantage I admit is that for things like defining simple layouts tailwind is handy indeed. You do your "flex gap-3 py-6" and you're golden.
Maybe some font-size too.
Very quick, simple, minimalistic.
But that's it. Anything more complex, that requires an actual styling, with tailwind immediately turns into a horrible unmaintainable mess.
How many years of developing in CSS have you got under the belt? CSS can be a real pain in the ass and absolutely not fun to write and maintain
@@MiguelDebruyne 8 years.
CSS _can_ be a real pain. And majority of it relates to global scope - which is solved long ago by css-modules.
Tailwind constantly _is_ a pain. And on its own it solves none of those problems (as it was mentioned, tw-merge isn't even part of tailwind) while bringing lots and lots of new ones.
@@MiguelDebruyne 7, but i never remembered css being a pain in the ass what so ever. The reason is, as I mentioned scoping. Avoid any global css that is just a one liner utility class and you'll be fine.
can we just delete css and make something better? big sigh
I’m scared for anyone that this scares/concerns them. I’d assume in any codebase this should be the last concern. Data schema, scalability, maintainability, security, db updates, breaking changes, logs, permission layer, bugs. No way devs are tripping over this.
The user/client is not interested in you data schema, scalability, maintainability, security, db updates, logs and permission layer
But when you styles are broken even the most non-tech guy with spot it
Clerarly frontend is not your domain. Just try to recognize this and move on. All your concerns are 90% backend stuff. CSS is a huge part of frontend and a lot of time has been spent optimizing that and they continue to discuss the stuff. Doesnt make any of your concerns irrelevant, just that different people are concerned with different stuff.
@ valid.👌 I do front end also; but deff see your point.
Yo Theo! Let’s go!