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:
We can do better! A "team-member card" can be as simple as:
<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:
.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:
The job-title looks a bit unbalanced, let's add text-wrap: balance
to it:
Now, let's add a wrapper — another grid — with auto-fill
, so we don't need to worry about breakpoints and responsive design:
.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:
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:
.card {
grid-row: 1 / 4;
grid-template-rows: subgrid;
}
… and — voilà — the name and job title align:
Adding a background color
Without changing the markup, let's add a background-color
and adjust the text accordingly:
.card {
background: color-mix(in srgb, Canvas 90%, CanvasText 10%);
& h2, small { padding-inline: .66rem; }
& small { padding-block-end: 1rem; }
}
The color-mix
blends two System Colors, so we don't have to do anything about dark mode:
Rounded
If we want rounded borders, we can add border-radius: .5em
:
— But that doesn't seem to work for the image … we need to set:
.card {
border-radius: .5em;
& img {
border-start-start-radius: inherit;
border-start-end-radius: inherit;
}
}
— OR we can use clip-path
:
.card {
clip-path: inset(0 round .5em);
}
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
:
All team member images by ThisPersonDoesNotExist — names by chatGPT.
Top comments (2)
Nife job, Mads. I like your approach. 👍
Thanks!