[HN Gopher] The Evolution of Scalable CSS
       ___________________________________________________________________
        
       The Evolution of Scalable CSS
        
       Author : remrem
       Score  : 90 points
       Date   : 2022-11-12 11:57 UTC (11 hours ago)
        
 (HTM) web link (frontendmastery.com)
 (TXT) w3m dump (frontendmastery.com)
        
       | krono wrote:
       | There 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
        
       | smrtinsert wrote:
       | Isn'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.
        
       | azangru wrote:
       | > 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.
        
         | dxchester wrote:
         | We 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-...
        
           | jacobr wrote:
           | Great post. It's similar to CUBE, https://cube.fyi and the
           | creator of CUBE even wrote about using "Tailwind as the U in
           | CUBE"
        
         | Gualdrapo wrote:
         | > 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 wrote:
           | > 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?
        
         | alwillis wrote:
         | There's also no mention of CSS Cascade Layers [1].
         | 
         | [1]: https://css-tricks.com/css-cascade-layers/
        
           | tln wrote:
           | The article does mention them... I'm just finding out about
           | this, it could be very useful!
           | 
           | https://frontendmastery.com/posts/the-evolution-of-
           | scalable-....
        
         | dtagames wrote:
         | Indeed. It's web components and the shadow DOM that fix all of
         | this.
        
       | aphexairlines wrote:
       | There'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 wrote:
         | This 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/
         | 
         | Live example:
         | https://lit.dev/playground/#gist=f0bdd3b5db5e4a404297e695305...
        
           | jacobr wrote:
           | SSR was mentioned though.
        
       | c-smile wrote:
       | FYI, 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 wrote:
         | This 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 wrote:
           | Yes, 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 wrote:
             | Actually, we add the stylesheet objects directly to the
             | shadow root, so they're shared and there's no <style> tags
             | (on supported browsers).
        
       | abathur wrote:
       | > 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/
        
         | TimTheTinker wrote:
         | Jesse James Garrett (the early web luminary who coined the term
         | "ajax") was already talking about the dual purposes of the web
         | in the year 2000. He called them "Web as software interface"
         | and "Web as hypertext system".
         | 
         | In _The Elements of User Experience_ (2000) he writes:  "The
         | Web was originally conceived as a hypertextual information
         | space; but the development of increasingly sophisticated front-
         | and back-end technologies has fostered its use as a remote
         | software interface." [0]
         | 
         | [0] http://www.jjg.net/elements/pdf/elements.pdf
        
         | wwweston wrote:
         | > 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 wrote:
           | It'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 wrote:
       | Good 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 wrote:
         | It's solved natively without build tools too: native CSS module
         | scripts for importing and shadow DOM for applying the styles
         | with scoping.
        
       | andix wrote:
       | Tailwind 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.
        
       | swyx wrote:
       | this 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)
        
       | zagrebian wrote:
       | How do I disable dark mode on that website? I can't read text
       | very well in dark mode.
        
         | vulcan01 wrote:
         | I don't think there's that option, but the page does work well
         | with reader mode.
        
         | [deleted]
        
       | ozten wrote:
       | Is there a resource designed for both designers and developers to
       | aid adopting design tokens?
        
         | krono wrote:
         | This W3C Design Tokens working group might be of interest to
         | you: https://github.com/design-tokens
         | 
         | Ever so slightly more details in my own top-level comment
         | https://news.ycombinator.com/item?id=33575191
        
       | Eduard wrote:
       | I never understood this with BEM:                 .nav {
       | &__link {         }       }
       | 
       | Why not this?:                 .nav {         a {         }
       | }
        
         | achairapart wrote:
         | To 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.
        
         | jaredcwhite wrote:
         | Exactly. 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.)
        
       | matsemann wrote:
       | My 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 wrote:
         | For 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 wrote:
           | If 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 wrote:
             | Fwiw, 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 wrote:
             | It 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
             | 
             | 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
        
               | matsemann wrote:
               | Thanks for some explanation. And yeah, I'm probably not
               | up to date on CSS-in-JS, just remember it being really
               | clunky to use before I ended up in an elm-shop a few
               | years back. I'd say that emotion does look similar to
               | what I've described, and nearly there. And I don't think
               | there is anything doable in elm that's not doable in
               | TS/React (it's rather the opposite, elm is the restricted
               | one, mainly on purpose). My point about ergonomics was
               | mostly that it's just elm all the way. No strings or
               | objects or new concepts. The CSS you write in elm is
               | mostly indistinguishable from the other elm view code
               | (html etc) you write, it's all the same syntax etc. While
               | for emotion and others, there is a clear divide in what's
               | React and what's styling, and difference in how you do
               | stuff.
        
       | jacobr wrote:
       | > 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.
        
       | jaredcwhite wrote:
       | Reading 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 wrote:
         | The 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.
        
         | dogcomplex wrote:
         | Tailwind's just a shorthand style for writing [a particular
         | snapshotted older version of] CSS based on the theory that
         | saving on keystrokes is worth more than understandable naming.
         | It then leverages this brevity to let people over-define styles
         | directly in the HTML, which would otherwise take paragraphs of
         | normal CSS and therefore be unwieldy to do (so you'd just alias
         | it into a new CSS property in a separate file). That's about
         | it.
         | 
         | While brevity is a nice feature, and we should always strive to
         | make the dev experience as elegant and simple as possible,
         | methinks Tailwind is just asking to become yet another dead-end
         | standard which I very much hope has a standardized compiler
         | back to vanilla CSS. (Does it not?)
        
       ___________________________________________________________________
       (page generated 2022-11-12 23:01 UTC)