blakeembrey/free-style

How to use multiple rules inside media query?

sladiri opened this issue · 7 comments

Edit: Never mind, I realized that I have to map the nested rules individually. :)

I converted the CSS file from Tachyons to JSON myself and I could not figure out how to use their classes inside media queries.

One example would be these lines: link

Free-style gives me one hash for the whole media-query, as far as I understand. How can I use the class aspect-ratio-ns?

Normally you assign this class to an element: class="aspect-ratio-ns aspect-ratio--16x9", is this possible?

Ok, so a couple of things. To start with, I definitely recommend https://github.com/postcss/postcss-js as a way to convert CSS to CSS-in-JS - I've used it a few times and will build a little tool online for this in the future.

The main question though, it really depends on how you registered the CSS. Using createStyle gives you hashes for the style itself, and you can nest rules inside that. It's pretty un-CSS like because you'd duplicate the rule used in multiple places. If you're using registerCss, there's not any publish hash of the content available - it's just all treated and register like regular CSS. How did you register it?

This is where I insert the framework CSS, it works nicely, apart from small limitations of cssparser: styles.js

Here is a consuming component: AppShell

Thanks for the hint about postcss-js, I have not looked at postcss. I used cssparser. I tried postcss-js now, but it seems to have problems, it would not finish parsing the framework's CSS file:

const { readFile } = require("fs");
const { parse, objectify } = require("postcss-js");

readFile(__dirname + "/tachyons.css", "utf-8", (err, css) => {
  if (err) {
    console.error(err);
    return;
  }
  const root = parse(css);
  const cssJs = objectify(root);
  console.log(cssJs);
});

That's pretty cool. This sounds like a great idea, maybe we can publish a module? I'll ask the Tachyons author and see if he's interested in having a tachyons-js object exposed for CSS-in-JS.

A tachyons-js would be nice, I was surprised that there was none around already. :)

@blakeembrey
Not sure if I should continue here :)

Btw, I tried to inject on demand now, using a Proxy object: proxy, component

It would be nicer if you could contruct it automatically instead of inside the view though:

const AppShell = (props, context) => {
  const css = getCssProxy(context); // Could this be done "outside" automatically?
  return <div className={css.styleA}>Test</div>
}

Odd. You shouldn't need to do that. The context approach is really only useful for 100% dynamic styles that you also want to use with free-style. I don't believe it's the best way to use CSS-in-JS because you're losing a couple of benefits - hard to discover these styles and it'll be slower as it's hashing each render. Hash is quick, so you probably don't notice, but if you know the styles already it's easier to register it beforehand.

Am I right in believing this is purely to get a smaller CSS build with things you aren't using at runtime? I wouldn't want to use proxies myself, but if this is a feature you want I could add something. The way react-free-style works is with individual FreeStyle objects merging together - by adding a get('styleName') method, we could make it so an instance registers dynamically on usage and so it's all computed beforehand. Does that sound good?

Yes, I played with the minimal CSS footprint-feature. :) True, proxies are slow, but at least the hashing is done only the first time, I think. It was just me trying out to simplify the usage of react-free-style (no getter function, but dot-notation for access).

by adding a get('styleName') method, we could make it so an instance registers dynamically on usage and so it's all computed beforehand. Does that sound good?

I tried to avoid having to change the registered CSS classes every time you change the classes used by the component (two places to change). If it could be avoided without Proxies, that would be great.

A bit of explanation why I tried this:
I guess the used classes mostly change a lot while you are protoyping, especially with atomic CSS like Tachyons. At that stage, having to sync the class-names in two places could be annoying.

Theoretically, there could be a feature, where you save the used classes during development to a file in the component directory, similar to React HTML snapshots for testing. In production, you would then import this static information.

But all this is of course more complicated, than simply importing all styles, and using react-free-style to deduplicate classes. Especially with atomic CSS it would make sense, where the CSS footprint is minimized by design already anyway, and where you create your own classes less often.