153

What is the best way to handle hovers in styled-components. I have a wrapping element that when hovered will reveal a button.

I could implement some state on the component and toggle a property on hover but was wondering if there is a better way to do this with styled-cmponents.

Something like the following doesn't work but would be ideal:

const Wrapper = styled.div`
  border-radius: 0.25rem;
  overflow: hidden;
  box-shadow: 0 3px 10px -3px rgba(0, 0, 0, 0.25);
  &:not(:last-child) {
    margin-bottom: 2rem;
  }
  &:hover {
    .button {
      display: none;
    }
  }
`
mxstbr
  • 11,087
  • 4
  • 39
  • 37
nickspiel
  • 5,170
  • 6
  • 33
  • 48

7 Answers7

268

As of styled-components v2 you can interpolate other styled components to refer to their automatically generated class names. In your case you'll probably want to do something like this:

const Wrapper = styled.div`
  &:hover ${Button} {
    display: none;
  }
`

See the documentation for more information!

The order of components is important. It will only work if Button is defined above/before Wrapper.


If you're using v1 and you need to do this you can work around it by using a custom class name:

const Wrapper = styled.div`
  &:hover .my__unique__button__class-asdf123 {
    display: none;
  }
`

<Wrapper>
  <Button className="my__unique__button__class-asdf123" />
</Wrapper>

Since v2 is a drop-in upgrade from v1 I'd recommend updating, but if that's not in the cards this is a fine workaround.

Paul Fitzgerald
  • 11,770
  • 4
  • 42
  • 54
mxstbr
  • 11,087
  • 4
  • 39
  • 37
  • 24
    For anyone reading this, the order of components is important. It will only work if `Button` is defined above/before `Wrapper` – Titan Jan 26 '18 at 16:28
  • Actually, another important documentation is [Referring to other components](https://www.styled-components.com/docs/advanced#referring-to-other-components) – L_K Mar 17 '18 at 04:54
  • 1
    What if I wanted to count on some props passed to Button from Wrapper, so the hover looks different depending on thos props? – rmartrenado Dec 14 '18 at 10:06
  • What if you want to target a class component that is not the child. I mean like they have the same level element – Chervin Tanilon Jun 18 '21 at 08:00
  • Anyone having issues with typescript and linting here? I'm using @emotion/styled, but I think I'm missing something – neaumusic Dec 22 '21 at 02:59
61

Similarly to mxstbr's answer, you can also use interpolation to reference a parent component. I like this route because it encapsulates a component's styling a little better than referencing the child component in the parent.

const Button = styled.button`
  ${Wrapper}:hover & {
    display: none;
  }
`;

I couldn't tell you when this feature was introduced but this works as of v3.

Relevant link: https://www.styled-components.com/docs/advanced#referring-to-other-components

Omegalen
  • 1,456
  • 1
  • 13
  • 18
7
const ConnectButton = styled(WalletDialogButton)`
  background-color: #105b72;
  border: none;
  margin: 10vh auto;
  width: 250px;

  &:hover {
    background-color: #105b72c2;
  }
  `;

This worked for me as Marcos said. I'm using styled() instead of styled.something

I don't really know why, but I'm referencing a node_modules package where WalletDialogButton exists.

0xgio
  • 121
  • 1
  • 4
6

My solution is

const Content = styled.div`
  &:hover + ${ImgPortal} {
    &:after {
      opacity: 1;
    }
  }
`;
Markus Zeller
  • 8,516
  • 2
  • 29
  • 35
6

This is what worked for me

const NoHoverLine = styled.div`
  a {
    &:hover {
      text-decoration: none;
    }
  }
`
C-Dev
  • 425
  • 1
  • 6
  • 15
3

This solution worked for me:

const ContentB = styled.span`
  opacity: 0;

  &:hover {
    opacity: 1;
  }
`

const ContentA = styled.span`
  &:hover ~ ${ContentB} {
    opacity: 1;
  }
`
MarcosSantosDev
  • 313
  • 2
  • 5
3

If you are using MUI

Here is a code sample:

...
  parentClass: {
    "&:hover $childClass": {
      display: 'flex'
    }
  },
  childClass: {
    position: "absolute",
    right: 5,
    display: 'none'
  },
...

Apply the child class to the component you want to affect onhover

Babs
  • 31
  • 1