7 ms·
The Evolution of Scalable CSS
- azangru 4y ago> The Evolution of Scalable CSS The evolution of practices described in this article is followed up to about ten yeas ago... and then stops, followed by Tailwind. Where is consideration of web components with shadow DOM, which solve the CSS encapsulation problem, the naming problem, and the dead code problem? Where is treatment of CSS variables that pierce the shadow DOM and allow global theming of such components? They are the next step in the evolution of scalable CSS, and yet they are noticeably absent from the discussion.
- Gualdrapo 4y ago> Where is treatment of CSS variables that pierce the shadow DOM and allow global theming of such components? I feel like, at least with that one, was left behind because there's some work left to do in that regard. For the redesign of my portfolio, miler.codeberg.page, I used icons I did for the previous one (and did some new ones, but all are a bunch of <symbol>s in a single file) but instead of "injecting" the SVG code in the HTML I tried to use them from CSS as pseudoelements (as a 'content' fragment identifier) and style them (stroke color). The state of things right now, as I learned, is that it's impossible to do that - neither with some obscure parameter within the SVG fragment identifiers. I had to do some crop filter trickery to "change" their stroke color.
- azangru 4y ago> I tried to use them from CSS as pseudoelements (as a 'content' fragment identifier) and style them (stroke color). Isn't this just the general problem of loading an svg as an image via a link as opposed to injecting it into the DOM as inline svg? How would any of the existing CSS approaches help (or how would web components hider) this one?
- dtagames 4y agoIndeed. It's web components and the shadow DOM that fix all of this.
- dxchester 4y agoWe wrote about our journey[0] to sanity after Tailwind: The answer is to do it all in strategic moderation: Use a subset of tailwind just for spacing and layout and revel in simple things being simple. Use modular CSS for UI patterns and revel in the readability of your HTML and visual consistency of your UI. And then use custom scoped CSS where required, and revel in interesting things being only as hard as need be, without ruining everything else along the way. [0]: https://frameable.com/company/tech/how-we-found-sanity-in-a-small-subset-of-tailwind-css https://frameable.com/company/tech/how-we-found-sanity-in-a-...
- jacobr 4y agoGreat post. It's similar to CUBE, https://cube.fyi https://cube.fyi and the creator of CUBE even wrote about using "Tailwind as the U in CUBE"
- alwillis 4y agoThere’s also no mention of CSS Cascade Layers [1]. [1]: https://css-tricks.com/css-cascade-layers/ https://css-tricks.com/css-cascade-layers/
- tln 4y agoThe article does mention them... I'm just finding out about this, it could be very useful! https://frontendmastery.com/posts/the-evolution-of-scalable-css/#:~:text=It%E2%80%99s%20worth%20noting%20that%20CSS%20cascade%20layers%20is%20an%20up%2Dand%2Dcoming%20feature%20that%20can%20help%20address%20this%20problem%20natively https://frontendmastery.com/posts/the-evolution-of-scalable-....
- aphexairlines 4y agoThere's still no good way of publishing an npm package with multiple components, stylesheets per component, and transitive consumers using only the stylesheets for the components they reference while rendering fully server side. CSS is still not scalable.
- spankalee 4y agoThis is what native CSS module scripts solve. You can import CSS directly into JavaScript modules: import styles from './styles.css' assert {type: 'css'}; https://web.dev/css-module-scripts/ https://web.dev/css-module-scripts/ Live example: https://lit.dev/playground/#gist=f0bdd3b5db5e4a404297e695305f92d9 https://lit.dev/playground/#gist=f0bdd3b5db5e4a404297e695305...
- jacobr 4y agoSSR was mentioned though.
- matsemann 4y agoMy favorite implementation of CSS systems has to be elm-css. Your CSS is just normal elm code included in your view code. E.g. everything is an expression, so can import reusable CSS, compose it from different blocks, have functions calculating the CSS runtime etc. Then runtime the rules are compiled to classes and applied to the elements. One nice thing about this is that instead of using classes, you can instead statically import the definition and apply it to your element, making it even fail compilation time if you remove some global styling some component still relies on. And the CSS itself is typed. So the project will not compile if you write invalid css.
- jamescostian 4y agoFor anyone else trying to understand how this fits in, it's either the "Inline Styles" section or the "CSS in JS" section, as long as you use typescript and follow the same rules mentioned here
- matsemann 4y agoIf I were to explain it in terms of react, it would be to use <Component style={{mystyle: someValue}} /> everywhere. Except that you also can define nested stuff, media queries, hover/active states, pseudo-elements etc. So yeah, syntactically a bit more like CSS in JS / JSS, but much more ergonomic, and much more easily composable.
- MrJohz 4y agoFwiw, most CSS-in-JS libraries don't use `style` directly, and so also allow the same features. One thing I've seen often is to use a `css` pseudo-prop so that it looks a bit like using `style` (but you've still got access to the full force of normal CSS rules). My favourite variation of this so far has been typestyle, which I believe works along essentially the same principles as in Elm.
- jamescostian 4y agoIt sounds like you have experience with the string-heavy CSS in JS. Here's some examples showing how this can be achieved using `csstype.Properties` objects: https://emotion.sh/docs/typescript https://emotion.sh/docs/typescript I'm sure you can imagine how easy it is to compose functions that accept and return `csstype.Properties` objects, and then at the end, you call `styled` with it to make a styled component. You can even pass styled a function, which takes in runtime-adjustable props, and of course, that function can itself use other functions, passing around those same or some derived runtime-adjustable props. That said, I have no idea what you mean when you talk about ergonomics being better, can you elaborate? I re-read your initial comment but there wasn't anything in it not achievable in TS using the kinds of things mentioned in the "CSS in JS" section, perhaps there's something else I'm just not aware of? I do not know elm, let alone have experience writing it in non-trivial production codebases, so a concrete example would be great
- zagrebian 4y agoHow do I disable dark mode on that website? I can’t read text very well in dark mode.
- abathur 4y ago> Let’s take a break from all these principles and architectures, and remember that CSS is ultimately about implementing visual designs. I enjoyed the overview (though the web component/shadow Dom bits others noted here would have been nice) but I feel like there's a missing realization lurking at the center of this history: the separation of concerns in the web stack was designed for documents, not layouts or visual designs. Much of the struggling we've seen over the decades is because the separations aren't aligned with how we're using them. It makes sense for documents to have separate stylesheets. It doesn't make sense to fragment the implementation of a layout across several files and complexly-interacting languages. This isn't really a fault of the article. I only just realized this in the past year myself and I've been writing html since the all caps era. I took a first swing at writing about this recently in: https://t-ravis.com/post/doc/what_color_is_your_markup/ https://t-ravis.com/post/doc/what_color_is_your_markup/
- wwweston 4y ago> I feel like there's a missing realization lurking at the center of this history: the separation of concerns in the web stack was designed for documents, not layouts or visual designs. I think that realization had solidly set-in throughout the industry by 2010 or so, and why so much effort over the most recent decade went into things that do lend themselves to an app-like focus such as native flexbox & grid capabilities, shadow dom, and even recent things like :has(). But personally... I think that "apps as documents" paradigm has actually worked out pretty brilliantly, even considering how squirrelly CSS can be. The inspectability of the UI layer is one of the reasons why the browser is so much more than the VM that lived, and HTML/CSS has so much flexibility that many native UI toolkits lack. It's not right for every situation, but for the common case I think there are reasons it's often what people reach for first.
- abathur 4y agoIt's an incredibly flexible toolkit. Not calling it bad! It just isn't cut along the seams we'd cut it along if we were building it fresh. There's tons of evidence in the record-of-innovation that people are iterating around these problems--so I suspect there are plenty of people who have indeed internalized this to some degree. But I also see a lot of continual coverage that indicates this realization hasn't diffused. (I don't want to pretend to have invented the wheel, but for example I see the fights around semantic VS functional tailwind-style css as hinging on this. Functional css makes sense for layouts as it collapses pointless separation; semantic classes make sense for documents which are more likely to evolve or get restyled without new markup.)
- stevebmark 4y agoGood article. I would have liked to see the article sternly advise against all CSS naming schemes like OOCSS. All CSS classes go into the global namespace, the solution is obviously not hand written naming conventions, it’s getting rid of the global namespace itself. OOCSS is like saying “we have to put our entire program in index.js at the top level, how do we name things to avoid conflicts?” CSS is a fully solved problem: CSS modules combined with global utility classes. You probably want sass too, but the important thing is you’re writing CSS, and font have to figure out the DSL, translation, and plugins needed to use CSS features.
- spankalee 4y agoIt's solved natively without build tools too: native CSS module scripts for importing and shadow DOM for applying the styles with scoping.
- c-smile 4y agoFYI, component styles in Sciter can be placed directly in JS module using `CSS.set` string literal (gets compiled at runtime to special style set object). The style set is a collection of styles rules local (rooted at) to the component. :root denotes the component to which styleset is applied. The style set definition is strictly local to the component - rules inside it do not pollute global style table. That is close to <style scoped> to anyone who remember such thing. Here is how styled component.js module looks like: const padding = "12px"; const styleset = CSS.set` :root { color: var(--theme-color); padding:${padding}; background: var(--theme-back); } :root > em { color: gold; }` export class TestComponent extends Element { render() { return <div styleset={styleset}> Hello <em>Embedded</em> Style Set </div>; } } IMHO, that's the best of two worlds - components may have local styles principal for their operation, and to use global styles that define macro properties like themed colors, etc.
- spankalee 4y agoThis is almost exactly how Lit works in browsers. CSS is included with a css`` template string, that contains standard CSS. :host is used to select the host element, as is standard. @customElement('simple-greeting') class SimpleGreeting extends LitElement { static styles = css` :host { display: flex; } p { color: blue; } `; render() { return html`<p>Hello, World!</p>`; } } So you get CSS that loads with components, is scoped, and bundles without plugins. It's pretty great.
- c-smile 4y agoYes, that's close. Only one thing: that static styles construct shall eventually go into a separate <style> DOM element inside shadow root. Probably not a big deal if there are not that many such components.
- spankalee 4y agoActually, we add the stylesheet objects directly to the shadow root, so they're shared and there's no <style> tags (on supported browsers).
- Eduard 4y agoI never understood this with BEM: .nav { &__link { } } Why not this?: .nav { a { } }
- achairapart 4y agoTo avoid CSS inheritance & specificity, the "Cascading" part of CSS is the actual root of all evil. If you think about it, all the modern approaches to CSS (BEM, Atomic CSS, OOCSS) try to avoid it all cost.
- alwillis 4y agoTo avoid CSS inheritance & specificity, the "Cascading" part of CSS is the actual root of all evil. The Cascade is CSS’a superpower. If only someone would come up with a way to write CSS to make the cascade work for you, not against you. Oh wait; that would be Inverted Triangle CSS. [1]: https://www.xfive.co/blog/itcss-scalable-maintainable-css-architecture/ https://www.xfive.co/blog/itcss-scalable-maintainable-css-ar...
- Fire-Dragon-DoL 4y agoI'd like to believe that, but the industry has proven across the board that inheritance sucks. Cascading to me seems essentially inheritance, so I'm disillusioned, it's not a superpower, it's a liability
- jaredcwhite 4y agoExactly. I've never written strict BEM, mainly just take a few cues from it now and then. When writing components and especially now that we have awesome low-specificity selectors like :where or cascade layers (and soon :has !!), it's really better to just target the DOM structure with semantic/custom element names, parent-child relationships, states like aria, etc. and not saddle every single element with some kind of naming convention. (I honestly don't use `class` much at all anymore.)
- ozten 4y agoIs there a resource designed for both designers and developers to aid adopting design tokens?
- krono 4y agoThis W3C Design Tokens working group might be of interest to you: https://github.com/design-tokens https://github.com/design-tokens Ever so slightly more details in my own top-level comment https://news.ycombinator.com/item?id=33575191 https://news.ycombinator.com/item?id=33575191
- krono 4y agoThere is actually a W3C working group working on a standardised design token schema specification and on adoption by design tooling. Several big names such as Adobe are actively involved, so this has some weight to it. https://github.com/design-tokens https://github.com/design-tokens
- deleted 4y ago[deleted]
- andix 4y agoTailwind is the solution to most CSS issues. You can also add so many customizations into their config file. There are just a few things that can’t be done with tailwind natively. With tailwind and react you now only write JSX files. Not separate files/sections for HTML, JavaScript and CSS your mind constantly needs to connect, although they are split up. Huge plus for someone with a goldfish brain like me, that’s getting super confused with more then 5 files open in the editor. And with tailwind 3.2 they finally allow multiple config files, so you can easily have multiple tailwind instances inside one project. For example one config for the website and another one for the admin-panel.
- jacobr 4y ago> Tailwind and CSS in JS libraries that pre-compile to Atomic CSS solve the problems of bloated CSS files full of duplicated rules. > With Atomic CSS, the growth of CSS is tied to the number of unique styles used, not the amount of features developers are shipping. > For example, it’s common to reuse certain properties like flex everywhere. Rather than have these duplicated in stylesheets under different class names, we only pay that cost once. This is true for each property/value combination. This is true in theory and when you stick to the very basic stateless utility classes. Check the CSS of any larger site using Tailwind and search for a CSS rule, you will see things like .opacity-100 { opacity:1 } .hover\:opacity-100:hover { opacity:1 } .group\:focus-within .group-focus-within\:opacity-100 { opacity:1 } and that's not counting media queries, dark mode, etc. In practice, the global CSS file that you load for every single page does grow for every feature you ship, since you use more of Tailwind.
- swyx 4y agothis is a great history of the development of CSS up til Tailwind. I think there us one more subtle benefit to tailwind not mentioned: Using "design system" values - every color and width variable comes with well chosen constraints! (from my take on this https://www.swyx.io/why-tailwind https://www.swyx.io/why-tailwind)
- jaredcwhite 4y agoReading an article about the evolution of CSS and ending up at…Tailwind…really feels like a bait and switch. I don't consider Tailwind at all a "solution" for writing scaleable CSS. It's a non-standard DSL for providing styling commands to a build tool, and the HTML/CSS output overloads class attributes everywhere in an absurd way. The "just use @apply" retort is also a non-starter if you want to write stylesheets that aren't vendor-locked to Tailwind's build tooling. I'm actually working on a large design system that's in the process of stripping Tailwind _out_, because it's in fact not scaleable if you want to provide vanilla component styling APIs via custom properties. And as some others here have mentioned, we're not even talking yet about web components, shadow DOM, shadow parts, etc. Scaleable CSS should adhere to the actual spec of CSS and how its evolving in browsers. Tailwind is a massive, non-standard deviation from the development of CSS.
- alehlopeh 4y agoThe conclusion I took from the article was that CSS simply isn’t scalable. I’ve been hearing about web components for years and nothing seems to have materialized. I’ve never built something where I thought to even use shadow DOM. Tailwind is the only solution that meets the stated aims. If tailwind doesn’t adhere to the dogma for how CSS should work in principle, well that’s a lovely problem to have.
- weo3dev 4y ago"Nothing seems to have materialized..." --> https://nordhealth.design/ https://nordhealth.design/ -- these are all custom components. And here is D. Darnes explaining in part how they get things done: https://web.dev/custom-properties-web-components/ https://web.dev/custom-properties-web-components/ CSS is scalable. You have to actually know CSS in order to accomplish it. I've been here since mid-90s, when CSS first existed. It isn't until the past four or five years that things have really blossomed into (imho) what it should have been from the outset. Unfortunately, since we have had to use filler tools for things like layout (tables, hacked flexbox for grid), CSS itself has taken a beating in perceived usefulness/weildability. I believe because of THAT, fewer and fewer people have decided to actually learn CSS. CSS is a robust language. It is programmable. It is scalable. You just have to learn it, practice it, and approach problem solving from the top down, bottom up, and sometimes sideways. :-)
- smrtinsert 4y agoIsn't this is a solved problem? Look at tools that provide themes. You can't use anything like semantic css or business related naming. It has to be widget based styling and that seems to be the end of it.
- perilunar 4y agoI saw the link to CSS Garden in the second section and was happy to see the site is still up and working. Separation of concerns is such a powerful idea — losing it by tying styles too tightly to markup is a huge step backwards.
- laura-media 4y agoI really dislike Tailwind. As someone who knows how to work with CSS, it feels like a simple vendor-locked version of CSS you throw onto your codebase and pollute your DOM with divs that have 40 classes. From my experience, working on smaller projects and bigger CRMs, single file components with separate template, logic and style areas are the best when it comes to scalable components.