In styled-components docs, they have this example:
https://www.styled-components.com/docs/advanced#referring-to-other-components
It shows an Icon that changes color when you hover its parent, which is a link, in this case.
const Link = styled.a`
display: flex;
align-items: center;
padding: 5px 10px;
background: papayawhip;
color: palevioletred;
`;
const Icon = styled.svg`
flex: none;
transition: fill 0.25s;
width: 48px;
height: 48px;
${Link}:hover & { // <---- This is what I'm not understanding
fill: rebeccapurple;
}
`;
From the Docs, we know that:
Doc Note #1: styled-components solves this use case cleanly via the "component selector" pattern. Whenever a component is created or wrapped by the styled() factory function, it is also assigned a stable CSS class for use in targeting.
And also that:
Doc Note #2: Ampersands (&) get replaced by our generated, unique classname for that styled component, making it easy to have complex logic.
Let's analyze ${Link}:hover &
I know it gets translated into the browser as:
and:
I understand that sc-kAzzGY
is the "stable CSS class" (Doc Note #1) that is created whenever an element is wrapped by the styled
function.
I also know that the Ampersand (&) gets replaced by their generated unique classname (Doc Note #2) for that styled components. Hence, kDmLky
is that class.
QUESTION
But what does the resulting selector (picture below) is actually selecting? Can anybody explain that to me?
${Link}
is pointing to const Link
i.e.: "Hovering my parent changes my style" which gets a class of sc-kAzzGY
.
&
is kinda like saying "And add this to the current class(es)/id(s)/etc."
So,
.my-class {
some-css: awesomeness;
&:hover {
more-css: extra-cool;
}
}
is equivalent to:
.my-class {
some-css: awesomeness;
}
.my-class:hover {
more-css: extra-cool;
}
Therefore, &
points to the containing element const Icon
i.e. the speech bubble and gets a class of kDmLky
.
When Link
is hovered, cause Icon
to have fill: rebeccapurple
EDIT:
Just to clarify things a bit more:
When you have a declaration block inside of another declaration block like the example below, that inner declaration block becomes an independent one.
const Icon = styled.svg`
flex: none;
transition: fill 0.25s;
width: 48px;
height: 48px;
${Link}:hover & { // This declaraition block becomes an independent one
fill: rebeccapurple;
}
`;
And the result, in this case, is a declaration block with a selection that says:
When you have a class &
which is descendent of the class ${Link}
which is in the hover
state, apply these rules:
fill: rebeccapurple;
NOTE: ${Link}
refers to the Link class and &
refers to the Icon class (svg).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With