DEV Community

Cover image for How To Make Hover Effect Overflow Its Container with React
Radzion Chachura
Radzion Chachura

Posted on • Originally published at radzion.com

2 1

How To Make Hover Effect Overflow Its Container with React

Watch on YouTube | 🐙 GitHub | 🎮 Demo

Do you see this nice hover effect going beyond the boundaries of a checklist item? Let me show you how to make a reusable component to make any interactive element hoverable with ease.

The component receives children, an optional horizontal and vertical offset to let hover go beyond the boundaries of an element, the as property so we can render the element as a div, button, or label, and optional onClick and style properties.

import styled from "styled-components"

import { defaultTransitionCSS } from "./animations/transitions"
import { ComponentWithChildrenProps } from "lib/shared/props"
import { UnstyledButton } from "./buttons/UnstyledButton"
import { getCSSUnit } from "./utils/getCSSUnit"

const Highlight = styled.div`
  position: absolute;
  ${defaultTransitionCSS};
  border-radius: 8px;
`

const Container = styled(UnstyledButton)`
  position: relative;

  :hover ${Highlight} {
    background: ${({ theme }) => theme.colors.backgroundGlass.toCssValue()};
  }
`

const Content = styled.div`
  z-index: 1;
`

interface HoverableProps extends ComponentWithChildrenProps {
  horizontalOffset?: number
  verticalOffset?: number
  as?: React.ElementType
  onClick?: () => void
  style?: React.CSSProperties
}

export const Hoverable = ({
  children,
  horizontalOffset = 8,
  verticalOffset = 8,
  onClick,
  as,
  style,
}: HoverableProps) => {
  return (
    <Container onClick={onClick} as={as} style={style}>
      <Highlight
        style={{
          left: getCSSUnit(-horizontalOffset),
          top: getCSSUnit(-verticalOffset),
          width: `calc(100% + ${getCSSUnit(horizontalOffset * 2)})`,
          height: `calc(100% + ${getCSSUnit(verticalOffset * 2)})`,
        }}
      />
      <Content>{children}</Content>
    </Container>
  )
}
Enter fullscreen mode Exit fullscreen mode

We base the container on an UnstyledButton component that clears all the default styles of a button element. We want it to be relative so we can position the Highlight element absolutely. The hover effect has a transition to animate appearance, border-radius, and no background, as it will be set on hover of the Container element. To position the Highlight and make it larger than the content inside, we'll make the left and top values negative and make the width and height 100% plus their offset. To make the content appear above the hover effect, we'll apply a z-index.

Image of Datadog

The Essential Toolkit for Front-end Developers

Take a user-centric approach to front-end monitoring that evolves alongside increasingly complex frameworks and single-page applications.

Get The Kit

Top comments (0)

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read more →