Discuss: Stealing CSS


#1

I see a lot of buzz around reducing blocking caused by CSS. I think this is an exciting area to think about. Would it be possible to do something similar to incremental rendering but for CSS? There are automated tools to extract your “above the fold” CSS but they are still in their infancy. I’m wondering if we could progressively inject <style></style> into the page? I’ve even seen that it is possible to cache inline styles using web workers. This could be a killer feature for steal, and actually an area steal could innovate on currently.

  1. https://www.filamentgroup.com/lab/inlining-cache.html
  2. https://csswizardry.com/2018/11/css-and-network-performance/
  3. https://github.com/addyosmani/critical

Perhaps this would interest the more designer types in the build tool as well.

Does the current component and bundling system already optimize CSS in such a way? I don’t feel I’ve seen much literature about it if so, and that certainly would be a plus.


#2

There’s an issue about this in done-ssr: https://github.com/donejs/done-ssr/issues/392

We were just talking about putting on the next community survey actually.


#3

I’m thinking about how keep things modular without duplicating style rules and/or polluting the HTML/stache markup with a bunch of generic class name noise…

For example, a Tachyon banner looks like this:

<article class="mw7 center ph3 ph5-ns tc br2 pv5 bg-washed-green dark-green mb5">
  <h1 class="fw6 f3 f2-ns lh-title mt0 mb3">
    This is a tagline. For x.
  </h1>
 <!--- snip --->
</article>

The excessive class names are ugly and distracting (in my opinion) and so perhaps a solution could be:

<can-component tag="basic-banner">
  <style type="text/less">
    display: block;
  </style>

  <view>
    <article class="{{this.class.article}}">
      <h1 class="{{this.class.h1}}">
        This is a tagline. For x.
      </h1>
     <!--- snip --->
    </article>
  </view>

  <script type="view-model">
    export default {
      class: {
        article: 'mw7 center ph3 ph5-ns tc br2 pv5 bg-washed-green dark-green mb5',
        h1: 'fw6 f3 f2-ns lh-title mt0 mb3',
      }
    }
  </script>
</can-component>

A mixin/extend approach would allow me to accomplish that, but IIRC a preprocessor will inline (in the resulting .css file) duplicate style rules for every class where the mixin is used (bloating the CSS file).

Perhaps to have the best of both worlds, CSS classes would need to be stored in JS variables? I’m not sure what implications this would have on caching etc., but it’s something React projects seem to use.

How can we keep component styles self-contained, but also eliminate the mass duplication of style rules, while still being able to make project-wide changes to generic things like padding and fonts?

  1. Add many generic class names to markup.
    pro. No duplication of style rules.
    con. Loads all style rules up front.
    con. HTML/stache markup becomes noisy.
  2. Use Less variables and mixins in component style classes.
    con. Lots of style rule duplication.
    pro. Doesn’t load all style rules up front.
    pro. HTML/stache markup remains clean.
  3. Store styles in JavaScript variables that can be shared between components.
    pro. No duplication of style rules.
    pro. Doesn’t load all style rules up front.
    pro. HTML/stache markup remains clean.

I’m imagining a new kind of language, essentially a variant of Less that gets transpiled to JavaScript:

<can-component tag="basic-banner">
  <style type="text/impress">
    article {
      import('mw7 center ph3 ph5-ns tc br2 pv5 bg-washed-green dark-green mb5');
      // if not explicitly called here, imported
      // mixins get invoked with default values
    }

    h1 {
      import('fw6 f3 f2-ns lh-title mt0 mb3 some-parametric-mixin');
      some-parametric-mixin(4px);
    }
  </style>

  <view>
    <article>
      <h1>
        This is a tagline. For x.
      </h1>
     <!--- snip --->
    </article>
  </view>
</can-component>

This might allow things like HTTP2 push to be able to just send the 'mw7 center ph3 ph5-ns tc br2 pv5 bg-washed-green dark-green mb5' and 'fw6 f3 f2-ns lh-title mt0 mb3 my-parametric-mixin' class style rules on demand and avoid sending down all the unused bytes and this should be more reliable than using jsdom with a build-time tool that removes unused css like uncss.


#4

This looks like something that might be able to be integrated with SSR without any major modifications:

I use a very limited set of Less features anyways, when I do use Less, so not having Less would be fine for me. The only major drawback I’d see is that you wouldn’t be able to just drop in a CSS or Less framework and conditionally load only the styles the current page uses like I was pondering before.

EDIT:

There may be some issues around async with Aphrodite:

EDIT:

Here is a library to convert CSS to JS object:

EDIT:

Similar to Aphrodite: