Previously in Emotion 9 you were able to use Emotion class names to take advantage of cascade. You would wrap the emotion const in curly brackets and prefix it with a period, and then dollar sign. For example, you could do this:
const child = css`
color: green;
`;
const parent = css`
color: red;
.${child} {
color: yellow;
}
`;
<div className={parent}>I am red</div>
<div className={child}>I am green</div>
<div className={parent}>
<div className={child}>I am yellow</div>
</div>
How can I go about achieving this behavior in Emotion 10? That is my question.
The following is further information about what happens when you don't use a period-dollar sign.
Now, the following was and is desirable: if no period are used in Emotion 9 or 10, the parent const will inherit the nested const styles. And furthermore, if that nested const then has overriding styles, those would ultimately be inherited by the parent.
const child = css`
color: green;
`;
const parent = css`
color: red;
`;
<div className={parent}>I am red</div>
<div className={child}>I am green</div>
const child = css`
color: green;
`;
const parent = css`
${child}
`;
<div className={parent}>I am green</div>
const child = css`
color: green;
`;
const parent = css`
${child} {
color: yellow;
}
`;
<div className={parent}>I am yellow</div>
const child = css`
color: green;
`;
const parent = css`
color: red;
${child}
`;
<div className={parent}>I am green</div>
const child = css`
color: green;
`;
const parent = css`
color: red;
${child} {
color: yellow;
}
`;
<div className={parent}>I am yellow</div>
The following will work, it just doesn't work in CodePen as the output code there has more text tacked onto it, and it hashes the const names all over again. But if you test in your own code base, this does work. I don't like doing it, it feels hacky. Would like Emotion to have something specific for these instances.
const cat = css`
color: red;
`;
const dog = css`
color: green;
.css-${cat.name} {
border-bottom: 1px solid currentColor;
}
`;
This isn't totally safe, mind you. If you are rendering subcomponents, they will not always get the same hashed class name. Additionally it also seems that Emotion will tack on the subcomponents name to the end of the hashed class name to avoid clashing I assume. So, proceed with caution. What I would really like is for Emotion to return the functionality it had in V.9 - an example of which is found in their V9 documentation, last example on this page:
https://5bb1495273f2cf57a2cf39cc--emotion.netlify.com/docs/nested
Yes, I agree this is needed! We can target with styled, but then composition is not as easy.
Workaround: use pre-generated name and object css.
const child = css`
color: green;
`;
const parent = css({
color: 'red',
[`.${child}`]: {
color: 'yellow',
},
});
I'm trying your suggestion, @TerenceZ , but I am not having any luck. The nested child styles do not appear to work.
If you use the /macro or Babel preset you can reference other styled components in your selectors.
const Foo = styled.div``;
const bar = styled.div`
${Foo} {
color: red;
}
`;
If you want to use the syntax posted in your original post, you must make sure to use the emotion package, not the React-specific @emotion/css or @emotion/styled ones, because they don't directly generate class names, but objects not meant to be consumed by 3rd party code.
I hope this answers your question!
@FezVrasta @mitchellhamilton Could this breaking change be referenced in the Emotion documentation? I have not seen anything written on it. On the page about migration, we could add a text explaining the need to use the babel-plugin-macros to keep "styled children target" work.
@thibaultboursier being able to use styled components as selector has always been a babel-powered feature
@Andarist Sure (https://emotion.sh/docs/styled#targeting-another-emotion-component). But we could add some information to say explicitly that it does not work anymore with Emotion 10.
This should very much work with Emotion 10. Maybe you experience some misconfiguration problem? Could you prepare a repro case on which I could take a look?
is there any solution to this? I am trying to achieve something like
const A = css`
// ...some style
`;
const B = css`
// some style
.${A} & {
// some update style
}
`;
but it seems that it doesn't work at all
@LXSMNSYC Does this work for you? It seems hacky and is recommended against above in this thread.
const A = css`
// ...some style
`;
const B = css`
// some style
.css-${A.name} & {
// some update style
}
`;
@ksweetie not with the emotion package, it returns a string
Some update?
I don't think this is going to be changed. And the way I work with Emotion now, I wouldn't need it anymore. What is the use case you are trying to solve for @rochagbr ?
Most helpful comment
This isn't totally safe, mind you. If you are rendering subcomponents, they will not always get the same hashed class name. Additionally it also seems that Emotion will tack on the subcomponents name to the end of the hashed class name to avoid clashing I assume. So, proceed with caution. What I would really like is for Emotion to return the functionality it had in V.9 - an example of which is found in their V9 documentation, last example on this page:
https://5bb1495273f2cf57a2cf39cc--emotion.netlify.com/docs/nested