In styled-ponents
we can add contextual styles using ponent selector pattern. But how do we select specific parents variants to contextually style the child ponent? For example, we have three ponents here, Child
, NoteWrapper
, and Note
.
const Child = styled.div<{ editing?: boolean }>`
${props => props.editing && css`some styles`}
`
const NoteWrapper = styled.div<{ pact?: boolean }>`
${props => propspact && css`some styles`}
`
const Note = styled.input`
/* How do I style this when Child is editing and NoteWrapper is pact */
`
const App = () => {
return (
<Child editing>
<NoteWrapper pact>
<Note/>
</NoteWrapper>
</Child>
)
}
`
With plain CSS we could do something like this
.child.editing .note-wrapperpact .note {
/* Contextual styles here */
}
I know I can easily use the editing
and pact
variables and pass it to the Note
ponent. However, it would be difficult to do so if ponents are highly nested.
My question is how do I style Note
when Child
is editing
and NoteWrapper
is pact
in styled-ponents
selector pattern?
I don't think we can do something like this in styled-ponents
in some way? Can we?
const Note = styled.input`
${Child.editingClass} ${NoteWrapperpactClass} & {
/* The contextual styles here*/
}
`
In styled-ponents
we can add contextual styles using ponent selector pattern. But how do we select specific parents variants to contextually style the child ponent? For example, we have three ponents here, Child
, NoteWrapper
, and Note
.
const Child = styled.div<{ editing?: boolean }>`
${props => props.editing && css`some styles`}
`
const NoteWrapper = styled.div<{ pact?: boolean }>`
${props => props.pact && css`some styles`}
`
const Note = styled.input`
/* How do I style this when Child is editing and NoteWrapper is pact */
`
const App = () => {
return (
<Child editing>
<NoteWrapper pact>
<Note/>
</NoteWrapper>
</Child>
)
}
`
With plain CSS we could do something like this
.child.editing .note-wrapper.pact .note {
/* Contextual styles here */
}
I know I can easily use the editing
and pact
variables and pass it to the Note
ponent. However, it would be difficult to do so if ponents are highly nested.
My question is how do I style Note
when Child
is editing
and NoteWrapper
is pact
in styled-ponents
selector pattern?
I don't think we can do something like this in styled-ponents
in some way? Can we?
const Note = styled.input`
${Child.editingClass} ${NoteWrapper.pactClass} & {
/* The contextual styles here*/
}
`
Share
Improve this question
edited Nov 30, 2021 at 4:00
Bijay Shrestha
asked Nov 30, 2021 at 3:53
Bijay ShresthaBijay Shrestha
871 gold badge1 silver badge7 bronze badges
2 Answers
Reset to default 6As far as I know, you can't access editing
or pact
, since they're props and aren't "propagated" in CSS. But you can achieve the same result using either classes or data attributes.
Here's how I'd do it:
const App = () => {
return (
<Child data-editing={true}>
<NoteWrapper data-pact={true}>
<Note/>
</NoteWrapper>
</Child>
)
}
const Child = styled.div`
`
const NoteWrapper = styled.div`
`
const Note = styled.input`
${Child}[data-editing="true"] ${NoteWrapper}[data-pact="true"] & {
/*
Only applied when Child is editing and NoteWrapper is pact
*/
color: red;
}
`
Essentially, styled-ponents needs to produce valid CSS at the end of the day. ${Child}
will be replaced by the custom-generated classname, like .sc-abc123
. And so the end result is .sc-abc123[data-editing="true"]
, which is totally-valid CSS.
You could also use classes, which looks a bit tidier:
const App = () => {
return (
<Child className="editing">
<NoteWrapper className="pact">
<Note/>
</NoteWrapper>
</Child>
)
}
const Child = styled.div`
`
const NoteWrapper = styled.div`
`
const Note = styled.input`
${Child}.editing ${NoteWrapper}.pact & {
/*
Only applied when Child is editing and NoteWrapper is pact
*/
color: red;
}
`
I prefer to use data-attributes because it's clear that they're used for logical purposes, and not because editing
is a CSS class with a bunch of styles. But that's a subjective preference, they both work equally well in terms of objective functionality :)
You could also pass the props to the Note
ponent itself and do a similar logic check.
<Note
pactEdit={editing && pact}
/>
const Note = styled.div`
${props =>
props.pactEdit
? css`color: red;`
: css`color: blue;`
};
`;