The first time I realized the power of “object-oriented” CSS (OOCSS) was when I read Nicole Sullivan’s The media object saves hundreds of lines of code. Since then, the media object has been a part of developing nearly every site I have touched.

For those who may not be familiar: The media object is a great example of OOCSS’ best qualities. It’s a small set of classes that make up one object/component that does one job and does that one job very well. It’s a small building block that, in Nicole’s Facebook example, makes up about 80% of the site’s layout. With this small number of classes, you can add/change/remove theming classes without affecting the layout, making for great re-usability and maintainability. If you haven’t already, I suggest reading Nicole’s original article before proceeding.

As much as I appreciate Nicole’s awesome work in creating this wonderful little abstraction, I think the original code can be improved for more flexibility at little-to-no cost on the way we mark it up.

The One That Started It All

Here’s a simplification of the original media object that we’ll reference:

smarterchild

Talking about dogs is a lot of fun.

@Smarterchild 8 years ago

The Weaknesses

The potential issues I want to point out and try to improve:

  1. The .img class defeats the purpose of calling it the “media” object. Media means, as Nicole explains in her article, “… is a tiny icon, a large video, or an avatar, but it is the same basic object”.
  2. The .bd class is clearly shorthand for “body” but without context it is impossible to know what its job is. It would be fine if it was designed to be a standalone class but I think it’s too closely tied to the media object. making it a sub-component and should be labeled as such.
  3. The .img class here is being applied to an anchor, which removes a little flexibility in the case that you may want to add some kind of caption or any other text underneath/above the image.

My Proposed solution

My solution to the first two issues would be to use a BEM-like naming convention and label these subcomponents under a “media” namespace since they’re not designed to be used outside of the media object. And instead of using “img” I think .media__item is most suitable, allowing for any type of media to exist in that element.

/* indented to reflect DOM structure */
.media {}
  .media__item {}
  .media__body {}

The third issue here is almost a non-issue thanks to the power of OOCSS techniques. Nicole’s example has her media item marked up on an anchor. I asked what if you wanted to add a caption to the image. An easy solution would be to add the .media__item class to a div wrapping the content that contains the image and the caption. The problem was never a problem after all, however, I propose that the media item always be wrapped in a generic div. This will maintain consistency and gives that div one job to do well — containing the media item and it’s related content. It may also prevent future bugs if you were to extend the media item with padding it may result in undesirable behavior if it were on an anchor for example.

Here’s where this leaves us:

/* indented to reflect DOM structure */
.media {
  overflow: hidden;
}
.media__item {
  float: left;
  margin-right: $base-spacing-unit;
}
// In it's basic form .media__body does not require any styles. It comes in handy when extending for modifications of the media object.

Lorizzle ipsum dolizzle get down get down amizzle, dang adipiscing elit. Nullam doggy velizzle, away volutpizzle, suscipit , shut the shizzle up vizzle, away.

Extending The Media Object

The strengths of this markup are even more recognizable with examples of extending the media object. By adding one additional class to <div class="media"> you can modify the way this media+text abstraction is laid out. Here are some examples:

// FLIPPED
.media--flip > .media__item {
  margin-right: 0; // resetting the default right margin
  margin-left: $base-spacing-unit;
  float: right;
}

// STACKED
.media--stack > .media__item {
  float: none;
  margin-left: 0;
  margin-bottom: $base-spacing-unit;
}

// NOWRAP
.media--nowrap > .media__body {
  overflow: hidden;
  // this property doesn't allow text to wrap around the floated image.
}

// VALIGN (aka "FLAG")
.media--valign {
  display: table;
}
.media--valign > .media__item,
.media--valign > .media__body {
  display: table-cell;
  vertical-align: middle;
}
.media--valign > .media__item { float: none; }
.media--valign > .media__body { width: 100%; }

Credit to the .valign class goes to Harry Robert’s “Flag Object” that I’ve made as an extension to media – strengthening the case for this pattern. You add one extension class to your media object to modify it’s layout while still staying within the idea of an image+text abstraction. Also massive thanks to @danofpaco & @apticknor for their excellent teaching on some of these OOCSS techniques I was taught early on.