Cool Scrolling Cards with HTML 5 and CSS

Spread the love

I read a lot on web. Be it articles, source code, tips-n-tricks and what not. In fact, if I like a site, I also jump through the HTML source code and try to figure out how a particular effect has been achieved. is one of those sites, which I often visit. The site has tons of information on various aspects of CSS / Design. Apart from the articles, the site is beautifully designed and one thing which particularly caught my attention is the list of articles on front page.

Here is the quick preview of the what I saw on The information is nicely presented and the animation looks very subtle.

Naturally, I had a curiosity to peek into the source code and understand the magic behind this cool component. The cards are initially stacked (horizontally) on one another. As soon as you move a mouse over any of the card, it simply comes on top. In this article, I will walk you through the steps to achieve this awesome card effect.


The html part is pretty simple. We create container to hold all the cards. Each individual card is then designed to hold information like article title, author name, date and tags.

<div class="card-container">
        <div class="card">
            <header class="article-header">
                    <div class="category-title">
                        <span class="date">Jan 19, 2020</span>
                <h2 class="article-title">
                    Custom Theme with Angular Material
            <div class="author">
                <div class="profile"></div>
                <div class="info">
                    <div class="caption">Author</div>
                    <div class="name">David Hose</div>
            <div class="tags">
        <!-- repeat the card here. -->
        <div class="card">

You will notice that everything is wrapped inside div and each component has its own class identifier.


We then move on to defining styles for our page. Lets begin with setting some global styles to ensure we have consistent widh, height and font.

Global Style

* {
        box-sizing: border-box;

    body {
        padding: 0;
        margin: 0;
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        color: #fff;

We ensure that all the elements have box-sizing as border box. The body style ensure there are no unnecessary padding and margin and the font is set to Segoe UI.

Card Container

In my example, I have set the card with to 1000 px, but you can change it as per your own requirement.

.card-container {
        width: 1000px;
        overflow-x: scroll;
        display: flex;
        background-color: #100e17;
        padding: 3rem;

Since the cards should be horizontally aligned one after the other, I am using Flex layout with default direction of row. Check the overflow-x property has been set to scroll. This will display scrollbars to view additional cards which won’t fit into the initial view.


Time to define style for individual card. Once again we use flex layout but this time with a direction of column.

.card {
        min-width: 300px;
        height: 350px;
        border-radius: 16px;
        background-color: #17141d;
        box-shadow: -1rem 0 3rem #000;
        display: flex;
        flex-direction: column;
        padding: 1.5rem;
        transition: 0.2s;

The minimum width has been set to 300px. Using min-width attribute is necessary with Flex layout, otherwise your card will be shrinked to fit. We also set height to 350px to ensure all the cards have consistent height. Rest of the attributes are required to make div look like card. Also take a note of transition attribute. One may argue that transition without specifying target property is not good from performance perspective. The argument is valid, but we are using this example for demonstration purpose, you can very well customize it as per your own requirement.

Card Element Style

Alright, looks like our card is in shape. Lets go ahead and style rest of the components.

.date {
        color: #8a8a8a;

    .tags {
        display: flex;
        flex-wrap: wrap;
        margin: 1rem 0 1rem;

    .tags div {
        font-size: 9px;
        font-weight: 700;
        padding: 4px 10px;
        border: 3px solid #28242f;
        border-radius: 2rem;

    .card .category-title {
        font-size: 14px;
        color: #fff;
        margin-bottom: 1rem;

    .card .article-title {
        font-size: 20px;
        font-weight: 700;

    .card .article-header {
        margin-bottom: auto;

    .card .author {
        margin-top: 3rem;
        display: grid;
        grid-template-columns: 75px 1fr;

    .author .info .caption {
        color: #8a8a8a;

Add the above style definitions and you will see that our cards now look much better. (I have repeated card element multiple times)

Lets make these card overlap each other, by defining following style definition.

.card:not(:first-child) {
        margin-left: -130px;

The trick is to move all the cards to its left (except first card) by 130px. This will give a nice overlapping effect.


Now comes the real part. As soon as user moves mouse over any of the card, we need to ensure that it moves upward. Refer to below style which uses :hover pseudo selector to achieve the desired result.

.card:hover {
        transform: translateY(-1rem);

That was pretty easy!!! But there is one problem. Our card is still sitting behind the next card. The contents of the card are not visible entirely. This can be easily be fixed using ~ selector and by ensuring that the next sibling should move from its original x axis by certain pixels.

    transform: translateX(130px);

And you must now have a cool looking stack of cards.

See the Pen Cools CSS animated card on CodePen 1