Not entirely true. I'd be totally fine with class names that identify what type of widget it is. <div class="card">, <div class="modal"> <button class="secondary-action">, or <span class="clipboard-copy"> are "made up CSS class names" that identify a type of widget and used without making no assumption about presentation concern. <button class="btn btn-small"> and <div class="w-12 rounded-small"> are not.
And yes, I understand that tailwind allows you to create types and @apply them. What I am saying is that (1) I'd like to see this separation to be enforced and not just possible and (2) plain SASS also lets you do that already. so I don't understand what I would gain from adding tailwind.
> Components are a better way for separating concerns
Except when they aren't. Downthread I gave the example of a library project that I want to define the functionality/behavior but leave the looks/styling to the consumer.
Desktop GUIs have theme engines for ages, yet frontend web developers want to get excited about frameworks that allow for "night mode"? "Night mode" is just a way to say "you can separate presentation and content however you want, as long you only present in two different styles".
Sounds a lot like an edge case. Most consumer applications do not need theming.
My larger point is that when you are developing a web app, it would be much easier if the framework was designed in a way that separated the concerns of presentation and behavior of the components.
Just to use Vue as it is what I am using now and had to get a bit more familiar: you have libraries like Vue Bootstrap and Vuetify (for Material Design) which have a lot of duplicate functionality yet are not compatible with one another.
If the concerns were separated, you could have components that have a common behavior and only differ in the visuals. Less work for everyone involved, easier for developers to get started, less unnecessary fragmentation and the possibility of positive feedback cycle between different design systems.
You can only change so much of the styling without changing markup.
https://tailwindcss.com/docs/theme [1]
> You can only change so much of the styling without changing markup.
I take that you are not old enough to remember the CSS Zen Garden?
Even with craptastic CSS2 implementations of IE7 and no browsers that could fully pass the ACID3 test, the Zen Garden showed how anything could be changed without touching markup.
Don't tell me that it's harder in 2020 because it is a whole lot easier.
Tailwind does “enforce” separation of concern between styling and content, just in a different way than the separation of html and css.
Consider the utility class m-1 and m-2. What they are supposed to say is that element with m-1 class and element with m-2 class should have different margin, with the m-2 element probably have a slightly bigger one, and every element that uses m-2 class should have the same margin. It doesn’t specify styling at all. The concerns of styling are completely separated into the theming system.
All that the utility class define is the relation between elements. Eg. which elements should have the same margin/color/typography etc... This would also provides consistency in your designs, unlike pure css which allows you to do whatever you want without defining structure and relationships between elements.
I would say tailwind forces you to separate styling concerns out of your content and into your theme. You could probably replicate css zen garden using tailwind theming system.
But if you are saying that you have different "utility" classes to specify different margins, and if these classes end up in your HTML, you already have styling/presentation definitions that should never be the concern of the document writer.
I was there for the Zen Garden, and it was great at the time and in its context (Flash and image maps!), but now I'm using the web stack for a 3D editing application, and my last job was complex GUI for managing large number of IoT devices. The idea of separating "the content" from "the presentation" does not apply anymore. It's just not a thing. Good software engineering is super important, more-so than ever I'd say, but keeping some parts of the UI in the .css files and some of it in the .ts files does not equal adequate "separation of concerns" in my context. It's just not that simple anymore, and in fact in the previous job it was an impediment, since UI refactors became much harder because of the state of the .css files. In my new project, which was moved over from Bootstrap shortly after I started, Tailwind has made sure that many of the old problems just don't arise anymore.
Yes, with vue it is nice to have <template>, <script> and <style> on the same file, but what if I'd like to have multiple styles? Why can't I say "This component has this structure and this behavior and it allows for style A, B, and C" and have the application bundler choose themselves what style they want to use? What if the application bundler thinks "I want to use style C, but I'd like to customize some rules"? How do you do that?
> moved over from Bootstrap shortly after I started, Tailwind has made sure that many of the old problems just don't arise anymore.
Yes, Tailwind is a step up compared to Bootstrap if you consider how you can define the types and remove the utility classes from your HTML. But my feeling is that people who are so fascinated by the idea of Tailwind custom types are just in the process of reinventing semantic styling, this time with a preprocessor to compensate for the verbosity and some helpful mixins to overcome inconsistencies between browser implementations.
So, to repeat the question: What am missing? What do I have to gain from Tailwind if I am using already SASS as the preprocessor and a good library of "utility classes" that can be @imported/@use'd/@apply'd to the document without touching the HTML?
Right, and I don't see the HTML and the CSS as separate concerns when the HTML describes a GUI, not a document. There being two languages in play is a historical detail that as developers we have to tackle in the best way. I don't believe that it's some sort of holy spirit we have to respect.
For my money, separation of concerns is things like where do I put my mutable state, which part of the application talks to the network, etc.
> but what if I'd like to have multiple styles
I have to say that's not a thing I've ever needed to worry about. I'm worried about things turning into a big pile of goop. The old approach too often devolved into making a separate class for each tag. Starting with repetition and noticing patterns that then get factored out is a better approach for me.
I will say, though, that in Tailwind it absolutely would be workable to give e.g. colours a semantic name - like primary and secondary - and then map those to whatever you want, including CSS custom properties. So you absolutely can implement both build-time and runtime theming at that level if you want, where you just need to change configuration options or a set of properties.
> What do I have to gain from Tailwind if I am using already SASS as the preprocessor and a good library of "utility classes" that can be @imported/@use'd/@apply'd to the document without touching the HTML?
Again, I'm not afraid of touching the HTML, that's not a goal for me. In my work, any change of any consequence is going to involve both HTML, CSS, and JS anyway. I am much more afraid of accumulating cruft in poorly-maintained CSS files.
Tailwind's utility classes are pretty fantastic - for instance, you can define a colour palette and they also become usable in gradients - so they're a good place to start. I also like that it's basically real CSS because that forces developers to learn, which will lead to better layouts. And yes, it will in some cases lead to the same set of classes as a semantic approach, because sometimes that classes are what makes sense. But the thing is, how do you arrive at that set of classes, and what do you do with the edges and boundaries and all the glue you need. Tailwind provides an extremely usable starting point and a good thought pattern for building the type of apps I do.
You know that you can create themes in GTK (a Desktop GUI) using CSS nowadays, right? Whether a document or a GUI, behavior (how it works) and presentation (how it looks) are still separate concerns.
> (Multiple styles)'s not a thing I've ever needed to worry about.
Yeah, others have though - both as consumers and as integrators. If you are okay with the idea of re-inventing wheels every time you want to have a different color, plenty of people are not.
> I'm not afraid of touching the HTML
It's not a matter of being afraid to touch HTML. It's a matter of not being able to! Whether in terms of ability (some marketing person that is putting together a wordpress or Shopify store and can only go with different artifacts provided to them) or from the nature of the source code (e.g, imagine you want to make a RSS/Atom feed reader, embed a Tweet on your site with a custom styling or use an OSM tile editor), if you are not able to touch the code but you can select different styles, then it is fundamental that the data is separated from the style definition.
You might not think that this is important for you to do your job, but I think that is extremely short-sighted. What made the web as interesting as an application platform was the idea that the user agent could be extended. It is in our interests as users to keep the web open and able to be tinkered with, and the easier it is to separate the layers that people want to improve, the better.
Does GTK offer CSS layouts? Do I describe the elements of the UI using HTML? As far as I know they just use a subset of CSS - aren't the selectors predefined by the framework? I don't recall, exactly. But GTK provides an entirely different set of primitives, I don't think it's the same problem at all if you're just providing fonts and colours. Again, I'm talking about something rather specific, creating complex, desktop-like user interfaces using HTML and SPA frameworks.
> behavior (how it works) and presentation (how it looks) are still separate concerns.
Yeah, but I wouldn't say that that distinction maps to the distinction between CSS and HTML at all, not in my context. HTML, especially document structure, is also presentational. That's really what I mean when I say it's not a "document".
And any way, no matter which approach (and platform, I'd wager) you use, if you want to completely restyle a complex GUI application like what I'm writing in the way you could restyle HTML documents like the Zen garden, you're looking at some serious engineering effort in keeping the so-called behavioural HTML and Javascript in check and documented. It won't just be about how you handle the CSS, it'll be about how you handle everything.
> Yeah, others have though - both as consumers and as integrators. If you are okay with the idea of re-inventing wheels every time you want to have a different color, plenty of people are not.
I actually feel like I have better control of my colours with Tailwind than I ever did. Currently I'm using a limited selection specified in the Tailwind theme. They have names like $adjective-$colour, so it'd be weird to change them, but if that's important to you that things are themable, as I stated, you can put in the effort to set it up with semantic names and make them customizable at build time or at run time. I still think you'd have a better experience than making separate classes for every tag and reimplementing that for each theme.
> It's not a matter of being afraid to touch HTML. It's a matter of not being able to! ...
And all of these things you list are not what I do. The examples that you list have a different set of trade-offs. I'm not embedding other people's code in my GUI, and I don't expect them to take a random chunk of my application and put them into theirs. OpenDoc was a fun idea, but it didn't take off.
> What made the web as interesting as an application platform was the idea that the user agent could be extended.
I don't really know about that in the general case, I think there are more reasons than that, but in the specific case I'm certain it's wrong. The reason my company is doing what it's doing on the web is 100% about distribution. Arguably, the web stack isn't even that good for making the kind of UIs I do - but if we did what we're doing in Java, we wouldn't get any users (or investors).
I totally agree with you about openness, but openness in my space means providing good APIs and integrations with other services, not allowing user stylesheets. A user stylesheet for my app would mean a twenty page list of weirdly interdependent CSS selectors, and the end result for someone who implemented it would be something like a colour theme that only works for app. Explain to me who would want that.
This smells of complexity to-justify-my-paycheck thinking about software. Css and html go well as seperate documents which makes things like theming and maintenance work but not frustrating. Why do we need the tooling overhead if the gains are marginal? SCSS gave css the powers it needed to be flexible but Tailwind sounds like classic cool-kiddery just like react.
React etc. are extremely nice if you're making complex applications for the web. Of course it can be overused, but I'd say that some kind of SPA framework (and state management framework) is a requirement for the work that I do.
The fact that most front-end frameworks implement some kind of React-ish approach should at the very least make you wonder if dismissing it as 'cool-kiddery' is perhaps a bit too broad a swipe.
With Tailwind, at first I had similar concerns. I used it a bit and it seemed okay, but went back to the good old fashioned way of doing things. Then, in a later project, I decided to give it a proper shot and it measurably increases my productivity, reduces complexity, and reading articles about why it's not 'separation of concerns' (in many cases) convinced me I had no real basis for being against it other than being a curmudgeonly old-skool guy.
It's totally fair to stick with what works for you, but perhaps dismissing both React and Tailwind as 'cool-kiddery' is more a 'stuck in your ways and insecure enough to need to justify it' kind of thing than it is a reasonable perspective. Sometimes new things /are/ better!
After (a short) twitter discussion with Adam Wathan about this, my impression is that his idea is to basically never use @apply, and instead create micro-components to encapsulate your basic styles. So instead of <div class="modal"> you create a component modal, and then you can put all the utility classes in its html, and still be able to quickly change it if needed.
Honestly, the only possible place where this may make sense to me is if you have tooling that can keep a two-say sync between designer tools and programmers tools. I think AirBnB was doing something like that with Sketch?
Aside from that, honestly I am still failing to see any benefit. If you are tying yourself to a JS codebase, you can still do that whole "utility classes at the component level" with plain SASS and global variables and mixins and you still don't need to put class definitions in your HTML.
Let me see if I can draft a quick Vue example:
<template>
<button><slot></slot></button>
</template>
<script>
export default {
name: "my-button"
}
</script>
<style lang="scss">
@use "my/sass/variables"
@use "my/sass/mixins/buttons"
button {
@include buttons.rounded($variables.radius-button-small)
@include buttons.colors($active: $variables.primary, $background: $variables.primary-accent, $disabled: $variables.disabled)
}
</style>
No Tailwind required. Easy to customize. One central place to organize your style and - most importantly to me - no css classes shoved in the HTML!Now, someone might ask for "a large button inside the hero section from the home page." Let's go about that...
<template>
<div class="hero">
<p>Welcome to the beautiful site</p>
<MyButton>Sign up now!</MyButton>
</div>
</template>
<script>
import MyButton from './my-button.js'
export default {
name: "hero",
components: {MyButton}
}
</script>
<style scoped lang="scss">
@use "my/sass/variables"
div.hero {
button {
width: $variables.size-button-large-width;
height: $variables.size-button-large-height;
}
}
</style>
Really, I am yet to understand what I am missing by taking this approach. The example above is contrived, but I don't see why more complex widgets and even whole pages couldn't be done this way. The mixins are the place where you can have all of the abstraction you want, you can even add some logic depending on the values from the variables.So, let's take a look at the benefits:
- If next week the frontend team decides to switch from Vue to anything else, the SASS code does not need to be touched at all.
- If next week the design team brings a whole new "Design Language", the JS code does not need to be touched at all (unless of course the design system also brings new functionality)
- The styling could even be verified on a series of static HTML pages. If the designer does not do any code, they can verify if the implementation matches the designs by opening a reference template, no need to run a whole JS app.
Downsides:
- If you want the code to be truly portable, your SASS need to follow a standard convention of @mixin names/parameters as well as variables. Honestly though this IS what I would expect from a "CSS framework", so I am not even sure it's a bad thing.
- You don't get to put any hip CSS-in-JS framework on your resume.
Also on bigger project you're almost guaranteed to have someone on the team who will insist on naming their classes in totally unintuitive way, or you'll end up with .big-blue-button that will at some moment end up red actually because they've been in hurry and forgot to rename the class.
One of the biggest benefits from using the frameworks is the standardization and uniformity, you're guaranteed that everyone on the team now or anytime in the future will know exactly what classes/mixins/variables are available and will have a documentation on how to use them. You need extra people to meet the deadline, you just hire devs who know the framework and you're good to go, no extra onboarding needed to explain where the buttons variables are located, and where to apply which, and how to name their classes, etc.
On the technical grounds, you are right that the biggest thing against jQuery was that it operated on the global context and that made large codebases messy, and that CSS alone might lead to a similar experience.
But I am not talking about CSS, I am talking about having an organized SASS framework, which can provide the utility classes (mixins) and which then your code would be organized by "base elements/components/pages" along with variable definitions.
The approach I am using and suggesting does require a certain discipline. It will also require that the whole team conforms to the idea that no class should represent presentation directives. But in my view this discipline not only would be beneficial in the long term, the separation of concerns would improve the chances of making reusable components and design systems that are easier to improve on its own, separate from the specifics of each underlying website/webapp that tries to adopt it.
This is the clearest concise explanation of this I've seen, thank you.
That you frequently have to add <div>s in your HTML in order to get CSS to lay stuff out correctly is enough evidence for me. :)
I'm trying not to make this too much of a dogmatic discussion, but is the cultural norm among developers going to be to just throw their hands in the air and say "styling is hard, let's go shopping for divs"?
On the one hand, I get that most people nowadays see HTML and CSS as object code, and is not that important to be abstraction that people think in. However, current web application frameworks can not solve problems that desktop GUIs frameworks have already solved in the 90s and no one is asking themselves "is this really the way to go forward?"
The experiment failed though, we've been trying for over a decade. You can't let one group write the HTML and one group write the CSS (with the pipedream being the designers writing the CSS). The only way to make complex designs is to modify both as you develop. They're too intertwined and CSS alone isn't powerful enough to do everything you want.
Keep your actual data like blog post content, blog post meta data, images etc. separated but it's 1) not practically possible and 2) there's no significant benefits to keeping your CSS and HTML separate besides sticking to dogmatism "best practices" that haven't panned out.
Also, it's not a matter of strictly separating the groups of people doing one task or another. It's a matter of being able to extend in one dimension while keeping the other untouched.
> They're too intertwined and CSS alone isn't powerful enough to do everything you want.
I'd argue that is precisely backwards. The reason that we don't see any more different designs and more bold experiments is because we are not defining the interaction points between different layers in the development stack.
If most developers keep this mentality that all they need to do is to get a system that solves their immediate problems and solves their own unique solution, then all they are going to do is this mushing together of their structure and their presentation layers, and all we are going to get is a pile architectures are going to converge to different local maxima. If instead we don't take the easy way out and make things with flexibility and extensibility in mind, then the likelihood of it becoming the basis of something ground-breaking grows enormously.
> Also, it's not a matter of strictly separating the groups of people doing one task or another. It's a matter of being able to extend in one dimension while keeping the other untouched.
Have you worked on a website with a complex web design? If you know how to do this where you write the HTML with only semantic markup tags then don't touch it again while you style it with CSS, you're breaking new ground because nobody has figured out how to do this.
That's why Tailwind, Tachyons, Bootstrap etc. exist and continue to evolve - nobody has figured out the best way to do things yet. The MVC style you can do in other languages just isn't practical with standard HTML and CSS and it's not through lack of people trying. CSS has rapidly been improving the last few years but we're still a long way away from being able to avoid e.g. adding a wrapper div or shuffling HTML around to solve CSS issues.
> all they are going to do is this mushing together of their structure and their presentation layers
I think the issue here is you think HTML is for structure only and CSS is for presentation only, when the practical reality is HTML is mostly part of the presentation layer as well because CSS alone isn't powerful + practical enough.
Large websites already store their page titles, page content etc. in a structured CMS database. What tangible benefit are you getting by pushing to separate structure and presentation more than this?
For non-web apps, how is structure and presentation split up more than this and how does it differ from web apps?
No, I said that I style it with SCSS.
I can give you all the utility classes you want - in the form of mixins. Then all your site styling and components can be defined in terms of these mixins.
I said that I am not against Tailwind in general. What I don't understand about it is the idea of having already all the mixins and utility classes and then letting people stick those in the HTML.
> What tangible benefit are you getting by pushing to separate structure and presentation more than this?
Go take a look at the template sites like ThemeForest and CreativeTim. Some of the templates look actually quite nice and could be an excellent starting point for a project. What they all have in common is that you have 5 JS technologies and maybe 3-4 different styles and they sell each permutation of these as a separate "bundle".
Then you actually download the thing and start working with it. You find out that some older versions will use Bootstrap 3, some will use Bootstrap 4. Some of them have their widget implemented with an outdated jquery plugin, but the rest is with React/Vue. And then you realize why no one makes big projects out of these things, because it requires an all-or-nothing approach when it is not necessary.
In my fantasy land, we get javascript UI component libraries that are standardized and a separate set of SCSS implementation of "design languages". So when I am writing an app and I want to have, say, an autocomplete that looks like Material Design, I can import only one widget and one "theme", instead of hoping that some React/Vue/Angular/Nuxt/Svelte/JS_FRAMEWORK_DU_JOUR has already implemented components following the style of Material/Bootstrap/God-Knows-what-Design-Language-is-fashionable-today.