defuss-shadcn / Website / Landing Page / testimonials
TestimonialsBLK
A pull quote with a linked brand lockup, plus review cards whose overlay floats over the photo with backdrop blur.
On this page (6)
§Default
Quote block + four quote cards (data-variant='quote'): stars, the review and the author with an Avatar.
§Photo cards
The cards as photos: the review floats over the picture on a blurred surface (backdrop-filter) - stars, the review line, name and role.
§Wall of love
data-variant='wall' on .mk-testimonial-cards: a masonry wall (CSS columns) - cards of any length pack without gaps; one carries a result line (.mk-testimonial-card-metric).
§Marquee
Two rows of quote cards gliding in opposite directions (data-direction='reverse'), soft edges; hover or focus pauses them. Each row runs twice in its track - the copy is inert and aria-hidden - for a seamless loop. Reduced motion: the rows stand still and scroll by hand.
§Spotlight
.mk-testimonial-spotlight: one review, large and centered - a serif quote that scales with the section, the author with a large Avatar and the company beside a rule.
§CSS view file
/* -- Testimonials (marketing) -------------------------------------- Big pull-quote with partner logo lockup, plus a grid of media cards whose review overlay floats over the photo (backdrop blur, real DOM - no JS). Overlay contrast comes from --background at 80% + blur, readable in both modes. */@layer components { .mk-testimonials { container: mk-testimonials / inline-size; display: flex; flex-direction: column; gap: 3rem; width: 100%; max-width: 80rem; margin-inline: auto; padding-inline: 1.25rem; } .mk-testimonial-quote-block { display: flex; flex-direction: column; } .mk-testimonial-context { display: flex; align-items: center; gap: 0.375rem; padding-bottom: 0.75rem; color: var(--muted-foreground); & svg { width: 1.5rem; height: 1.5rem; flex-shrink: 0; } & span { font-size: 1.125rem; } } .mk-testimonial-layout { display: flex; flex-direction: column; gap: 2.25rem; } .mk-testimonial-quote { margin: 0; font-size: 1.875rem; line-height: 1.15; letter-spacing: -0.025em; text-wrap: balance; } .mk-testimonial-brand { display: flex; align-items: center; gap: 0.5rem; height: fit-content; flex-shrink: 0; color: inherit; text-decoration: none; &:hover .mk-testimonial-brand-name { text-decoration: underline; text-underline-offset: 3px; } &:focus-visible { outline: 2px solid var(--ring); outline-offset: 4px; border-radius: var(--radius-sm); } & svg { width: 2.5rem; height: 2.5rem; aspect-ratio: 1; flex-shrink: 0; } } .mk-testimonial-brand-name { font-size: 1.5rem; font-weight: 500; letter-spacing: -0.025em; white-space: nowrap; } .mk-testimonial-date { color: var(--muted-foreground); font-size: 1.125rem; } .mk-testimonial-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; } /* quote cards flow: one column on phones, as many 16rem columns as fit above (four cards: 2 × 2, then a row) */ .mk-testimonial-cards:has(> [data-variant="quote"]) { grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr)); } .mk-testimonial-card { position: relative; isolation: isolate; aspect-ratio: 3 / 4; overflow: hidden; border-radius: var(--radius-md); background: var(--muted); padding: 0.75rem; /* the element is a <figure> - without an explicit reset its UA margins (1em 40px) stack onto the grid gap (measured: 92px between cards); the gap comes from `gap` alone */ margin: 0; & > img { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; object-fit: cover; object-position: top; } } .mk-testimonial-card-body { position: relative; z-index: 10; width: 100%; /* source: bg-background/80 + backdrop-blur - keep the text readable over any photo without a hard opaque card */ margin-block-start: auto; border: 1px solid var(--border); border-radius: var(--radius-lg); background: color-mix(in oklch, var(--background) 80%, transparent); backdrop-filter: blur(4px); padding: 1rem; } .mk-testimonial-card-info { display: flex; flex-direction: column; align-items: flex-start; gap: 0.25rem; } .mk-stars { display: flex; align-items: center; gap: 0.125rem; } .mk-stars svg { width: 0.75rem; height: 0.75rem; fill: currentColor; flex-shrink: 0; } .mk-testimonial-card-name { font-size: 0.875rem; font-weight: 500; line-height: 1.3; } .mk-testimonial-card-role { color: var(--muted-foreground); font-size: 0.75rem; } /* the review itself - in a quote card, or under the stars of a photo card */ .mk-testimonial-card-text { margin: 0; font-size: 0.9375rem; line-height: 1.55; text-wrap: pretty; & p { margin: 0; } } .mk-testimonial-card-body .mk-testimonial-card-text { margin-block: 0.375rem 0.25rem; font-size: 0.8125rem; } /* the author line: an Avatar + name / role */ .mk-testimonial-card-author { display: flex; align-items: center; gap: 0.75rem; margin-block-start: auto; & .mk-testimonial-card-info { gap: 0; } } /* quote: a card surface - stars, the review, the author at the bottom */ .mk-testimonial-card[data-variant="quote"] { display: flex; flex-direction: column; gap: 1rem; aspect-ratio: auto; padding: 1.25rem; border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--card); color: var(--card-foreground); box-shadow: var(--shadow-xs); & .mk-stars { color: oklch(0.78 0.16 75); } & .mk-testimonial-card-text { font-size: 1rem; } & .mk-testimonial-card-text::before { content: "“"; display: block; height: 1.75rem; margin-block-end: 0.25rem; color: var(--primary); font-family: Georgia, var(--font-serif), serif; font-size: 3.25rem; line-height: 1; opacity: 0.85; } } @container mk-testimonials (min-width: 30rem) { .mk-testimonial-layout { flex-direction: row; } .mk-testimonial-quote { font-size: 2.25rem; } } @container mk-testimonials (min-width: 52rem) { .mk-testimonial-cards { grid-template-columns: repeat(4, 1fr); gap: 1.5rem; } .mk-testimonial-card { padding: 1.25rem; } .mk-testimonial-card-name { font-size: 1.125rem; } .mk-testimonial-card-role { font-size: 0.875rem; } } /* wall: a masonry wall of quote cards (CSS columns) - "wall of love" */ .mk-testimonial-cards[data-variant="wall"] { display: block; columns: 16rem; column-gap: 1rem; & > .mk-testimonial-card { break-inside: avoid; margin-block-end: 1rem; } } /* marquee: rows of quote cards gliding sideways (the second row reverses); the row runs twice in its track (the copy is inert) for a seamless loop */ .mk-testimonial-marquee { display: grid; gap: 1rem; overflow: hidden; mask-image: linear-gradient(to right, transparent, #000 4rem, #000 calc(100% - 4rem), transparent); } .mk-testimonial-marquee-track { display: flex; gap: 1rem; width: max-content; animation: mk-testimonial-marquee var(--mk-testimonial-duration, 45s) linear infinite; &[data-direction="reverse"] { animation-direction: reverse; } & > .mk-testimonial-card { width: 20rem; flex: none; } } .mk-testimonial-marquee:is(:hover, :focus-within) .mk-testimonial-marquee-track { animation-play-state: paused; } @keyframes mk-testimonial-marquee { to { translate: calc(-50% - 0.5rem) 0; } } /* spotlight: one big quote, the author with a large avatar and the logo */ .mk-testimonial-spotlight { display: grid; justify-items: center; gap: 1.5rem; max-width: 48rem; margin-inline: auto; text-align: center; & .mk-stars { color: oklch(0.78 0.16 75); } & .mk-stars svg { width: 1.25rem; height: 1.25rem; } } .mk-testimonial-spotlight-quote { margin: 0; font-family: var(--font-serif); font-size: clamp(1.5rem, 4cqi, 2.25rem); font-weight: 500; line-height: 1.3; letter-spacing: -0.01em; text-wrap: balance; } .mk-testimonial-spotlight-author { display: flex; align-items: center; gap: 1rem; text-align: start; & .mk-testimonial-card-name { font-size: 1rem; } & .mk-testimonial-spotlight-logo { padding-inline-start: 1rem; border-inline-start: 1px solid var(--border); font-weight: 700; letter-spacing: -0.02em; } } /* a result line inside a quote card: "+42% faster releases" */ .mk-testimonial-card-metric { display: flex; align-items: baseline; gap: 0.5rem; padding: 0.75rem 1rem; border-radius: var(--radius-md); background: var(--muted); & strong { font-size: 1.5rem; font-weight: 700; letter-spacing: -0.02em; color: var(--primary); } & span { color: var(--muted-foreground); font-size: 0.8125rem; } } /* -- Accessibility ------------------------------------------- */ @media (prefers-reduced-motion: reduce) { .mk-testimonial-marquee { overflow-x: auto; mask-image: none; } .mk-testimonial-marquee-track { animation: none; } .mk-testimonial-marquee-track > [aria-hidden="true"] { display: none; } } @media (prefers-reduced-transparency: reduce) { .mk-testimonial-card-body { background: var(--background); backdrop-filter: none; } } @media (forced-colors: active) { .mk-testimonial-card-body { background: Canvas; } }}Comments, ideas or improvements? Edit this page's source on GitHub