Cards, Lists, and Media Objects

Introduction

Cards, lists, and media-object patterns appear in almost every modern UI: feeds, dashboards, profiles, search results, and settings pages. The goal is not just visual polish, but reusable structure, consistent spacing, and responsive behavior. This chapter covers practical CSS patterns you can apply across many product interfaces.

Prerequisites

  • Basic Flexbox/Grid knowledge
  • Box model and spacing fundamentals
  • Responsive sizing and media handling basics

Design Goals for Reusable Components

For repeatable UI blocks, aim for:

  • consistent spacing scale
  • predictable typography hierarchy
  • flexible media behavior
  • clear hover/focus interaction feedback
  • simple variant extension

Reusable patterns reduce CSS duplication and maintenance cost.

Card Component Basics

A solid base card:

css
.card {
  display: grid;
  gap: 0.75rem;
  padding: 1rem;
  border: 1px solid #e2e8f0;
  border-radius: 12px;
  background: #ffffff;
  box-shadow: 0 4px 12px rgba(15, 23, 42, 0.06);
}

Code explanation:

  • display: grid + gap gives clean internal spacing
  • border + soft shadow provides subtle separation
  • radius and padding create a modern, readable surface

This is a good default for many product cards.

Keep these subregions explicit so variant cards stay predictable.

Interactive Card States

Code explanation:

  • hover adds subtle lift
  • :focus-within helps keyboard users track active card context

Avoid turning every card into an aggressive animated component.

Card Grid Layout

css
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1rem;
}

This creates responsive card columns with minimal breakpoint code.

List Styling Fundamentals

Default list styling is semantic but often needs visual tuning.

css
.list {
  margin: 0;
  padding: 0;
  list-style: none;
}
 
.list > li {
  padding: 0.75rem 0;
  border-bottom: 1px solid #e2e8f0;
}

Code explanation:

  • removes browser default spacing/bullets
  • applies consistent item rhythm and separators

If bullets/numbering are meaningful content, keep native semantics and style markers instead of removing them.

Marker Styling for Semantic Lists

css
.article-list li::marker {
  color: #2563eb;
}

This keeps list semantics while aligning visual brand language.

Compact vs Comfortable List Density

css
.list--compact > li {
  padding-block: 0.4rem;
}
 
.list--comfortable > li {
  padding-block: 0.9rem;
}

Density variants help reuse one list structure in admin tables, feeds, and mobile menus.

Media Object Pattern

A classic media object pairs fixed media with flexible content.

Code explanation:

  • fixed thumbnail width keeps visual consistency
  • flexible body fills remaining space
  • min-width: 0 prevents long text overflow issues

This pattern is ideal for comments, chat previews, notifications, and result rows.

Media Object with Actions

Useful for placing timestamps, tags, and contextual buttons cleanly.

Text Truncation in Cards/Lists

css
.truncate-1 {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

Use this for titles in dense UI where vertical expansion is undesirable.

For longer previews, prefer natural wrapping or controlled line-clamp strategy based on context.

Variant Strategy and Naming

Keep naming consistent:

  • base: .card
  • variants: .card--interactive, .card--featured
  • parts: .card__header, .card__body

Avoid deeply nested selectors tied to fragile DOM structure.

Clear naming is more maintainable than complex selector logic.

Tip

Build Reusable Primitives

A few strong primitives (card, list, media object) can power most UI screens with minor variants.

Responsive Adaptation

Media object can switch to stacked layout on very narrow widths:

css
@media (max-width: 420px) {
  .media {
    flex-direction: column;
  }
 
  .media__thumb {
    width: 100%;
    max-width: 220px;
  }
}

This prevents cramped horizontal layouts on small phones.

Common Mistakes

MistakeWhy it hurtsBetter approach
Building unique CSS for every cardRepetition and inconsistencyUse shared card base + small variants
Removing list semantics everywhereAccessibility and structure lossKeep semantic lists when content is list-like
No min-width: 0 in media bodyText overflow in flex rowsAdd explicit shrink allowance
Overly heavy shadows on all cardsVisual noise/perf costKeep subtle elevation scale
Fixed thumbnail sizes without responsive fallbackLayout break on narrow screensAdd mobile stacking/size rules

Debugging Tips

When cards/lists/media rows look broken:

  1. inspect spacing layers (padding, gap, margin)
  2. verify list semantics and marker behavior
  3. check flex item shrink behavior (min-width)
  4. test long title/description overflow
  5. test narrow viewport for wrapping and interaction target size

Component stress-testing with long content catches most edge cases early.

Mini Exercise

  1. Build a card grid with 6 items using auto-fit/minmax
  2. Add interactive hover + focus-within states
  3. Build a semantic list with custom marker styling
  4. Build a media-object notification list with avatar + text + meta
  5. Add long-title test data and fix overflow cleanly
  6. Verify responsive behavior at phone/tablet/desktop widths

FAQ

Should every card have a shadow?

Not necessarily. Use shadow/elevation intentionally based on hierarchy and interaction importance.

Is it okay to remove ul bullets?

Yes for UI lists (menus, settings rows) if semantics remain intact. For article content lists, markers are often meaningful.

Why do media-object text columns overflow?

Flex children can resist shrinking. Adding min-width: 0 on the content column usually fixes this.

Should I use Grid or Flex for card internals?

Either can work. Grid + gap is often clean for vertical card structure; Flex is great for one-axis header/footer alignment.

How do I avoid too many card variants?

Start with one strong base and add only meaningful modifier classes tied to actual product states or hierarchy.