..., CSS Modules, CSS-in-JS, and Tailwind when I'm not constrained to do so.
I've been thinking about this for quite a while but wasn't able to articulate it clearly until I watched Josh W. Comeau's talk "How to Teach CSS".
Let's take the problem that Josh starts off his talk with. We have an image sitting in a container and it turns out that there's this weird gap under the image.
An interesting thing to notice is that the problem persists even if we write it using JSX or elm-html
. So it's fundamentally an HTML/CSS problem.
We can fix it using the first solution that Josh found, in particular, by using line-height: 0
on the section
element. And, it's easy to translate that solution to corresponding solutions in elm-css
, CSS Modules, CSS-in-JS, and Tailwind.
For e.g. with elm-css
:
import Css
import Html.Styled as H
import Html.Styled.Attributes as HA
main =
H.toUnstyled <|
H.section
[ HA.css [ Css.lineHeight (Css.px 0) ] ]
[ H.img [ ... ] [] ]
For e.g. with Tailwind:
<section class="leading-[0]">
<img ... />
</section>
Great, problem solved. Move on to the next. But wait. As Josh rightly points out, when you deeply understand the problem, you realize that that's not the best way to fix it. And this led me to a key insight.
Key insight
All these abstractions, elm-css
, CSS Modules, CSS-in-JS, Tailwind, etc, that try to abstract away CSS, fail to do so because they DO NOT change the mental model that you have to use to reason about styling problems. They definitely make it convenient to use CSS but when styling problems arise, the person who doesn't deeply understand how CSS works will struggle to find a solution.
Take a step back and think about it. You write in those technologies but you think in CSS. You have to. Those technologies offer no value when it comes to solving fundamental styling problems. How do you even decide when one styling solution is better than another. You have to understand the philosophy of the web, the philosophy of HTML, the philosophy of CSS. It's not all technical. There's a way of doing things and a reason why.
Think about it this way. Suppose a developer joins your team who doesn't understand CSS but is expert at Elm, you know, better than Richard Feldman. You give them an Elm view that's styled using elm-css
and has the image in a container problem. Can thinking in types help them find a good solution to the problem? The line-height: 0
solution we wrote in elm-css
above passes the type checker. elm-css
didn't lead us to a better solution because it's type-safe. No, it's thinking about layout modes that gets to the root of the problem and eventually leads to the better solution. The only way to get there was to think in CSS, not in Elm. It's fundamentally a CSS problem.
As much as we would like to dismiss CSS we still have to learn it. But what about elm-ui
?
elm-ui
elm-ui
changes your mental model because you never have to think in terms of HTML and CSS when using it. That's novel. That's impressive. None of the other technologies I mentioned come close to doing that. Sign me up, I'm sold. However, it doesn't fit with the web. It goes against the web's grain.
The two major issues I have with elm-ui
has to do with rigidity and divitis. It comes back to understanding the philosophy of the domain you're working within and what's trying to be achieved by that community as a whole. For e.g. elm-ui
would probably be great for native desktop applications. But, on the web, fluidity and accessibility are too highly prized.
Given that context, can you see how one might judge this button as a horrible way to implement a button for the web? Please try to understand what I'm saying. It's not a technological issue, it's a philosophical one. That button is inflexible and inaccessible.
So why do I prefer not to use elm-css
et al.?
Simple. They give you more abstraction for very little gain. I took the time to learn CSS a long time ago. I'm no expert but I get by with BEM and a smattering of utility classes.
Here's the thing though. I can pick up any of those other technologies in an instant if a project requires it because I know how to think in CSS. Those other technologies just help you write CSS in a different way. Yes, I know the problems they solve are real problems, but, especially in recent years, there are very good alternative pure CSS solutions.
CSS isn't going anywhere. If you plan to be building websites and web applications for a long while then taking the time to deeply understand CSS is a great investment.
Conclusion
elm-css
, CSS Modules, CSS-in-JS, Tailwind, etc. are wonderful technologies. Unfortunately, they don't absolve you of the need to learn and deeply understand CSS. If you're already skillful with CSS then by all means go ahead and use those technologies because they can be convenient at times, especially Tailwind, which makes it easy to prototype UIs. But, if you struggle to use CSS and you secretly dislike it, just know that you may be writing your styles colocated with your code and avoiding specificity but CSS will still be on your mind. Except that your mental model of CSS would be so weak that every fundamental styling problem you encounter would just make you hate CSS even more. Don't get trapped in that spiral. Instead, learn CSS.
Subscribe to my newsletter
If you're interested in improving your skills with Elm then I invite you to subscribe to my newsletter, Elm with Dwayne. To learn more about it, please read this announcement.
Top comments (2)
I agree!
I can see the value these tools provide for those developers who are new to front-end (but not new to software development) because the mental models behind CSS are quite different from what they're used to.
But ultimately, if you want to seriously work as a front-end developer, you have to learn the basic languages.
Elm-css, Tailwind, etc. are abstractions, but all non-trivial abstractions are leaky.
I had started using elm-ui years ago and never looked back. When a feature is missing, I just slap some
Html.Attributes.style
on anElement
but that's pretty much it.