Hi Adam! Excellent wrap up on CSS strategies, congrats for the article
My path is fairly similar to yours, and I would say most people who have been doing frontend for living can relate to it as well.
I've been an OOCSS evangelist for a few years now, the Phase 3 group of your article, but some months ago i've started adding some utilities to the party as well: spacing, coloring, typescales and my new favourite is a personal version of FLA from StefanKovac which means I'm now in Phase 4. What got me to this point was the useless or over engineered abstractions or that you've mentioned. What prevent me to go fully functional CSS approach is just one thing: clarity
Let's take a second look at that specific the
actions-listpattern. Let's add just a little extra complexity there. Responsive complexity. Imagine that your buttons are bordered, there's no space between them and that in small screens they are stacked vertically and on bigger screens horizontally. You want to collapse borders (like tables do) by using the negative -1px margin-left plus you need z-index on :hover trick.
OOCSS vs FCSS:
That escalated a little bit right? In modern applications, designed for thousand of screen sizes, complexity can be much higher that a "simple" pack of objects" and single breakpoint. So in the end I would still use a OOCSS pattern in there.
Class names should communicate useful information to developers. How much information can we glean from the smallest possible source? Is our code self-documenting? Can we make safe assumptions from a single context? How much do we have to rely on external or supplementary information in order to learn about a system"
We don't code only for machines, we code for our teammates as well.
And that's exactly what you're trying to solve with Tailwind CSS!
And i'm curious about it: getting the benefits from rapid and dry Utility/FCSS approach, but keeping the OOCSS clarity!
For a SASS lover like me, a major set back would be that we can't dinamically generate mixins we do with atomic classes. We can use extend or silent placeholders but we know that mixins are better for performance. So it will be more tuff to do the setup manually.
Keep up and looking forward for that Tailwind CSS! Subscribed!
Yes, I shamelessly admit that I'm a fanboy of Harry's work
That was an awesome read Adam. One of things I really appreciate is that you went into detailed examples with everything, including the little bit about Vue.
I've been using more and more utilities lately and while it's been amazing I've wondered, "Should I really be doing this". Reading your article helped me make sense of the arguments for and against this approach. Thanks!!
The css framework I'm most looking forward to trying next: https://www.iotacss.com/ but I'll certainly check out Tailwind to see your approach.
Great write up! I have one concern though, what if you want to change let's say your card elements to have a different type of border radius. Then would you need to go through all your card elements in all your html templates and change their classes? I would rather create semantic classes by @extend'ing the utility classes (sort of like your .btn-purple example, but for all elements). That way you can have semantic classes in your html, while still getting to pick out of limited number of utility classes. This would also resolve the issues that might come up because of the order of the classes.
If I see a pattern repeating enough and I can confidently say to myself, "if I change one of these, I'm going to want to change all of them," I'll usually make a new class that serves as a higher level abstraction around that group of utilities. Card is a good example for sure.
I prefer not to do this for everything though, only when I see patterns. Otherwise you end up with this giant ball of CSS that's super coupled to your particular project, and you have to constantly make new classes even for parts of your UI that are never repeated, so your CSS size will grow linearly with your project size, which is death for maintainability in my experience.
I wouldn't use extend because it has a lot of nasty side effects on your source order, especially when a component tries to extend a utility, because it'll move that component definition to the same place in the stylesheet where the utility is defined, which means that component's styles may get precedence over other utility styles you might want to add as modifiers.
Instead, use mixins. This is really easy in Less because any class can already be used as a mixin, but if you are using Sass, I would extract a mixin from a utility as soon as I wanted to reuse it, and use that mixin in both the component and the original utility, like:
EDIT: Code samples don't turn out great here, so check out this gist instead:
Thanks for the great examples, I can see your point. I guess it also kinda depends on what kind of a project you are working on and with how many other people. Also LESS looks pretty good for something like this so I will give it a shot in my next project.
All in all really eye-opener article, made me think about how I structure my CSS. Thanks for sharing.
Fantastic article, made me seriously rethink how I build parts of websites and apps (although I was already moving in the right direction).
I really hope SASS adds that LESS ability, I don't want to write includes for every class.
Very nice article, I'm even thinking now about using Less again instead of Sass. Looking forward to see Tailwind framework - definitely want to try "your" approach to writing CSS.
this is how I do it as well. It's essentially combining the most prominent methodologies together, or at least their most important aspects.
This becomes even more awesome when you make use of scss mixins and functions.
Awesome write up! You answered every question that crossed my mind while reading it. I remember trying "Semantic" markup and it ended up being a mess. Since then I've switched to BEM and haven't found a reason to change yet.
Great article! Showing the evolution of styling strategies is the best way to make the case for utility classes.