Hover Cards

Introduction

I often find myself in a position where I want to code, but I don't have a project I am working on or want to start. I have also always wanted to try my hand at blogging. The idea is simple (original? probably not), I go on Dribbble, find something that I think looks cool, and build it using react or whatever framework/tech stack I feel like (with some design liberties - I don't make graphics, and I eyeball colors). Then in the post, I will explain how I did it and show some code. Sounds fun. So, I am going to give it a try. My main goals for this are to:

  1. Work on technical communication and explanation
  2. Work on my writing abilites
  3. Have some fun building some things I have seen online

Hover Card

I went on Dribbble, and I found this, a neat little hovercard design. The main thing with this design is the hover effect on each of the card component. There are a couple of other things there, mainly layout and different fonts, but I would like to focus on the hover.

For this, we can build out two different components:

  • The Card component
  • A CardList component

The first one is where the majority of our work will be. The second is the container that will feed data to each of our cards and lay out the cards.

The card structure is pretty simple; there are 3 things: an icon, a title, and a description. For now, we can hardcode a couple of values for the title and description and put a div in for the icon.

<div className="card">
<div className="icon"></div>
<div>
<h4>San Fransisco</h4>
<p>The beating tech heart of California</p>
</div>
</div>

Now it's time to style. There aren't any sizes on the Dribbble post that I am aware of, so it's time to begin taking civil liberties. Let's pick a size that looks good on our screen and a background color that looks similar. Additionally, let's add some styling to the icon div. This will be the full extent of the icon styling we will do (I can't make those icons! I mean, did you look at them? They're incredible). After adding some border-radius, our Card looks like this.

.card {
height: 300px;
width: 200px;
background-color: #ccc;
border-radius: 10px;
background-color: #f5f5f5;
}

San Fransisco

The beating tech heart of California

Close, but our layout and spacing are a tad wonky. We can fix the card's layout using flexbox, and we can fix our spacing up while we're at it. We want the flex-direction to be column and to set "justify-content" to space around. This will push our data to the top and bottom of the card. Now our card is looking much more like the picture.

.card {
...
border-radius: 10px;
padding: 16px;
display: flex;
justify-content: space-between;
flex-direction: column;
}

San Fransisco

The beating tech heart of California

Now comes the interesting part, animating the card. We can achieve this by using the hover CSS selector. The hover selector allows us to define the div's behavior when the mouse hovers over it. So what do we want the div to do? We want it to:

  • add a shadow
  • change the background color
  • change the text color to white
  • slide the div up

Adding a shadow can be accomplished using box-shadow CSS property; it can be a tad finicky to use if you are unfamiliar with it, but the docs on MDN are good, and there are plenty of online 'box-shadow-generators.' Changing the background color is a tad harder since we have to change it to a gradient. Adding a background gradient is best accomplished using the linear-gradient CSS function. Changing the text color to white simple, thanks to the color property. All of these can be added to the hover-block in our CSS.

Next comes perhaps the most complex part of the animation, the sliding up. To slide the div up, we will be taking advantage of the top property. If you look at w3Schools, you'll find, the top property affects the vertical position of a positioned element, and the top property does not affect non-positioned elements. It also notes that if the position is static, this property does nothing. This means we have to adjust our card class since, by default, all divs are position static. Our best option is to set the position property to relative. A relative positioning means the top property makes the element's top edge move above/below its normal position, which is exactly what we want. Using this, we can define our initial top on the card class and the top we want to animate to in the hover-block. Now, this is what we have.

San Fransisco

The beating tech heart of California

It works... but it's not perfect. it's abrupt and hard to look at. It just jumps. But why? Well, because we haven't added any CSS-transitions. CSS transitions allow you to change property values smoothly over a given duration. We need it in two places - animating in and out. Using the transition property, we can define the behavior of some properties or all. For this, we will animate all the same. Putting in the transitions into the hover-block allows us to animate in smoothly, but once we leave the hover, the jumping behavior is back. To have the animation run to the return state, we need to add a transition to the base card class. Just like that, we have a good looking card component.

San Fransisco

The beating tech heart of California

Great! So what's next? Well, we have one good looking card component, but we need four cards (I'm choosing to do four instead of five for responsive reasons). First, we need to remove the hardcoded data and replace it with values passed into the component's props. Then we need to create a data source to generate our cards.

const data = [
{
title: "San Fransisco",
description: "The beating tech heart of California",
},
{
title: "New York",
description: "A city that avoid labeling or description",
},
{
title: "Toronto",
description: "The cold never bothered us anyway",
},
{
title: "Remote",
description: "We have offices in over 25 different countries",
},
]

Once that's done, we need to create a list component that feeds the card component the correct data and lays them out. We can also put the upper text above the list in this component to make the design complete. All we need to do is add the text about the card container, add some styles to it, and then have the component all complete and ready to use.

<div className="container">
<div className="hover-container spaced">
<div className="spaced">
<h2>Fly anywhere</h2>
<h1>Work everywhere</h1>
</div>
<div className="spaced text">
<p>
Its a certain type of freedom when you can slam you laptop shut in cold
Toronto and pop it back open in warm karachi the next day .
</p>
<p>
Your already connected with the world. The space you physically occupy
matters less and less.
</p>
</div>
</div>
<div className="hover-container">
{data.map((office, index) => (
<Card office={office} key={index} />
))}
</div>
</div>

To layout the cards, we will again take advantage of css grid. Using the repeat function we can define 4 columns and layout the text and title using grid-template-areas.

To make this responsive you can add media queries and redefine the grid tempate areas

.title {
grid-area: title;
}
.text {
grid-area: text;
}
.hover-container {
grid-template-columns: repeat(4, 1fr);
grid-template-areas: "title title text text";
max-width: 1330px;
}
}

And there we have it. A fun little list of hover cards!

Fly anywhere

Work everywhere

Its a certain type of freedom when you can slam you laptop shut in cold Toronto and pop it back open in warm karachi the next day.

Your already connected with the world. The space you physically occupy matters less and less.

San Fransisco

The beating tech heart of California

New York

A city that avoid labeling or description

Toronto

The cold never bothered us anyway

Remote

We have offices in over 25 different countries