Emotion: Support multiple nested selectors (`& > &`)

Created on 29 Mar 2020  路  4Comments  路  Source: emotion-js/emotion

The problem

It's not easy to target a component inside another of the same component. e.g. as a direct child of another

Proposed solution

Allow multiple &s in a rule.

e.g.

<div
    css={{
      color: 'darkorchid',
      '& > &': {
         color: 'hotpink'
       }
    }}
  >
    This is darkorchid.
  </div>

Alternative solutions

I haven't thought of any clean solutions to this.

question

Most helpful comment

I'm not sure I follow what you mean when you say "unique styles"

My understanding is that in this case:

  <div css={{
      color: 'darkorchid',
      '&:hover': {   color: 'hotpink'  }
    }}
  >
    This is darkorchid.
  </div>

The component will be assigned a className, eg xyz and css for that className would be generated, where & is essentially replaced with the className, like so:

  .xyz {
    color: darkorchid;
  }
  .xyz:hover {
    color: hotpink;
  }

My suggestion is to replace multiple ampersands, not just one. e.g. & > &

  color: 'darkorchid',
  '& > &': {
     color: 'hotpink'
   }

would be compiled to

  .xyz {
    color: darkorchidl
  }
  .xyz > .xyz {
    color: hotpink;
  }

If you nest this component directly inside another instance of this component the CSS would apply. There would be no need to awareness of the nesting in JS, the CSS would just work in the browser.

All 4 comments

& refers to "unique styles", it's not aware of any kind of component identity. Most of the time the preferred solution is to avoid descendant selectors altogether, but if that's not an option I feel like data attributes are clean of doing this.

I'm not sure I follow what you mean when you say "unique styles"

My understanding is that in this case:

  <div css={{
      color: 'darkorchid',
      '&:hover': {   color: 'hotpink'  }
    }}
  >
    This is darkorchid.
  </div>

The component will be assigned a className, eg xyz and css for that className would be generated, where & is essentially replaced with the className, like so:

  .xyz {
    color: darkorchid;
  }
  .xyz:hover {
    color: hotpink;
  }

My suggestion is to replace multiple ampersands, not just one. e.g. & > &

  color: 'darkorchid',
  '& > &': {
     color: 'hotpink'
   }

would be compiled to

  .xyz {
    color: darkorchidl
  }
  .xyz > .xyz {
    color: hotpink;
  }

If you nest this component directly inside another instance of this component the CSS would apply. There would be no need to awareness of the nesting in JS, the CSS would just work in the browser.

My suggestion is to replace multiple ampersands, not just one. e.g. & > &

And this works just fine: https://codesandbox.io/s/quirky-noyce-5nn9g?file=/src/App.js

But... this doesn't: https://codesandbox.io/s/vibrant-microservice-7fr2o?file=/src/App.js

And this is what I was referring to as "& referring to unique styles". In the second example even though the same component is used it has 2 different styles and thus & is being replaced to a different class name in both instances of this component.

This is basically the same as https://github.com/emotion-js/emotion/issues/1922 , even though this issue here is older I'm going to close this one as the other one seems to have more information regarding this problem.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MrFungusEli picture MrFungusEli  路  3Comments

artooras picture artooras  路  3Comments

desmap picture desmap  路  3Comments

eddeee888 picture eddeee888  路  3Comments

Aaron-Pool picture Aaron-Pool  路  3Comments