Open In App

How to create responsive stacked cards hover effect using CSS ?

Last Updated : 12 Sep, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

We will create responsive stacked cards using HTML and CSS. To achieve a multi-layer stacking effect, you have to follow certain steps given below.

Note: By hovering over the cards, we can achieve various directions or effects on the cards, such as top-left, bottom-right, diagonal, rotate, etc.

Approach

  • Design a simple card structure in HTML.
  • Use CSS properties to build the basic design of the card.
  • Define ::before and ::after pseudo-elements and position them relative to the parent card to create a stack effect.
  • Move the div with class “card-inner” away from its original position using the transform property.
  • Add a hover effect on the stack of cards using a transform that translates the card before and after the hover effect.

Example 1: In this example,  On hover, the top card translates 5px along the X and Y axes (bottom-right direction), while the below stacked card moves in the opposite direction (-X, -Y), creating a stacked bottom-right effect using ::before and ::after pseudo-elements.

HTML
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" 
          content="width=device-width, initial-scale=1.0">
    <title>Stacked Cards Hover Effect</title>
    <style>
        body {
            color: #ffffff;
            background: #1f1f1f;
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
        }

        h1 {
            margin-bottom: 20px;
        }

        .card-container {
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
        }

        .card {
            position: relative;
            width: 100%;
            max-width: 400px;
            margin: 20px;
            perspective: 1000px;
        }

        .card::before,
        .card::after {
            content: "";
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }

        .card::before,
        .card::after,
        .card .card-inner {
            background-color: #2e2e2e;
            border: 1px solid #00796b;
            border-radius: 10px;
            transition: transform 0.5s, box-shadow 0.5s;
        }

        .card::before,
        .card-inner {
            z-index: 1;
        }

        .card-inner {
            position: relative;
            padding: 2rem;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        }

        .cards:hover .card-inner {
            transform: translate(5px, 5px);
            box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
        }

        .cards:hover::before {
            transform: translate(-5px, -5px);
        }

        .cards:hover::after {
            transform: translate(-10px, -10px);
        }

        @media (max-width: 600px) {
            .card {
                width: 90%;
            }

            .card-inner {
                padding: 1rem;
            }
        }
    </style>
</head>

<body>
    <div class="card-container">
        <h1>Welcome to GeeksforGeeks</h1>
        <div class="card cards">
            <div class="card-inner">
                <h1>Down-Right</h1>
                <h3 class="card-title">GeeksforGeeks</h3>
                <div class="card-body">
                    A Complete Portal for Geeks.
                </div>
            </div>
        </div>
    </div>
</body>

</html>

Output:

Example 2: In this example, we will see stacked-diagonal-left and stacked-rotate-left using the same approach as explained above.

Stacked-Rotate-left:

  • Top Card will translate only over X-axis , here ( translate(2.5px, 0) ) left direction, and rotate at certain angle, here its 2.5 degree ( rotate(2.5deg) ) .then
  • Below stacked card will also translate and rotate in the same direction but with double pixel to create a stacked multi-layer effect with the help of before and after Pseudo element.

Stacked-diagonal-left:

  • In diagonal-left, Initially multi-layer stack card is positioned in opposite direction to the directional-left ( translate(-16px, -16px) ) using transform:translate property and then
  • When the user hovers over the card, stacked multi-layer card will translate to diagonal-left direction using same value i.e ( translate(16px, 16px)  ) but opposite sign so that stacked multi-layer cards can cover equal direction.
HTML
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" 
          content="width=device-width, initial-scale=1.0">
    <title>Stacked Cards Hover Effect</title>
    <style>
        body {
            color: #FDFDFD;
            background: #1E3A8A;
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
            min-height: 100vh;
            margin: 0;
        }

        :root {
            --offset-before: 8px;
            --offset-after: 16px;
        }

        h1 {
            margin: 40px 0;
            font-size: 2.5rem;
            text-align: center;
        }

        .card-container {
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
            margin-bottom: 20px;
        }

        .card {
            position: relative;
            width: 100%;
            max-width: 400px;
            margin: 20px;
            perspective: 1000px;
        }

        .card::before,
        .card::after {
            content: "";
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            border-radius: 12px;
        }

        .card::before,
        .card::after,
        .card .card-inner {
            background-color: #2E2E2E;
            border: 1px solid #0FBFC4;
            transition: transform 0.5s, box-shadow 0.5s;
        }

        .card::before,
        .card-inner {
            z-index: 1;
        }

        .card-inner {
            position: relative;
            padding: 2rem;
            border-radius: 12px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
        }

        .cards-diagonal::before {
            transform: translate(calc(-1 * var(--offset-before)), calc(-1 * var(--offset-before)));
        }

        .cards-diagonal::after {
            transform: translate(calc(-1 * var(--offset-after)), calc(-1 * var(--offset-after)));
        }

        .cards-diagonal:hover::before {
            transform: translate(var(--offset-before), var(--offset-before));
        }

        .cards-diagonal:hover::after {
            transform: translate(var(--offset-after), var(--offset-after));
        }

        .cards-rotate::before,
        .cards-rotate::after {
            transform-origin: 50% 100%;
        }

        .cards-rotate:hover {
            transform: translate(2.5px, 0) rotate(2.5deg);
        }

        .cards-rotate:hover::before {
            transform: translate(2.5px, 0) rotate(2.5deg);
        }

        .cards-rotate:hover::after {
            transform: translate(5px, 0) rotate(5deg);
        }

        @media (max-width: 600px) {
            .card-inner {
                padding: 1.5rem;
            }

            h1 {
                font-size: 2rem;
            }
        }
    </style>
</head>

<body>
    <h1>Welcome to GeeksforGeeks</h1>
    <div class="card-container">
        <div class="card cards-diagonal">
            <div class="card-inner">
                <h1>Diagonal-Left</h1>
                <h3 class="card-title">GeeksforGeeks</h3>
                <div class="card-body">
                    A Complete Portal for Geeks.
                </div>
            </div>
        </div>
    </div>
    <div class="card-container">
        <div class="card cards-rotate">
            <div class="card-inner">
                <h1>Rotate-Left</h1>
                <h3 class="card-title">GeeksforGeeks</h3>
                <div class="card-body">
                    A Complete Portal for Geeks.
                </div>
            </div>
        </div>
    </div>
</body>

</html>

Output:

Example 3: In this example, we will see stacked-Up and stacked-Right effects using the same approach as explained above.

Stacked-Up:

  • Top Card will translate only in negative Y-axis , here (translate(0, -5px)) Up direction, then
  • below stacked card will translate positive Y-axis i.e opposite to Up direction and it will also scale along Y-axis which will create multiple stacked-Up effects with the help of before and after Pseudo element.

Stacked-Right:

  • Top Card will translate only in positive X-axis , here ( translate(5px, 0) ) Right direction, then
  • below stacked card will translate negative X-axis (  translate(-10px, 0)  )  i.e opposite to right direction and it will also scale along negative X-axis which will create multiple stacked-Up effects with the help of before and after Pseudo element.
HTML
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" 
          content="width=device-width, initial-scale=1.0">
    <title>Stacked Cards Hover Effect</title>
    <style>
        body {
            color: #FDFAF6;
            background: #1E3A8A;
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
            min-height: 100vh;
            margin: 0;
        }

        :root {
            --offset-before: 8px;
            --offset-after: 16px;
        }

        h1 {
            margin: 40px 0;
            font-size: 2.5rem;
            text-align: center;
        }

        .card-container {
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
            margin-bottom: 20px;
        }

        .card {
            position: relative;
            width: 100%;
            max-width: 400px;
            margin: 20px;
            perspective: 1000px;
        }

        .card::before,
        .card::after {
            content: "";
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            border-radius: 12px;
        }

        .card::before,
        .card::after,
        .card .card-inner {
            background-color: #2E2E2E;
            border: 1px solid #0FBFC4;
            transition: transform 0.5s, box-shadow 0.5s;
        }

        .card::before,
        .card-inner {
            z-index: 1;
        }

        .card-inner {
            position: relative;
            padding: 2rem;
            border-radius: 12px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
        }

        .cards-up::before,
        .cards-up::after {
            transform-origin: center bottom;
        }

        .cards-up:hover {
            transform: translate(0, -5px);
        }

        .cards-up:hover::before {
            transform: translate(0, 5px) scale(0.95);
        }

        .cards-up:hover::after {
            transform: translate(0, 10px) scale(0.90);
        }

        .cards-right::before,
        .cards-right::after {
            transform-origin: left center;
        }

        .cards-right:hover {
            transform: translate(5px, 0);
        }

        .cards-right:hover::before {
            transform: translate(-10px, 0) scale(0.95);
        }

        .cards-right:hover::after {
            transform: translate(-20px, 0) scale(0.90);
        }

        @media (max-width: 600px) {
            .card-inner {
                padding: 1.5rem;
            }

            h1 {
                font-size: 2rem;
            }
        }
    </style>
</head>

<body>
    <h1>Welcome to GeeksforGeeks</h1>
    <div class="card-container">
        <div class="card cards-up">
            <div class="card-inner">
                <h1>Stacked-Up</h1>
                <h3 class="card-title">GeeksforGeeks</h3>
                <div class="card-body">
                    A Complete Portal for Geeks.
                </div>
            </div>
        </div>
    </div>
    <div class="card-container">
        <div class="card cards-right">
            <div class="card-inner">
                <h1>Stacked-Right</h1>
                <h3 class="card-title">GeeksforGeeks</h3>
                <div class="card-body">
                    A Complete Portal for Geeks.
                </div>
            </div>
        </div>
    </div>
</body>

</html>

Output:



Next Article

Similar Reads