I have a Playground here: https://codesandbox.io/s/736v9vjzw1
const Something = ({ classes, children, variant }) => {
return (
<div className={classes.someThing}>
<p> I'm some thing </p>
<SomeOtherThing />
<SomeOtherThing> I have some children </SomeOtherThing>
<SomeOtherThing> I have some children </SomeOtherThing>
<SomeOtherThing> I have some children </SomeOtherThing>
</div>
);
};
const styles = {
someThing: {
color: "green",
border: "solid 2px black",
margin: 30,
"& $someOtherThing": {
backgroundColor: "pink" // Doesn't work
},
"& p": {
fontWeight: "bold" //This works but is too broad
}
}
};
I have a situation here, where I want to style all the SomeOtherThing
s inside my SomeThing
.
I can use & p
selector to select the p
element - but I don't like this. It would style any random p
s I have around - and I don't want to have to look inside the component definition to find what it's top level element is.
How can I do this? Something like & SomeOtherElement
.
The real world application of this, is that in some places I want have SomeOtherElement
be displayed block
and other places inline-block
.
I would extend the
SomeOtherThing
component to accept a className and add it to thediv
if present. This will also work on a production setup, where the class names is minified to e.g..t-0-root
.Here is a forked playground: https://codesandbox.io/s/zlzx277zzm which shows how to use it.
I would most likely use the package
classnames
to conditionally render the class name instead of string interpolation.One problem with the "cascading" aspect of CSS is that it sort of breaks React's component model. But in React you can always create a wrapper or higher-order component that returns another with some predefined props, kind of like a factory function:
Instead of using the
&
selector to define your style, create a class that only applies to these specific versions of your component. In this way, the global scope of CSS is avoided and you can create these sort of declarative components that describe their own style, but don't require you to explicitly pass a class name.It's so simple, in your
someThing
CSS codes select thep
elements with classsomeOtherThing
class name and usenot()
CSS operation forp
in top level, see following code:and
CodeSandBox
The way that this works, is that by giving
SomeOtherThing
any jss class, it's going to render the dom element as something like:which the
[class*='SomeOtherThing'
] attribute selector will match on.You should note that this selector will apply to any deeper nested
SomeOtherThing
s as well.