defuss-shadcn / Website / Landing Page / blog
BlogBLK
Insights teasers: 3:2 media, category + read-time meta, clamped excerpt, author row from the Avatar component.
On this page (7)
§Default
Each card is one link; the whole card is clickable.
§Featured post
data-variant='featured' on .mk-blog-grid: the first post spans two columns and two rows from 44rem; the others fill the column beside it.
§List
data-variant='list': rows with the picture beside the text and a rule between them - the author line steps aside.
§Minimal
data-variant='minimal': text-only posts (no figure) under a strong rule - for a quiet, editorial page.
§Overlay
data-variant='overlay': the text sits on the picture over a dark scrim; the picture zooms a little on hover.
§Carousel with filters
data-variant='carousel': one row that scrolls sideways and snaps per post; category links (.mk-blog-filters) above it - the current one is filled.
§CSS view file
/* -- Blog (marketing) ---------------------------------------------- Insights grid: media card with category/read-time meta, line-clamped excerpt, and author row composed from the avatar component. */@layer components { .mk-blog { container: mk-blog / inline-size; display: flex; flex-direction: column; gap: 3rem; width: 100%; max-width: 80rem; margin-inline: auto; padding-inline: 1.25rem; } .mk-blog-head { display: flex; gap: 1.25rem; align-items: flex-start; } .mk-blog-head-copy { display: flex; flex: 1; flex-direction: column; align-items: flex-start; gap: 0.75rem; width: 100%; max-width: 48rem; text-align: left; } .mk-blog-eyebrow { color: var(--primary); font-size: 1rem; font-weight: 500; } .mk-blog-title { line-height: 1.15; margin: 0; font-size: 1.875rem; font-weight: 500; letter-spacing: -0.025em; text-wrap: balance; } .mk-blog-desc { margin: 0; max-width: 42rem; color: var(--muted-foreground); font-size: 1rem; text-wrap: pretty; } .mk-blog-see-all { display: none; margin-inline-start: auto; align-self: flex-end; flex-shrink: 0; } .mk-blog-grid { display: grid; gap: 1.25rem; width: 100%; } .mk-blog-card { display: flex; flex-direction: column; color: inherit; text-decoration: none; } .mk-blog-media { position: relative; aspect-ratio: 3 / 2; width: 100%; margin: 0; overflow: hidden; border-radius: var(--radius-lg); background: var(--muted); & img { width: 100%; height: 100%; object-fit: cover; display: block; transition: opacity 150ms ease; } } .mk-blog-card:hover .mk-blog-media img { opacity: 0.9; } .mk-blog-body { display: flex; flex: 1; flex-direction: column; gap: 0.75rem; padding-block: 0.875rem; } .mk-blog-meta { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; } .mk-blog-category { color: var(--primary); font-size: 0.875rem; font-weight: 500; } /* read time: a muted pill with a clock glyph */ .mk-blog-read { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.125rem 0.5rem; border-radius: 999px; background: var(--muted); color: var(--muted-foreground); font-size: 0.75rem; font-weight: 500; font-variant-numeric: tabular-nums; & svg { width: 0.75rem; height: 0.75rem; flex: none; } } .mk-blog-copy { display: grid; gap: 0.25rem; } .mk-blog-card-title { line-height: 1.3; margin: 0; font-size: 1.125rem; font-weight: 500; letter-spacing: -0.025em; text-wrap: balance; } /* excerpt clamp: exactly 3 lines (source: line-clamp-3) */ .mk-blog-excerpt { margin: 0; color: var(--muted-foreground); font-size: 0.875rem; text-wrap: pretty; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; } .mk-blog-author { display: flex; align-items: center; gap: 0.5rem; margin-block-start: auto; } .mk-blog-author-name { font-size: 0.875rem; font-weight: 500; } .mk-blog-author-date { color: var(--muted-foreground); font-size: 0.75rem; } @container mk-blog (min-width: 30rem) { .mk-blog-grid { grid-template-columns: 1fr 1fr; } } @container mk-blog (min-width: 44rem) { .mk-blog-grid { grid-template-columns: repeat(3, 1fr); } } @container mk-blog (min-width: 52rem) { .mk-blog-title { font-size: 2.25rem; } .mk-blog-see-all { display: inline-flex; } .mk-blog-grid { gap: 2.25rem; } } /* -- variants ------------------------------------------------- */ /* featured: the first post spans two columns and two rows */ .mk-blog-grid[data-variant="featured"] > :first-child { & .mk-blog-card-title { font-size: 1.5rem; } & .mk-blog-excerpt { -webkit-line-clamp: 4; font-size: 1rem; } /* the card spans two rows - keep the author with the text, not at the bottom */ & .mk-blog-author { margin-block-start: 0.5rem; } } /* list: rows with the picture beside the text, separated by rules */ .mk-blog-grid[data-variant="list"] { grid-template-columns: minmax(0, 1fr); gap: 0; & .mk-blog-card { flex-direction: row; align-items: center; gap: 1.25rem; padding-block: 1.25rem; border-block-end: 1px solid var(--border); } & .mk-blog-card:first-child { padding-block-start: 0; } & .mk-blog-media { flex: none; width: 34%; max-width: 15rem; aspect-ratio: 4 / 3; } & .mk-blog-body { padding-block: 0; } & .mk-blog-author { display: none; } } /* minimal: text only - a rule on top of each post */ .mk-blog-grid[data-variant="minimal"] .mk-blog-card { padding-block-start: 1rem; border-block-start: 2px solid var(--foreground); & .mk-blog-card-title { font-size: 1.25rem; } &:hover .mk-blog-card-title { text-decoration: underline; text-underline-offset: 0.2em; } } /* overlay: the text sits on the picture, a scrim keeps it readable */ .mk-blog-grid[data-variant="overlay"] .mk-blog-card { position: relative; isolation: isolate; overflow: hidden; min-height: 22rem; border-radius: var(--radius-xl); color: #fff; & .mk-blog-media { position: absolute; inset: 0; z-index: -2; aspect-ratio: auto; border-radius: 0; } & .mk-blog-media img { transition: scale 400ms ease; } &:hover .mk-blog-media img { opacity: 1; scale: 1.04; } &::before { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(to top, oklch(0.12 0.02 260 / 0.9), oklch(0.12 0.02 260 / 0.1) 70%); } & .mk-blog-body { justify-content: flex-end; padding: 1.25rem; } & .mk-blog-category { color: inherit; } & .mk-blog-read { background: oklch(1 0 0 / 0.16); color: inherit; } & :is(.mk-blog-excerpt, .mk-blog-author-date) { color: oklch(1 0 0 / 0.75); } & .mk-blog-author { margin-block-start: 0.25rem; } } /* carousel: one row that scrolls sideways and snaps per post */ .mk-blog-grid[data-variant="carousel"] { display: flex; gap: 1.25rem; overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scroll-padding-inline: 0.25rem; padding-block-end: 0.75rem; scrollbar-width: thin; & > * { flex: 0 0 min(82%, 20rem); scroll-snap-align: start; } } /* category filters: links with the current one filled */ .mk-blog-filters { display: flex; flex-wrap: wrap; gap: 0.5rem; & a { padding: 0.375rem 0.875rem; border: 1px solid var(--border); border-radius: 999px; color: var(--muted-foreground); font-size: 0.875rem; font-weight: 500; text-decoration: none; } & a:hover { color: var(--foreground); border-color: color-mix(in oklch, var(--foreground) 30%, var(--border)); } & a[aria-current] { border-color: var(--foreground); background: var(--foreground); color: var(--background); } & a:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; } } @container mk-blog (min-width: 44rem) { .mk-blog-grid[data-variant="featured"] > :first-child { grid-column: span 2; grid-row: span 2; } .mk-blog-grid[data-variant="featured"] > :first-child .mk-blog-media { aspect-ratio: 16 / 10; } } /* -- Accessibility ------------------------------------------- */ @media (prefers-reduced-motion: reduce) { .mk-blog-grid[data-variant="overlay"] .mk-blog-media img { transition: none; } .mk-blog-grid[data-variant="overlay"] .mk-blog-card:hover .mk-blog-media img { scale: none; } } @media (forced-colors: active) { .mk-blog-filters a[aria-current] { border-color: Highlight; background: Highlight; color: HighlightText; } } @media (prefers-reduced-motion: reduce) { .mk-blog-media img { transition: none; } } @media (forced-colors: active) { .mk-blog-card { color: LinkText; } }}Comments, ideas or improvements? Edit this page's source on GitHub