Tutorial - Creating a Responsive Credit Card in HTML/CSS

NicolasBrondinBernard

Author
@NicolasBrondinBernard

Discover CSS concepts by recreating this credit card through a detailed tutorial.

Article published on 18/06/2021, last updated on 10/08/2026

Here's a simple little tutorial to improve your HTML/CSS skills, in which I invite you to recreate a responsive and animated credit card.

Note that the tutorial does not follow the DRY (Don't Repeat Yourself) principle, in order to keep the code blocks clear and detachable from one another.

You'll find all the necessary code in the article, but I invite you to grab the whole project directly on GitHub, where you'll find the images as well as all the steps, broken down file by file.

And a demo of the final result right here: https://nicolasbrondin.github.io/tutorial-css-credit-card/

Step 0: The background

Creating a somewhat elaborate background like this one doesn't require huge knowledge, and you can go find a gradient that you apply to your html document, as well as a pattern that you apply to the body of your page.

Personally, I used Hero Pattern for the pattern and UI Gradient for the gradient.

HTML

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <title>Tutorial - Credit Card</title>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
    <link rel='stylesheet' type='text/css' media='screen' href='./css/main.css'>
  </head>
  <body>
    
  </body>
</html>

CSS

html {
  background: #009FFF;  /* fallback for old browsers */
  background: -webkit-linear-gradient(to right, #ec2F4B, #009FFF);  /* Chrome 10-25, Safari 5.1-6 */
  background: linear-gradient(to right, #ec2F4B, #009FFF); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
}

body {
  width: 100vw;
  height: 100vh;
  background-image: url('../img/graph-paper.svg');
  background-repeat: repeat;
  padding: 20px;
  box-sizing: border-box;
  margin: 0;
}

Step 1: The shape of the card

Two interesting techniques here: using flex-box to easily center our card, as well as using padding-top in percentage to always keep the same ratio for our card.

When you apply a percentage size to a padding-top, the size will be calculated based on the width of the element and not its height, which is why this makes it easy to maintain a ratio.

HTML

<div class="card-container">
  <div class="card">
        
  </div>
</div>
body {
  ...
  display: flex;
  justify-content: center;
  align-items: center;
}

.card-container {
  background: #34495e;
  border-radius: 20px;
  width: 100%;
  max-width: 600px;
  position: relative;
  box-shadow: 0px 0px 10px 5px rgba(0,0,0,0.1); 
  border-bottom: 6px solid #2c3e50;
  border-right: 6px solid #2c3e50;
}

.card {
  position: relative;
  padding-top: 60%;
  overflow: hidden;
}

Step 2: The images

Nothing complex in this step: adding, resizing and positioning the images with percentage values to prepare for responsiveness.

HTML

<img class="chip" src="./img/chip.svg"/>
<img class="contactless" src="./img/wifi-signal.svg"/>
<img class="visa"src="./img/visa.svg"/>

CSS

.chip {
  position: absolute;
  top: 35%;
  left: 5%;
  height: 23%;
}

.contactless {
  position: absolute;
  top: 40%;
  left: 20%;
  height: 15%;
  transform: rotate(90deg);
}

.visa {
  position: absolute;
  bottom: 5%;
  right: 5%;
  height: 30%;
}

Step 3: The 16 digits

Here, using the "text-shadow" property makes the text stand out and gives a volume effect, just like on a real credit card.

HTML

<p class="card-number">0000 0000 0000 0000</p>

CSS

.card-number {
  position: absolute;
  top: 50%;
  left: 5%;
  font-size: 2.5rem;
  font-family: sans-serif;
  color: white;
  text-shadow: 0px 0px 5px black;
}

Step 4: The arrow

Why go looking for an icon when you can directly draw a triangle in CSS using the borders technique?

Note that there are also generators for creating these famous CSS triangles if you want to go faster.

HTML

<div class="arrow"></div>

CSS

.arrow {
  position: absolute;
  top: 80%;
  left: 5%;
  width: 0; 
  height: 0; 
  border-top: 20px solid transparent;
  border-bottom: 20px solid transparent; 
  border-right:17px solid white; 
}

Step 5: The additional information

Here we use the "text-transform" property with the "uppercase" value in order to switch the entire text to capital letters, directly in the CSS, which is very handy!

HTML

<p class="card-name">M John Doe</p>
<p class="card-expire">Expire 05/23</p>

CSS

.card-name, .card-expire {
  position: absolute;
  left: 10%;
  font-family: sans-serif;
  color: white;
  text-transform: uppercase;
  text-shadow: 0px 0px 3px black;
}

.card-name {
  top: 74%;
  font-size: 1.3rem;
}

.card-expire {
  top: 82%;
  font-size: 1rem;
}

Step 6: The bank

Switching a text's display from "inline" to "inline-block" means that the text will only take up the space it needs, without stretching infinitely horizontally.

HTML

<p class="bank-name">Bank 1337</p>

CSS

.bank-name {
  margin: 0;
  display: inline-block;
  padding: 10px 20px;
  padding-left: 5%;
  position: absolute;
  top: 10%;
  left: 0;
  font-size: 1.5rem;
  font-family: sans-serif;
  color: black;
  font-weight: bold;
  background-color: white;
  min-width: 30%;
  border-top-right-radius: 50px;
  border-bottom-right-radius: 50px;
}

Step 7: The decorations

The ideal approach when you want to draw something that adds no semantic meaning to your page is to use the "::before" and "::after" pseudo-elements.

These are "virtual" elements, which only exist if you declare them in CSS; they will then be attached to your starting element (in this example, the card).

CSS


.card::before {
  content: "";
  position: absolute;
  display: inline-block;
  background-color: white;
  width: 50%;
  height: 5%;
  left: 0;
  top: 26%;
  border-top-right-radius: 50px;
  border-bottom-right-radius: 50px;
  opacity: 0.5;
}

.card::after {
  content: "";
  position: absolute;
  display: block;
  background-color: white;
  width: 200px;
  height: 200px;
  right: -75px;
  top:-75px;
  border-radius: 50%;
  opacity: 0.05;
}

Step 8: The animation

A very simple method for animating an element is to modify some of its attributes on an event (for example :hover) and to apply a transition animation to the element as a whole.

Here we play with zoom, rotation and box-shadow to create a levitation effect.

CSS

.card-container {
  ...
  transition: 0.5s transform, 0.5s box-shadow;
}

.card-container:hover {
  transform: scale(1.1) rotate(3deg);
  box-shadow: 10px 10px 10px 5px rgba(0,0,0,0.3); 
}

Step 9: Responsiveness

Most of our design is nearly responsive, but a few elements (particularly the texts) need a bit of help for smaller screen sizes.

Since we used sizes in rem, we can simply vary the size of all the fonts by modifying that of the :root element, as below:

CSS

@media screen and (max-width: 580px){
  :root {
    font-size: 12px;
  }
  .bank-name {
    padding: 8px 15px;
  }
  .arrow {
    border-top: 18px solid transparent;
    border-bottom: 18px solid transparent; 
    border-right:15px solid white; 
  }
}

@media screen and (max-width: 460px){
  :root {
    font-size: 10px;
  }
  .bank-name {
    padding: 5px 12px;
  }
  .arrow {
    border-top: 13px solid transparent;
    border-bottom: 13px solid transparent; 
    border-right:11px solid white; 
  }
}

@media screen and (max-width: 360px){
  :root {
    font-size: 8px;
  }

  .card-container {
    border-bottom: 3px solid #2c3e50;
    border-right: 3px solid #2c3e50;
  }

  .bank-name {
    padding: 3px 8px;
  }

  .arrow {
    border-top: 10px solid transparent;
    border-bottom: 10px sol

Finished reading this article?
Our newsletter

No spam. Only free content, news, and ever more resources to level up your skills!

Join +1500 developers

Comments (0)

to leave a comment

No comments yet