Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Write a postcss plugin that'd make this compatible with CSS modules #70

Open
gajus opened this issue May 19, 2017 · 6 comments
Open

Write a postcss plugin that'd make this compatible with CSS modules #70

gajus opened this issue May 19, 2017 · 6 comments

Comments

@gajus
Copy link

gajus commented May 19, 2017

A large portion of user base is excluded because there is no integration with CSS modules.

The actual plugin is not complicated. All it needs to do is:

  1. find @element ".myDiv" and (min-width: 300px) {
  2. parse it
  3. use https://github.com/css-modules/postcss-modules to generate a new name (see babel-plugin-react-css-modules for an example)
  4. write @element ".generatedClassName" and (min-width: 300px) {

This issue has been raised with postcss team (css-modules/css-modules#169). However, no one has picked it up since. Presumably, because there is lack of overlapping userbase between the two communities.

@gajus
Copy link
Author

gajus commented May 19, 2017

I want to elaborate on how this is integrates into a project. Just so that we are all on the same page.

Lets start with a typical CSS module setup.

I have my styles, e.g.

.nose {
  color: red;
}

.sky {
  color: blue;
}

I consume these styles using a really awesome plugin babel-plugin-react-css-modules, e.g.

import React from 'react';
import './styles.css';

export default () => {
  return <div styleName='sky'>
    <div styleName='nose'></div>
  </div>;
};

Two things happen when this project is built:

  1. styles are assigned hashed named
  2. markup is generated using styleName hashed result for class property
<style>
.nose_demo_j4jf {
  color: red;
}

.sky_demo_14dg {
  color: blue;
}
</style>

<div class='sky_demo_14dg'>
  <div class='nose_demo_j4jf'></div>
</div

Note that in a project that is consuming CSS modules, it is canonical to have 1-to-1 relation between a styleName and an element with a specific role.

Now, I want my "nose" to change color depending on the size of they "sky". I can do this using EQCSS.

@element ".sky" and (min-width: 300px) {
  .nose {
    color: purple;
  }
}

For this to work, we need a postcss plugin that'd render the following CSS output:

.nose_demo_j4jf {
  color: red;
}

.sky_demo_14dg {
  color: blue;
}

@element ".sky_demo_14dg" and (min-width: 300px) {
  .nose_demo_j4jf {
    color: purple;
  }
}

This way EQCSS is able to recognize the target element.

@gajus
Copy link
Author

gajus commented May 20, 2017

@tomhodgins made a good suggestion that left my mind.

As a compromise, in context of React applications at least, you can write CSS inside a component.

Using css-loader, consumer can import CSS modules and use the resulting object to reference the generated class names. CSS can be then created using template tags and injected as a regular React component, e.g.

import styles from './styles.scss';

const eqcss = `
  @element ".${styles.sky}" and (min-width: 300px) {
    .${styles.nose} {
      color: purple;
    }
  }
`;

export default () => {
  return <div>
  <style>{eqcss}</style>
  <div styleName='sky'>
    <div styleName='nose'></div>
  </div>
</div>;
};

This still requires you to write CSS separately from the main stylesheets (assuming you are maintaining CSS in a separate file in the first place and not using something like styled-components). But it allows to use the full power of EQCSS without requiring postcss to support the syntax.

@gajus gajus closed this as completed May 20, 2017
@gajus gajus reopened this May 20, 2017
@thepian
Copy link

thepian commented Nov 3, 2017

Why can't this be a separate project? There is a new cool technology in JS land every 6 months that supposedly will take over the world. This project is a shim for future browser functionality. Yes I know that CSS modules is also, but the way most React projects do it is well beyond that.

Sorry to be gruff but I was forced to work with CSS Modules on a project and I had to work around it constantly (no I'm not against CSS modules, just the religious application).

@kennymalac
Copy link

This is a huge problem for me. I can't use this library without being able to use it on v-dom elements. :/

@tomhodgins
Copy link
Contributor

tomhodgins commented Dec 14, 2017

@kennymalac Do you have any code samples for what you're trying to do?

The way EQCSS works is by looking through the DOM for any element(s) matching the supplied selector, then if there are conditions, it will test them in realtime on the page, finally, if there were conditions and the test returns true, a copy of the stylesheet gets output into the DOM (but not before instances of eval(''), $this, $parent, $prev, $next, ew, eh, emin, and emax get resolved to their proper values)

It should be able to handle new HTML dynamically being added to the DOM just fine, but you'll need to add those elements to the DOM before EQCSS becomes 'aware' of them and has a chance to find, measure, test, and apply the styles.

If you're not married to EQCSS, this is one of ~thirty plugins I have for extending CSS - there's a big chance rather than trying to wrangle with EQCSS (by far the largest of them) there might be a smaller plugin that suits what you're trying to do that's easier to integrate into your toolchain or workflow, but I'd need to see what you're trying to do, hear an explanation of what you want, and to understand the elements, events, and styles you're working with :D

@kennymalac
Copy link

kennymalac commented Dec 15, 2017 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants