Small Tips for Styling Card Components
Tags: css, html, webdev, tutorial
Published: 2024-04-09 20:29:18

The other day, I stumbled upon an "About Us"-page for an agency, I used to work for. Not only were the team member images in irregular and different sizes — the grid had unnecessary many levels of `<div>`-soup:

![DIV Soup](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/asokh72glcte5qbo7uld.png)

We can do better! A "team-member card" can be as simple as:

```html
<div class="card">
  <img src="srj.jpg" alt="Samantha Richardson-Jackson" width="200" height="200" loading="lazy">
  <h2>Samantha Richardson-Jackson</h2>
  <small>Senior Digital Program & Project Manager</small>
</div>
```

The CSS is a simple `grid`. We add a `row-gap`, align the content to `start`, and add an `aspect-ratio` to the image. 

We then set a `background-color` on the image, so it looks nice while loading. I've chosen the system color `GrayText`, so it looks nice in _both_ light and dark mode:

```css
.card {
  align-content: start;
  display: grid;
  row-gap: 1ch;
  & h2 {
    line-height: 1.3;
    margin: 0;
    text-wrap: pretty;
  }
  & img {
    aspect-ratio: 1;
    background: GrayText;
    height: auto;
    object-fit: cover;
    width: 100%;
  }
}
```

For the name, `<h2>`, we use the new `text-wrap: pretty` — and we get:

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

The job-title looks a bit _unbalanced_, let's add `text-wrap: balance` to it:

![Text Wrap Blance](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rji6sgrrshf1ed5l0m1c.png)

Now, let's add a wrapper — _another grid_ — with `auto-fill`, so we don't need to worry about breakpoints and responsive design:

```css
.card-grid {
  column-gap: 2em;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  row-gap: 3em;
}
```

The grid will be filled with cards with a minimum width of `200px`, which will automatically break to a new line, when the space has been used up:

![Grid](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ajn1f1y79b2okv9wrorh.png)

---

## Using subgrid
If you can live without the `auto-fill`, you can align the text in multiple cards using `subgrid`.

Add this to the `.card` CSS:

```css
.card {
  grid-row: 1 / 4;
  grid-template-rows: subgrid;
}
```

… and — voilà — the name and job title align:

![Subgrid](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yijlaxrzcuy5o54ljnjx.png)

---

## Adding a background color
Without changing the markup, let's add a `background-color` and adjust the text accordingly:

```css
.card {
  background: color-mix(in srgb, Canvas 90%, CanvasText 10%);
  & h2, small { padding-inline: .66rem; }
  & small { padding-block-end: 1rem; }
}
```

![Background](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0z9tfmwq9f73qg4g4b9v.png)

The `color-mix` blends two [System Colors](https://developer.mozilla.org/en-US/docs/Web/CSS/system-color), so we don't have to do anything about dark mode:


![Dark Mode](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/smtbsr5rn2mb1wybjrzc.png)

---

## Rounded

If we want rounded borders, we can add `border-radius: .5em`:

![Border Radius](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yel3zdnk11l6esbza6e7.png)

— But that doesn't seem to work for the image … we need to set:

```css
.card {
  border-radius: .5em;
  & img {
    border-start-start-radius: inherit;
    border-start-end-radius: inherit;
  }
}
```

— **OR** we can use `clip-path`:

```css
.card {
  clip-path: inset(0 round .5em);
}
```

![Border Radius and clippath](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/97dtgydj0v13iocpgixl.png)


The result is the same, but `clip-path` will also cut off box-shadows and borders, should you need them.

And that concludes this tutorial! As you can see, a card-component can be _super simple_, with a **lot** of flexibility through the power of CSS grids.

---

## Demo
Here's a CodePen. Open it in _full_ and resize to see `auto-fill` in action. The last four cards have `background-color`, the final two `border-radius`:

{% codepen https://codepen.io/stoumann/pen/abxGymK %}

---

All team member images by [ThisPersonDoesNotExist](https://thispersondoesnotexist.com/) — names by chatGPT.