Pattern Build: CodePen Card

by Drew Barontini

In this new Pattern Build series, we’re going to pick a pattern on the web and write modular, responsive, and reusable HTML and CSS for the particular pattern. This week, we’re going to recreate the cards seen on CodePen.

CodePen Cards

And to get extra meta, we’re going to use CodePen to build it out. Whoa now! Let’s get going.

See the Pen Pattern Build: CodePen Card by Drew Barontini (@drewbarontini) on CodePen.

Here’s a final version of the pattern.

Writing the markup

Let’s start with the markup. Specifically, let’s just generically write out what the element is composed of. That’s a good way to get started on naming things.

  • A media image
  • The title of the pen
  • The author information, which has an avatar and their name
  • Stats about the pen (views, comments, loves)

CodePen Card

Okay, now we can start laying out our markup:


    %img.card-media-img(src='...' alt='' width='370' height='208')


      %a(href='#') My Pen Title


          %img.bucket-media(src='...' alt='' width='20' height='20')
          %h3.bucket-content.card-meta-author Author Name

            %a(href='#') 204
            %a(href='#') 12
            %a(href='#') 22

We’re using Haml here for brevity (and because I like it).

Okay, let’s talk about this since there are three different modules working together here. We have:

  • The card for all card-specific styling
  • The split for a Flexbox horizontal split of elements
  • The bucket for a Flexbox version of the media-element pattern (media element with content floated next to it, if you’re not familiar)

Styling the pattern

We’re using Sass, so we’ll set up some variables and helpers first:

// -------------------------------------
//   Variables
// -------------------------------------

$breakpoint: 400px
$darkGray: #191919
$mediumGray: #2f2f31
$lightGray: #999
$radius: 2px
$space: 20px

// -------------------------------------
//   Helpers
// -------------------------------------

=respond-to($val, $query: min-width, $media: screen)
  @media #{$media} and ($query: $val)

Next, we’ll lay down some base styles for root tags:

// -------------------------------------
//   Base
// -------------------------------------

  background-color: $darkGray
  color: $lightGray
  font-family: 'Montserrat'
  padding: $space

// ----- Headings ----- //

h1, h2, h3,
h4, h5, h6
  margin-bottom: $space * 0.25
  margin-top: 0

// ----- Lists ----- //

  list-style-type: none
  margin: 0
  padding: 0

// ----- Links ----- //

  color: $lightGray
  text-decoration: none
  transition: 0.2s ease-in-out

    color: #fff

// ----- Images ----- //

  height: auto
  max-width: 100%

These would be styles you’d most likely apply globally to all base HTML tags.

And now we’ll go through each of our three modules in turn.


As mentioned earlier, the bucket is a module that handles the media-element pattern. Since we’re all modern and fancy, we’ll use Flexbox for this pattern.

// -------------------------------------
//   Bucket
// -------------------------------------


    align-items: center
    display: flex

// ----- Content ----- //

  flex-grow: 1

// ----- Media ----- //

  flex-shrink: 1
  margin-right: $space * 0.5

  > img
    display: block

Notice the +respond-to mixin that we’re using to only have the Flexbox styling kick in at a certain breakpoint. We’re also using the flex-grow and flex-shrink properties to control how the individual elements size themselves.


The card-specific styles are pretty straightforward, and they look something like this:

// -------------------------------------
//   Card
// -------------------------------------

  background-color: $mediumGray
  border-radius: $radius
  margin: 0 auto // For demo display purposes
  padding: $space * 0.25
  max-width: 370px // For demo display purposes
  text-align: center

    text-align: left

// ----- Content ----- //

  padding: ($space * 0.75) ($space * 0.5) ($space * 0.25)

// ----- Shared ----- //

  display: block

  font-size: 12px


    display: flex

// ----- Meta: Author ----- //

  font-weight: normal
  margin-bottom: $space * 0.5

    margin-bottom: 0

// ----- Meta: Stat List: Item ----- //

  display: inline

  margin-right: $space * 0.5

// ----- Title ----- //

  font-size: 16px
  margin-bottom: $space * 0.75


This is a style pattern used for elements that sit at opposite ends on the same baseline.

// -------------------------------------
//   Split
// -------------------------------------

  display: block

    align-items: center
    display: flex

// ----- Cell ----- //


    flex-grow: 1

    flex-shrink: 0

Similar to the bucket, we’re using flex-grow and flex-shrink. Additionally, we have align-items: center on the flex parent to vertically center the elements.

That’s all, folks

Hopefully this is useful to demonstrate how even a small module or pattern can be broken down into multiple, reusable modules and patterns. When built this way, we can continue to grow a library of self-contained modules that can be ported and reused throughout a codebase. It helps keep a codebase lean and efficient.

If you can think of pattern you’d like to see built, send me a link on Twitter.