Hi,

I understand the behavior of Emotion, but I don't understand why this behavior has been choosed over the one of original classnames tool which does concat the 2 classes instead of producing a new one.
If there are already 2 classes available in the stylesheet, why would we want to insert a new merged one when doing cx(cls1,cls2), isn't this supposed to be less performant? I think explaining this choice in the doc would be helpful and I could submit a PR once I understand the reason behind this choice
The reason for it is mentioned in the doc just below the place in your screenshot
If the order of the class names is reversed in the cx call the styles would change precedence.
This allows you to have predictable composition so you don't have to worry about specificity and which class was inserted first but you can instead know that the order of the styles will be whichever is first in the cx call.
If you think the wording could be improved or it could be explained better then we would love a PR!
Hi,
I understand the order of the cls1 and cls2 matter to know which styles are applied finally, but instead of merging the 2 classes, couldn't we just append the classnames in the initial order?
I mean: <div class="cls1 cls2"/> vs <div class="cls2 cls1"/> would produce the same result no?
Maybe this behavior is to solve the specificity problem when the class contain high specificity nested selectors like ids or attributes?
The point is you should be able to specify the order that styles should be applied and you can't do that if you just append the class names.
You can see another explanation of this at https://emotion.sh/docs/composition.
I just noticed that that composition example actually seems to be broken but the first example should be turquoise rather than red. That's just another example of how using the insertion order makes composition unpredictable.
(It seems to be a problem with ssr so if you go to another page, reload and navigate to the composition page, it'll work)
I mean:
vs would produce the same result no?
Yeah, exactly, but cx(cls1, cls2) and cx(cls2, cls1) won't produce the same result and that is nice feature, because u don't have to worry which class got inserted to the stylesheets first, u can just rely on cx arguments order and it's predictable.
omg I always thought the class name order did matter for same specificity classes! just tested and you are right :O http://jsfiddle.net/slorber/v2w0hboj/2/
So basically all this time I was lucky using css-in-js because I had the correct insertion order
So to give more context on what I'd like to achieve, is to compose styles together and avoid merging my "base style" to the custom style, that can always override the base style
For example currently I have:
import React from 'react';
import {css} from 'emotion';
import classnames from 'classnames';
const centered = css`
display: flex;
align-items: center;
justify-content: center;
`;
export const Centered = ({className, ...props}) => (
<div className={classnames(centered,className)} {...props}/>
);
const row = css`
display: flex;
flex-direction: row;
align-items: center;
`;
export const Row = ({className, ...props}) => (
<div className={classnames(row,className)} {...props}/>
);
And using <Row css={{alignItems: 'baseline', ...}}/>
I'm considering migrating to cx but noticed this different behavior, and I feel that merging the 2 classnames would be less performant than reusing the base row class and adding another custom class to override it. Not a big deal, just thinking about the perf implications, I don't currently have any perf problem.
In such a case (where I know the row style is inserted first for sure), does it make sense to not use cx behavior as an optimisation and make sure I get 2 classes as output?
Use cx. The performance cost will be not be noticeable whatsoever in comparison to all the work react and etc. do.
omg I always thought the class name order did matter for same specificity classes!
Very common misconception, class name order in stylesheet > class name order on element. That's why styled-components (and I assume emotion too?) does a bunch of work to make sure we inject things in the right order at the right time based on dependencies and stuff! That's where a solid 80% of the complexity in the styled-components codebase comes from.
We actually don't care about insertion order because as you mention it's really complex and requires a bunch of code.
We rely on composition instead so we store all the styles in a cache and for example with styled we pull out all of the emotion class names in the className prop and merge those styles with the styles passed to the styled call.
thanks all this is useful to know ;)
Most helpful comment
We actually don't care about insertion order because as you mention it's really complex and requires a bunch of code.
We rely on composition instead so we store all the styles in a cache and for example with styled we pull out all of the emotion class names in the className prop and merge those styles with the styles passed to the styled call.