9 ms·
In Defense of Utility-First CSS (2018)
- 51Cards 7y agoThis was how I adopted CSS from day one. My standard home-evolved CSS library has a large set of very simple classes that standardize the options I have to choose from. As the article mentions one of the fallouts from this is consistancy of design across multiple pages. I'd like to say I had some grand epiphany about how CSS should be used but this just seemed like the most obvious way to use it.
- saagarjha 7y agoI’m not familiar with Utility-First CSS: is it where you add class=“color-blue underline font-big” to your links instead of class=“header-link” and add the CSS to do the styling to the class? If so, I’m not sure I can shake the “yuckiness” I feel by choosing to not annotate an element with its semantic meaning. It seems awfully likely that you’d get the same issues you’d see with styling divs instead of using actual HTML elements…
- donatj 7y agoThey makes a very poor case IMHO, and come off as just preaching to the choir. > Make no mistake: just because style composition is performed in the HTML document doesn’t mean it’s done in HTML. That is 100% what that means. Sure, you could make .font-italic do anything, yet if it turns everything bold or anything other than italic it’s a horrible sin. Make no mistake, you are editing your HTML to adjust styling. It’s “done in html”. Truly semantic CSS has been dead for around a decade, killed by the likes of Bootstrap. God I miss it. I miss the goal of just cleanly naming things what they are, not how they look. Taking pride in the quality of the HTML, versus today’s rush to get an MVP out the door as quick as possible.
- klum 7y ago> God I miss it. I miss the goal of just cleanly naming things what they are, not how they look. I think utility-first CSS has its benefits as well as it's drawbacks, but just regarding the statement above: wouldn't you say that when naming things for the purpose of targeting them with styling, what they look like is indeed what they are? As in, referring to, for example, ".comment" and ".testimonial" in your CSS, when those classes have been added purely for the purpose of styling the elements as what is commonly called a media component, could be considered less semantic than just naming them according to how they look -- as that's the reason for naming them in this case? (I think these are two different ways of looking at the issue, none of which is clearly the right or wrong one.)
- lfischer 7y agoI might be wrong, but I have the definite impression that semantic CSS was invented mainly by people working in publishing, so typical semantic class names map to content types you would create in a CMS. The developer mainly controls the CSS and users generate most of the HTML. Developers who work on app-like experience might be less interested in this style of semantic CSS because users are extremely constrained in how they can influence the layout anyway.
- meerita 7y ago> I think utility-first CSS has its benefits as well as it's drawbacks What drawbacks?
- welly 7y agoYou add a class called font-bold which adds a bold style to the element. Your client decides the element should be italic not bold. You then have to go back and change all your bold elements to use font-italic.
- meerita 7y agoThat's not a drawback at all. First, you would replace those font-bold with font-italic (assuming you name the utilities like that) and problem solved. You don't need to change .font-bold and add font-style: italic; in the font-bold class. That's they convinience of utilities: they aren't mutable.
- welly 7y agoWhat if you have 500 pages which need to have font-bold replacing with font-italic? Or more? 1000 pages? Sure, you can probably write a script but if you name your elements semantically, you potentially only have to change it once.
- thinkloop 7y ago> wouldn't you say that when naming things for the purpose of targeting them with styling, what they look like is indeed what they are? What do you mean? A "comment" is likely to stay a "comment" forever, whereas its bold'ness or italic'ness can/will likely change relatively often.
- gonational 7y agoI 100% agree with your opinion on “utility-first CSS”. I wouldn’t declare CSS dead though. Some folks, like myself, continue to do things the right (IMHO) way. I sometimes even consider creating a new site like CSS Zen Garden (haven’t bothered to check whether such already exists)... imagine the creations people could make nowadays. I also use Bootstrap, and I love it, but I don’t use it to design my apps / websites; I use it for its utilities (responsive utilities, form styles, etc.). I realize there are smaller frameworks for this purpose, and I sometimes use them also. I still design most of the internal layout from scratch (e.g., I don’t use “cards” and other shortcuts to bypass meaningful design, etc.).
- metaxy2 7y agoMaybe I just have an unusual learning style, or haven't gotten the right resources, but I've found traditional, semantic CSS to have a brutal learning curve. When you're trying to build complex apps, you're constantly rearranging your taxonomy of classes to break down the page into an appropriate logical hierarchy. I appreciate that in principle this is a good thing to do, and once you get good at it there is less rewriting, but when you're trying to learn all of the other aspects of this craft at the same time, it can be a draining experience. And I mean this on the scale of years, not just the 6-12 month "just getting the basics" stage of learning to be a dev. If we still had the position of "front end developer" in the old sense of writing HTML, CSS, and maybe some light JS, that's someone who could dedicate their resources to mastering semantic CSS. Sometimes I wish there was still a job like that, but for whatever historical reasons, at most companies what we have is a combined role called "front end developer" that involves fairly heavy duty development with client side frameworks like React, but also all of the HTML and CSS stuff. And asking these folks to get good at the semantic side of CSS at the same time as learning all the rest, is asking a lot. Maybe worth it, but it's no joke.
- gonational 7y agoI should have mentioned that I don’t apply the semantic concepts completely and dogmatically. They just act as a guiding philosophy. I definitely have to agree that the complexity of “front end development”, as a role, has increased drastically, meaning there is much less time to dedicate to learning and applying these types of traditionalist techniques, compared to pragmatically and quickly implementing things with heavy framework usage. I also think there is a bit of a vicious circle with that mindset. When people use frameworks they tend to build more complicated things than they might without those frameworks, which makes plain ol’ CSS/ JS look like an untenable solution. When I think of building an app with plain CSS and JS with only jQuery, I think of it as a helpful constraint that will lead to simpler code and simpler functionality, not to mention what could be megabytes less of tools and frameworks that users will need to load.
- Theodores 7y agoExactly. The other thing is that the tools you use define how you think. Nobody is using HTML properly, it is as if the only elements are div and span. Why can't we have people using the full vocabulary? If you only think in terms of div and span with a gigantic mess of CSS making it look like a web page then you are never going to write good content. Content means articles with sections with asides, headers, details and summaries and regular HTML goodness such as lists. If you can write your content in a sensibly structured way then you can style the elements consistently with a minimal amount of classes. Also to add to the mix is CSS variables. People that aren't using them in their CSS for making pages responsive are just not using CSS sensibly and are doomed to use a hacky scheme to manage untold bloat-CSS.
- ravenstine 7y agoTo each their own, but I personally learned to hate this approach. In my experience, it leads to a CSS spaghetti full of overrides and `!important` just to get all the utility classes to play nicely across a site. And of course the markup becomes less readable. I prefer to just write classes for specific components with some modifier classes to toggle variations. People resist this because they've been taught to avoid repetition, but I've found that repetition is a good trade-off for things just making more sense because it's really not that hard to go in and change the same pattern repeated among CSS selectors if there's a site-wide design change. If you really hate repetition, you can still use CSS variables and SCSS mixins. But the end product of the CSS definitions should be styles that are easy to use, don't tangle with each other, and make it clear what an element represents. What I describe becomes even more practical if you separate your CSS concerns into concepts like "layout" and "component" or "design". That way the styles that handle your page layout and responsiveness don't get tangled with the styles that handle the appearance of elements. Here's a blog post I wrote that goes into more detail about my approach to CSS: https://tenbit.co/blog/my-approach-to-writing-maintainable-css/ https://tenbit.co/blog/my-approach-to-writing-maintainable-c... (I only recently discovered that the page heading is kinda broken on mobile. Sorry.)
- deltron3030 7y ago>To each their own, but I personally learned to hate this approach. In my experience, it leads to a CSS spaghetti full of overrides and `!important` just to get all the utility classes to play nicely across a site. And of course the markup becomes less readable. The entire point of utility CSS frameworks is that you barely mess with the css, the css is already baked in, you just pick from it within html. >What I describe becomes even more practical if you separate your CSS concerns into concepts like "layout" and "component" or "design". That way the styles that handle your page layout and responsiveness don't get tangled with the styles that handle the appearance of elements. Frameworks like tachyons or tailwind have basically inverted the specificity/explicity/reach pyramid that is known from soft CSS frameworks like ITCSS. Their css file is quite similar.
- harimau777 7y ago
- swlkr 7y agoI came across tachyons a few years ago and it made CSS finally click with me. The main advantage for me was that I didn’t have to switch back and forth between two files to style something. Utility-first CSS feels more like using a REPL than a compile-debug-reload workflow.
- shubhamjain 7y agoIf you're not sold on Utility-first CSS, your gut reaction would be, how's it different from inline styles? The author does a great job at listing out the differences, but I think that kinda misses the point. If you've to accept Utility-first CSS, you should unlearn the fact that there is something inherently wrong with inline-styles. Often, they are much cleaner solutions than creating an entirely different class that won't be used more than once. Utility-First CSS only makes it easier to use inline styles (by reducing verbosity) and provides a standard set of classes so you don't end up creating 100 variants of margins. I have found it hard to convince folks this is indeed a good approach because inline styles have acquired a reputation of being a disgusting hack. A while ago, my outlook was not very different. But then, I started seeing how often I was writing the same styling rules again and again. Our 1MB stylesheet was nothing more than a repetition of a few basic rules. Utility-first CSS builds on that idea and to me, it feels natural.
- al2o3cr 7y agoUtility-First CSS only makes it easier to use inline styles (by reducing verbosity) and provides a standard set of classes so you don't end up creating 100 variants of margins. If your "standard set" has 3 varieties each for top/bottom/left/right margin, you've already got 81 combinations of margins available at each element.
- dceddia 7y agoI was just today watching some of the videos Adam Wathan put together for Tailwind [0] and this one on "Optimizing for Production"[1] is especially relevant to your comment. You can introduce a build step (in his example, PurgeCSS) to filter down to only the styles that you actually use. So during development you'd have thousands of available classes, but in practice you only use a handful, and that final CSS file can be significantly reduced. I'm not (yet?) fully on board the utility-first bandwagon and I have yet to give it a solid try, but I was excited by the idea that it should be pretty optimizable. [0] https://tailwindcss.com/course/ https://tailwindcss.com/course/ [1] https://tailwindcss.com/course/optimizing-for-production https://tailwindcss.com/course/optimizing-for-production
- mikl 7y agoUtility-classes like `font-16 font-bold font-purple` are essentially just shorthand for writing inline CSS. You are defining the styling in HTML, with a utility CSS file as go-between, true, but if you use Tachyons or Tailwind the way they’re supposed to be used, the way to change the look of an element is to go edit the HTML. For component libraries, that makes a lot of sense. You re-use snippets of HTML that is styled a certain way. No need to set up another re-use layer using CSS. I expect the next level of utility-first CSS will do away with the CSS file altogether, and start baking the resulting styles directly into the HTML, so <div tx(['font-bold', 'font-16', 'font-purple'])> would be transformed by whatever you use for HTML rendering into <div style="font-weight: bold;font-size: 16px;color: purple">. That would complete the circle and cut away a lot of complexity.
- Moru 7y agoThat already exists in email newsletter creation tools so I guess you were right there :)
- lfischer 7y agoAlso in the React community, there are already ultra-generic component collections like https://rebassjs.org/ https://rebassjs.org/.
- lfischer 7y agoWhat you describe sounds like the way some use CSS-in-JS frameworks as emotion or Styled Components.
- mikl 7y agoYeah, they’re currently just one step away, generating class names on the fly and attaching those classes to elements.
- ratww 7y ago> I expect the next level of utility-first CSS will do away with the CSS file altogether, and start baking the resulting styles directly into the HTML It's not exactly the same thing, but Atomizer [0] generates a CSS file from HTML, by translating class names into functional CSS rules. The problem with inline CSS is that it has some limitations, notably lack of support for selectors like :hover, :focus, etc, and pseudo-classes like :before and :after. [0] https://github.com/acss-io/atomizer https://github.com/acss-io/atomizer / https://acss.io/guides/atomizer.html https://acss.io/guides/atomizer.html
- lfischer 7y agoLately I’ve been intrigued by https://every-layout.dev/ https://every-layout.dev/ and so-called ‘intrinsic’ CSS approaches. It’s like having utilities for whole layout chunks, instead of single properties. I would describe it as trying to extract whole atomic layouts like ‘sidebar’, with CSS rules that make the objects behave ‘well’ no-matter what the surroundings are. In comparison, semantic CSS can be too tied to single page elements (main__header) while utility-first in a sense is not ambitious enough (because it limits atomicity to single properties).
- aarondf 7y agoIMO, this is one of the best articles on utility CSS: https://adamwathan.me/css-utility-classes-and-separation-of-concerns/ https://adamwathan.me/css-utility-classes-and-separation-of-...
- jpochtar 7y agoJust use inline styles and simplify your life. If you’re using React/Angular/Vue/etc, your markup is styling; so why are you separating styling (html) from other styling (css)??
- meerita 7y agoI've wrote an extensive piece (p1: http://minid.net/2019/04/07/the-css-utilitarian-methodology/ http://minid.net/2019/04/07/the-css-utilitarian-methodology/) about this too called "In Defense of Functional CSS" (p2: http://minid.net/2019/08/12/in-defense-of-functional-css/ http://minid.net/2019/08/12/in-defense-of-functional-css/) I give all the arguments I think are valuable for this discussion.
- leephillips 7y agoI'd just like to mention that Jukka "Yucca" Korpela had some interesting observations, relevant to the discussion here, about CSS back in 1997. He might have been the first person to write about these issues: http://jkorpela.fi/styles/harmful.html#pos http://jkorpela.fi/styles/harmful.html#pos
- erikpukinskis 7y agoIf you are building a totally generic CSS library to use on a bunch of independent sites, then sure... utility first. But the main reason I think semantic CSS is important has nothing to do with anything technical. CSS is not just a technical contract with the browser, it is the place where your organization’s design language is made manifest. If your pages match what’s in your designers’ mockups, that’s good. But if your CSS matches what’s in your designers’ heads that’s way, way better. What that means is that “configurability” and “flexibility” and “composition” are anti-patterns. Being able to do anything is bad. The goal is the opposite: almost everything should be impossible to do. The goal is that you can only do things that make sense within the design system. That means making something that’s technically quite useless, but just barely can do the things your designers want to do. The same applies to component names and arguments. That’s the other place where the design system contract becomes real. So, if you’re a freelancer than yes, go utility-first. But if you work on one app day in and day out then you’re playing a different game with different goals.
- btbuildem 7y agoI've switched to this approach a while ago, and haven't looked back since. It makes everything so much simpler, hands down. I have utility classes, grouped semantically into separate css files. I've built up a library of components that I use across my projects (so eg. if I need to change a button, I just change it on the component server). Encapsulating style, function and semantics in separate layers has really increased my efficiency as a developer. Interesting challenges arise when collaborating with UX / UI designers. Quite a few of their tools (XD, Figma, etc) can output ready-made CSS blobs for front-end dev copypasta, but it's the old-school semantic CSS. What I have found reassuring though is that in general, designers eventually come up with UI kits, and there are certain stylistic consistencies inherent to those. The kits usually translate very well to a functional CSS implementation because of that.
- irrational 7y agoI skimmed the article, but I don't think it covered one of the reasons why I prefer utility-first CSS. When all the CSS is in a separate CSS file I can look at a page's HTML and have no idea what it will actually look like. But with utility-first CSS, just by looking at the classes on the HTML elements I can make a pretty good guess at what the HTML will look like when rendered. I'm sure a lot of people won't see this as useful, but I really really appreciate it.
- mynegation 7y agoI disagree with the author but I appreciated very thorough explanation of various CSS structuring approaches - it was very helpful for me. Disclaimer: my knowledge of CSS is 2 out of 10 at best, but my personal preference is the semantic way: use header, footer, article tags and use either div’s with semantically name classes (like ‘card’) or React components or web components. If CSS is more complicated as a result of that - I don’t care, there are ways to deal with that (extend, variables, preprocesssors etc). HTML is not the place to be concerned whether your text is green or card has a ribbon.
- goofballlogic 7y agoI think this is an issue which needs to be addressed a bit more holisticly. The fact is that HTML, JavaScript and CSS (to name three) all use an element's _className_ for slightly different purposes. The author seems to consider BEM an example of a _semantic_ CSS scheme, but really the semantic needs to be clear across all the consumers of the API being implicitly established by the markup. Ultimately HTML is the original source of a web page, with CSS and JavaScript often augmenting this. For that reason, I think it makes sense to opt for the HTML spec's definition of _className_ semantics when there is a clash. The spec effectively balances the importance of both CSS and JavaScript (or other user agent) uses, but cites an example useful to both: https://www.w3.org/TR/1999/REC-html401-19991224/struct/global.html#adef-class https://www.w3.org/TR/1999/REC-html401-19991224/struct/globa...
- luord 7y agoOne vying for this approach can wax poetic as much as one wants, but for me, seeing a difference between 'style="color: purple"' and 'class="color-purple"' (with '.color-purple { color: purple }' in the css file) is very much the same as seeing the emperor's new clothes. It looks and feels like indirection and I am aware of duck typing. The "it limits options" defense is not really here nor there, since ultimately you could just rewrite all css rules into classes. Much like the style you can add is infinite, the classes you can add are infinite.
- jspash 7y agoI think what people are really gravitating to with "utility CSS" when they say they finally "get it" or it say "feels like REPL" is the fact that you can get instant feedback in the browser using the inspector. It's a bit like when you first "get" TDD. Which in my experience happens soon after you've got your spec listeners and live reload hooked up properly and manage to get the spec runner to react in less than 300ms. A whole new world of possibilities open up. I'm not taking sides, but just want to point out that this quick feedback loop _might_ be clouding people's judgement as to the benefits and drawbacks of using a coding style such as this.