Making a Card Component With BEM
Tags: webdev, css, html, beginners
Published: 2022-10-04 01:48:32

In this tutorial, I'll show you how to make a simple card component for your next project using the BEM naming mythology.

## What is a Card?

One of the most used components on any website I've worked on is the card component. Primarily used to group various pieces of content into a container like blog posts, projects, or even products. 

## Let's Get Started

First, look at what we are building to visualize the code we will write.

![Card Example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ezfwyf8zir4v0id6png.png)

With the simple example above, we will now identify the parts we will work with to create the HTML markup. I came up with the following, but depending on your design, it can be more complex.

### Parts of my card;
 
1. Card Body
2. Card Image
3. Card Title
4. Card Subtitle
5. Card Excerpt
6. Card Action

## Identify The Card Parts

Now that we know the parts of the card, it will be beneficial to determine what parts they are and what they will be called. For this example, I'll be breaking the elements out into layout and components parts. 

### Card Layout BEM Names

**c-card**
The wrapper of the whole card. This is usually a **`<article>`** tag for SEO purposes and semantics, but you can also get away with just a **`<div>`**. 

**c-card__header**
Contains the Image, Title, or Subtitle. We will use the **`<header>`** tag to ensure everything is semantic and valid.

**c-card__body**
Contains the Title, Subtitle, or Excerpt. We will use a **`<div>`** for this part. There is no read HTML element for this use.

**c-card__footer**
Contains the action button. This will use the **`<footer>`** tag to keep everything nice and semantic with the **`<article>`** specifications.

### Card Component BEM Names

**c-card__image**
I like the image used by the card to make a background image, so it's easier to display.

**c-card__heading**
Usually wrapped in an `**<H2>**` tag for semantics and to stick with the **<article>** tags spec, the title can also be made a **`<div>`** or a **`<span>`**. 

**c-card__sub-heading**
We will use a **`<div>`** tag. There is no real need for us and heading tags.

**c-card__excerpt**
The **`<p>`** tag will be used to wrap this part. Again, you can get away with a **`<div>`** but semantics.

**5. c-card__action**
the action will hold our **`<button>`**. We will use a **`<div>`** tag here.

## Start Writing The Code

1. let's start by opening up your editor. I'll use [Visual Studio Code](https://visualstudio.microsoft.com/) for this tutorial.

Create an index.html file and open it up. Let's put the basic coded need for the HTML to render. Place the following code in your index.html;

```
<!DOCTYPE html>
   <html lang="en-us">
   <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
   </head>
   <body>
   </body>
</html>
```

2. With the index.html file open, let's add the following code to create the card markup.

```
<article>
   <header>
      <div></div>
      <h2>Card Headline Here</h2>
      <div>Card Subtitle Here</div>
   </header>
   <div>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit,    sed do eiusmod tempor incididunt ut labore...</p>
   </div>
   <footer>
      <div>
         <button>Read Full Post</button>
      </div>
   </footer>
</article>

```
3. Now that we have our markup, it is time to add the BEM class names we came up with earlier.

```
<article class="c-card">
   <header class="c-card__header">
      <div class="c-card__image"></div>
      <h2 class="c-card__heading">Card Headline Here</h2>
      <div class="c-card__sub-heading">Card Subtitle Here</div>
   </header>
   <div class="c-card__body">
      <p class="c-card__excerpt">Lorem ipsum dolor sit amet, consectetur adipiscing elit,    sed do eiusmod tempor incididunt ut labore...</p>
   </div>
   <footer class="c-card__footer">
      <div class="c-card__action">
         <button class="c-button">Read Full Post</button>
      </div>
   </footer>
</article>

```
You might note that the button is its own component and not part of the card component. I do this to make my code easy to reuse.

4. Now that our HTML is marked up and ready to go, it's time for the CSS. I'll just be using plain CSS in this example, but I recommend using SASS as it makes the job much easier.

5. To Keep this simple, we will inline the CSS. Between the **`<head></head>`** tags add the **`<style></style>`** tags;
```
<!DOCTYPE html>
   <html lang="en-us">
   <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />

   <style>Inline CSS Will Go Here</style>

   </head>
   <body>
   </body>
</html>
```
6. Let's start with the c-card styles. Because we want this to be a component and reusable, the CSS for this layout part is quite simple;

```
.c-card {
   position: relative;
   width: 100%;
   color: #222222;
   background: #fafafa;
   transition: 0.4s ease-in-out;
}
```
Let's go over what I have. First, I always like to add position relative to my components, so the 0, 0 position is always their top left, not the sites. It makes future edits much more manageable. 

Next, I add 100%. Of course, you don't have to if you use a rest.css, but for me, it is just something standard. 

Now because I want his component to be used without modifiers for colors, I added default ones. 

And finally, we have the transition in case we want to add animation effects to the card later.

7. Next, let's create the Layout CSS. Below your .c-card styles, add the following code;

```
.c-card__header {
   position: relative;
   padding: 16px 16px 16px;
}

.c-card__body {
   position: relative;
   padding: 16px 16px 16px;
}

.c-card__footer {
   position: relative;
   padding: 16px 16px 16px;
   border-top: 1px solid #e7e7e7;
}
```
The layout parts are what I use to give the card padding. This gives you more flexibility to move them around or not even include them. Again you will note I added position relative just for future flexibility.

8. Next, let's style the components. Create the following code;
```
.c-card__image {
}

.c-card__heading {
   margin: 0;
   padding: 0;
   font-size: 28px;
   font-family: "Lato";
   line-height: 1.2;
}

.c-card__sub-heading {
   font-size: 18px;
   font-family: "Lato";
   line-height: 1.2;
}

.c-card__excerpt {
   margin: 0;
   padding: 0;
   font-size: 18px;
   font-family: "Lato";
   line-height: 1.2;
}

.c-card__action {
}
```
9. You're going to note the margin and padding set to 0 on the .c-card__heading and .c-card__excerpt. I like making the line height do the work vs. margin and padding. The other styles for fonts are our defaults and can be overridden by modifiers later.

10. If you preview your file, you should now have something like 
this;

![Basic Card](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bg9yk2vebf1scvy0x5us.png)

11. Now, let's look at adding the image to the card. I prefer to set the picture as a background image to avoid resizing it and make it easier later on to animate. Let's add the following styles to the image CSS;

```
.c-card__image {
   margin: 0 0 16px 0;
   background-size: cover;
   background-repeat: no-repeat;
   aspect-ratio: 4 / 3;
}
```
You will note I am using the aspect ratio style instead of providing a width or height. Now that this style is fully supported, it gives us a more flexible way to manipulate the image. In addition, the margin is added to provide a bit of extra space.

12. Next, let's add the image to the HTML. I am going to just use a placeholder image from placeholder.com. Make sure it's a 4:3 ratio. You should end up with the following code;

```
<article class="c-card">
   <header class="c-card__header">
      <div class="c-card__image" style="background-image: url(https://via.placeholder.com/1024x768);"></div>
      <h2 class="c-card__heading">Card Headline Here</h2>
      <div class="c-card__sub-heading">Card Subtitle Here</div>
   </header>
   <div class="c-card__body">
      <p class="c-card__excerpt">Lorem ipsum dolor sit amet, consectetur adipiscing elit,    sed do eiusmod tempor incididunt ut labore...</p>
   </div>
   <footer class="c-card__footer">
      <div class="c-card__action">
         <button class="c-button">Read Full Post</button>
      </div>
   </footer>
</article>

```
You Should now have something similar to this when you preview your HTML file.

![Card With Image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pmnlsaa3oghnqqxjembo.png)

13. We are almost done with the base card component. We just have one more step left, and that's to add styles to the c-card__action component. For example, add the following code to align the button to the right and center align it.

```
.c-card__action {
   display: flex;
   justify-content: flex-end;
   align-items: center;
}
```
You should now have something that looks similar to this;

![Card With Action Butto](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hawfy1sfutdsrwe1w7a9.png)

## Adding Modifiers
Now that we have our base card ready to go, it's time for us to create some modifiers. Modifiers can be used for many things, such as changing Color, Font sizes, widths, add animations.

1. let's start with creating modifiers for rounded corners and drop shadows. Add the following CSS to your index.html file;

```
.c-card--rounded {
   border-radius:  0.375rem;
}

.c-card--elevation {
   box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.3), 0px 2px 6px 2px rgba(0, 0, 0, 0.15);
}
```
We have created 2 modifiers, one for rounded corners and one for the drop shadow. Let's add them to our code. You should end up with something like this;

```
<article class=""c-card c-card--rounded c-card--elevation"">
   <header class="c-card__header">
      <div class="c-card__image" style="background-image: url(https://via.placeholder.com/1024x768);"></div>
      <h2 class="c-card__heading">Card Headline Here</h2>
      <div class="c-card__sub-heading">Card Subtitle Here</div>
   </header>
   <div class="c-card__body">
      <p class="c-card__excerpt">Lorem ipsum dolor sit amet, consectetur adipiscing elit,    sed do eiusmod tempor incididunt ut labore...</p>
   </div>
   <footer class="c-card__footer">
      <div class="c-card__action">
         <button class="c-button">Read Full Post</button>
      </div>
   </footer>
</article>

```
Let's preview our index.html file. You should have something like this;

![Card With Modifiers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zkkugk3rf88bp5hc4he6.png)

That's really it. You can add more modifiers, like making the image full width by adding a negative margin to the image component or adding animation effects to the drop shadow. It's really up to you.

## Conclusion
Building components is one of my favorite things to do as a developer, and there are many advantages to this theme style. It's essential to think through how components will be used so you can plan ahead on how to best build a component that can be reused. 

Rushing through building components without understanding where and how a component may be used can lead to duplicating code or redoing your work to accommodate new project requirements.

If you like to mess around with the code or use the card component, You can download the working file from [my gist here](https://gist.github.com/gijinkakun/d20e2f2c4f8498eedb6bc12dfa460380).