Center anything, both axes
.hero {
display: grid;
place-items: center;
}
The layout moves you make every week, from centering and responsive columns to sticky headers, clamped text, and container queries.
.hero {
display: grid;
place-items: center;
}
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 1rem;
}
auto-fill keeps empty tracks. auto-fit collapses them so the items stretch to fill the row.
.tags {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.toolbar > .logout {
margin-left: auto;
}
An auto margin takes all the free space in a flex or grid container. It works on the cross axis too.
.page {
max-width: 65ch;
margin-inline: auto;
}
Logical properties follow the writing direction, so this also works for right-to-left pages.
.cell {
min-width: 0;
}
Items default to min-width: auto, so a long word or a wide table refuses to shrink until you say it can.
.thumb {
aspect-ratio: 16 / 9;
object-fit: cover;
}
h1 {
font-size: clamp(1.5rem, 1rem + 2vw, 3rem);
}
Minimum, preferred, maximum. The middle value scales with the viewport.
.title {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
All three are needed. The element also needs a width to run out of.
.excerpt {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
The -webkit- prefix is the standard spelling every browser ships.
header {
position: sticky;
top: 0;
}
Sticks within its parent. An overflow: hidden on any ancestor between here and the scroller breaks it.
.card-slot {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
grid-template-columns: 1fr 2fr;
}
}
The query reads the nearest ancestor with a container-type.
.field:has(input:invalid) {
border-color: var(--color-destructive);
}
Works for any selector inside. .card:has(> img) matches cards with a direct image child.