DEV Community

Cover image for Making a Card Component With BEM
Christopher Satterthwaite
Christopher Satterthwaite

Posted on

Making a Card Component With BEM

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

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 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 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>
Enter fullscreen mode Exit fullscreen mode
  1. 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>

Enter fullscreen mode Exit fullscreen mode
  1. 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>

Enter fullscreen mode Exit fullscreen mode

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.

  1. 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.

  2. 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>
Enter fullscreen mode Exit fullscreen mode
  1. 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;
}
Enter fullscreen mode Exit fullscreen mode

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.

  1. 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;
}
Enter fullscreen mode Exit fullscreen mode

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.

  1. 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 {
}
Enter fullscreen mode Exit fullscreen mode
  1. 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.

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

Basic Card

  1. 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;
}
Enter fullscreen mode Exit fullscreen mode

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.

  1. 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>

Enter fullscreen mode Exit fullscreen mode

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

Card With Image

  1. 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;
}
Enter fullscreen mode Exit fullscreen mode

You should now have something that looks similar to this;

Card With Action Butto

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);
}
Enter fullscreen mode Exit fullscreen mode

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>

Enter fullscreen mode Exit fullscreen mode

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

Card With Modifiers

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.

Top comments (0)