How to create an accordion hover effect with box-shadows
Tags: html, css, tutorial
Published: 2020-03-13 17:00:11

This tutorial was originally posted on [fossheim.io](https://fossheim.io/writing/posts/css-box-shadow-animation/).

In this tutorial we'll use the `box-shadow` property to create a layered card component, and animate it on hover. 

{% codepen https://codepen.io/fossheim/pen/MWwOBwx %}

## The box-shadow property explained

To add shadows to a box we'll need to specify several things in the `box-shadow` property:
- `x-offset`: Position on the x-axis. A positive value moves the shadow to the right, a negative value moves the shadow to the left. _(required)_
- `y-offset`: Position on the y-axis. A positive value moves the shadow to the bottom, a negative value moves the shadow to the top. _(required)_
- `blur`: How much blur the shadow should have. The higher the value, the softer the shadow. The value is set to 0px, meaning no blur, by default.  _(optional)_
- `spread`: How much larger the shadow should be compared to the component. A positive value makes the shadow larger than the box, a negative value makes the shadow smaller. _(optional)_
- `color`: Which color the shadow should have. The default value is the text color. _(optional, required for Safari)_
- `inset`: The position of the shadow. By default the shadow is outside the box. Setting inset moves it to the inside. _(optional)_

```CSS
    box-shadow: [x-offset] [y-offset] [blur] [spread] [color] [inset];
```

For example:

{% codepen https://codepen.io/fossheim/pen/poJdVEg %}

You can read more about box-shadows on [W3Schools](https://www.w3schools.com/cssref/css3_pr_box-shadow.asp) or [css-tricks](https://css-tricks.com/almanac/properties/b/box-shadow/). My [CSS-only polaroid camera](/writing/posts/css-polaroid-camera/) is built using box-shadows as well.

## The card component

We don't need to write any additional HTML to add the stacked cards in the background. We'll start our tutorial with the following code:

```HTML
    <div class="card">
        <p>Similar post</p>
        <h2>How I recreated a Polaroid camera with CSS gradients only</h2>
    </div>
```

{% codepen https://codepen.io/fossheim/pen/MWwOXRz %}

## Translating cards into shadows

We want to stack 4 cards behind our component, each with the same border width (3px) and same background (white) but a different position and border color. 

This means we'll need to draw 8 shadows: one for each color/border, and one for each white fill. 

### Adding the first background card

We'll start by adding the first green caed behind the component. Let's take a look at its requirements:
- Move 10px to the right
- Move 10px to the top
- No blur
- Same size as container (no spread)
- Green color (<span style="background-color: #5CBD3F; color: #192824">#5CBD3F</span>)

This translates into CSS like this:

```CSS
    box-shadow: 10px -10px 0 0 #5CBD3F;
```

{% codepen https://codepen.io/fossheim/pen/vYOWroy %}

### Combining shadows to create fills and borders

Next, we have to draw a white shadow on top of the green one to mimic the white fill of the box.

The border should be 3 pixels thick, so the white shadow should be 3px smaller than the colored one on each side. We can do this by setting a negative spread:

```CSS
    box-shadow: 10px -10px 0 -3px white;
```

When adding several shadows, the one that's listed first will be rendered on top. So our code will now look like this:

```CSS
    box-shadow: 10px -10px 0 -3px white, 10px -10px 0 0 #1FC11B;
```

{% codepen https://codepen.io/fossheim/pen/xxGPJxb %}

Repeat the same process three more times for the other colors, and keep moving the shadows 10px upwards and to the right.

```CSS
    box-shadow: 10px -10px 0 -3px white, 10px -10px 0 0 #1FC11B, /* Green */
        20px -20px 0 -3px white, 20px -20px 0 0 #FFD913, /* Yellow */
        30px -30px 0 -3px white, 30px -30px 0 0 #FF9C55, /* Orange */
        40px -40px 0 -3px white, 40px -40px 0 0 #FF5555; /* Red */
```

{% codepen https://codepen.io/fossheim/pen/GRJOBRE %}

## Adding the hover animation

Now that the design is in place, the only thing left to do is adding the hover animation. 

All the cards will have to move from their original position to the position of the red card in the back. The first step is to change the position of our component.

```CSS
.card {
    position: relative;
    top: 0;
    left: 0;
    transition: left 1s, top 1s;
}

.card:hover {
    top: -40px;
    left: 40px;
}
```

{% codepen https://codepen.io/fossheim/pen/wvaPxam %}

The shadows still move along with the component because the offset is still the same. All the shadows have to move towards the same position as the box, meaning their horizontal and vertical offset has to be set to 0.

```CSS
.card {
    position: relative;
    top: 0;
    left: 0;
    transition: box-shadow 1s, left 1s, top 1s;
}
.card:hover {
    box-shadow: 0 0 0 -3px white, 0 0 0 0px #1FC11B,
        0 0 0 -3px white, 0 0 0 0px  #FFD913,
        0 0 0 -3px white, 0 0 0 0px  #FF9C55,
        0 0 0 -3px  white, 0 0 0 0px  #FF5555;
    top: -40px;
    left: 40px;
}
```

This gives us our desired end result:

{% codepen https://codepen.io/fossheim/pen/MWwOBwx %}

## More border effects using box-shadows

{% codepen https://codepen.io/fossheim/pen/LYVOBRZ %}

{% codepen https://codepen.io/fossheim/pen/qBdVyNZ %}

{% codepen https://codepen.io/fossheim/pen/dyoZjMO %}

{% codepen https://codepen.io/fossheim/pen/yLNPqeZ %}

{% codepen https://codepen.io/fossheim/pen/abOYqKY %}

{% codepen https://codepen.io/fossheim/pen/abOVjJv %}