3 ms·
The same is true of CSS classes, though - there you have the same choice between reuse and duplication. Do you have .button-primary, .button-secondary, etc, or
by MrJohz 3y ago
The same is true of CSS classes, though - there you have the same choice between reuse and duplication. Do you have .button-primary, .button-secondary, etc, or do you use modifiers instead? The combinatorial complexity is inherent in the design of these sorts of components, you won't get away from it just by using a different tool to write your styles.
- lawn 3y agoBut CSS handles it much better, which is the point. You separate it into a .button class, and then further specialize it by adding more classes (like ".button .button-primary"). With Tailwind everything is duplicated, but with CSS you can move out the common parts.
- 5Qn8mNbc2FNCiVV 3y agoNothing holding you back doing exactly the same with Tailwind.
- lawn 3y agoOf course, the solution to Tailwind's problem is to refactor it with CSS classes...
- pcthrowaway 3y agoAnd to do this with a component framework and tailwind you give your <Button> component some props that customize it. With CSS you also have to worry about the cascade way too much, so while you are doing much of the same work with Tailwind, you get the nice benefit of inlining the styles which will actually apply to your component. Yes, you still have to think about organization and how to make different styles apply to variants of the main class, but it's so much easier to not also have to worry about how cascading rules might apply and constantly check different rules for specificity and overrides
- tisc 3y agoI am curious what you - and with you more proponents of Tailwind in this thread - mean with “component” and “component framework”? I’m also Zen-garden age and with my very limited React experience this does sound like you are meaning a component framework like React, correct? If so; what would be the motivation for using JavaScript to style a button? Call me old - my coworkers do -, but that feels counterintuitive. Please note that I haven’t really formed an opinion on Tailwind yet. This is an honest question.
- MrJohz 3y agoComponent in this sense is typically just "a composable unit of UI". That often corresponds well with JS frameworks that want to be able to attach state and behaviour to those units, but you can have components without needing Javascript. For example, partials in classic server-side rendering libraries can be thought of as components, although they tend not be used at such small scales. In CSS patterns like BEM, the B ("Block") is in many ways a component with different sub-elements and states. This is partly why Tailwind provides the @apply directive - it allows you to create "CSS only" components even if you don't have other ways of creating components. That said, other forms of components are often easier to use, and if you already are using them, Tailwind recommends using them for style reuse rather than @apply.
- pcthrowaway 3y agoBy "component framework" I was honestly thinking of React, Svelte, Vue, Solid, Qwik, and Angular, though I don't actually have experiences withh all of those. I also don't have experience with native webcomponents or HTMX but I believe it would apply to those as well. I do have experience with HTML templating such as Jinja and ERB and it would absolutely apply to those as well (though I don't think those would count as component frameworks, and certainly wasn't what I had in mind) Basically some system which allows you to write some "unit" of markup such as <li class="search-item-result"> <div> <img src={item.icon} /> <a href={item.url}>{elided(item.url)}</a> </div> <div> {item.previewText} </div> </li> Which represents some logical unit which should be displayed in a consistent manner (with allowed exceptions, you can style the first and last of the result list differently using CSS selectors or tailwind classes) With Tailwind, you just drop in the class names you want to spruce those up, and your component framework or templating library will give you a way to render a series of them with different properties. You have to repeat neither the markup nor the class names for multiple items This is possible with CSS of course: Just add rules that apply to `li.search-item-result`, `li.search-item-result>div:first-child`, `li.search-item-result>div:last-child` but this creates a number of problems for maintainability. Say you want to wrap the first div in another element, or change the tag type, or add a spacer element before it. Now you have to repoint your CSS rules. Additionally you have to think about the cascade, and how your CSS rules might apply to elements you didn't intend them too. There are numerous systems for resolving these issues (BEM mentioned by the sibling commenter being one of them), but you end up writing a bunch of class names (and IDs for elements you only intend to render once on the page) which you have to name and reference. Then you have to probe devtools to determine which rules apply to which elements. I can empathize with devs who have their own systems dialed in and don't think Tailwind brings them much value here, but if you don't have that system dialed in or just don't like thinking about names and specificity, it's a massive boon. Also, you end up writing a lot less code altogether since you don't have to write selectors or custom class names for everything you want to target precisely.
- MrJohz 3y agoIt is completely possible to do that with Tailwind and components, I do it all the time. I'll create a Button component that takes parameters like `mode=primary`. The Button component contains a `button` element with some common classes that apply to all buttons (padding, borders, shadows, etc). Then depending on the parameters, I'll append other specialised classes (usually colours). The only thing you have in CSS that is harder when working with Tailwind is overrides - e.g. "this component is normally blue, but it's green if this class/parameter/attribute is set". That said, even when I'm using CSS, I tend to find overriding, except in the simplest of cases, usually causes problems, because now I need to make assumptions about the order of declarations that are difficult to make in a codebase maintained by multiple people over several years. For that reason, in the button case, I would typically make it so that the different modifiers (.button-primary etc) are mandatory when using the .button class.
- snowcode 3y agoI'm not a CSS guru, and as a result I've had to do things in a very very simple way. Currently the simplest solution for me, involving no additional server side frameworks is to just "compose" the static html on the server or at build time. So a "base" class of re-usable styling could easily be a static string. I wouldn't start by thinking about inheritance, I'd only consider it if and when I actually hit that problem. It's often just a single edge case. So my code is generated server side, using something Jam-stacky like Hugo or Cloudflare pages, (with a cloudflare worker that dynamically replaces or modifies a button ...in that very one specific edge case.) Your existing example needs to be made more complex though because I'd just use standard CSS for that, for example button.submit { color:blue) button.submit.critical { color:red } i.e. all my buttons are blue, except that one special case where I have a "critical button" and we "override" the color to "red". I simply flag it with the extra semantic attribute and style it accordingly.The button will clearly be red because the css for red has a higher specificity, but it also "reads" easily as such if the css is properly crafted. Of course it's possible to write Semantic CSS that no-one can follow; and the same goes for Tailwind. The problem with CSS though, is unfortunately the most common approach is to add a new DIV, and slap on a CSS definition that ignores all inherited styling. So, unless you're going to re-write everything a big corporate ball of mud is made up of, Tailwind works better here, since it's PURPOSE is overriding and ignoring everything. He says ..ducking!
- snowcode 3y agoIs this really an argument for Tailwind though? isn't this just an observation that both approaches seem to converge when the systems get very large and complex? At which time the work and effort is the same, except ..in the case of Tailwind you're using a made up syntax, and when writing similar amounts of code using CSS you can do it using the CSS standard. The key difference is that you would have to hope that Tailwind outlives CSS as a standard in terms of tooling and language support and continuing improvements (evolution) over time.
- MrJohz 3y agoDefinitely, Tailwind is just one approach to solving this problem, there are plenty of others. That said, one of the big advantages of Tailwind over other approaches, at least in my experience, is that it is far less bound to typical JS workflows, which means if you want to write HTML with your own favourite templating language, you can just drop in the Tailwind CLI and still get a lot of mileage out of the system. Compare that to CSS-in-JS or CSS modules, which are both very specific to the Javascript ecosystem. The other big option is just using a methodology like BEM and being consistent with that, which in fairness also isn't bound to Javascript and has the benefit that - like you say - you're writing CSS as opposed to a DSL that is mostly equivalent to CSS. For me, the problems there come from the lack of tooling for writing really maintainable CSS - stuff like scoping and detecting whether a class is still in use. But it's definitely still an alternative, especially with some of the new features like nested selected that are coming out now.