25 CSS Testimonials & Reviews13 / 25

Pure CSSMIT licensed

Bento Box Testimonial Grid Layout

The bento grid is the dominant landing-page layout of the decade because it lets one section carry several kinds of proof at once — a marquee quote, a hard metric, a logo wall, a rating and a photo, each sized to its own importance. This build uses explicit grid-template-areas so the composition is readable in the CSS and re-flows to a single column with one rewritten area map.

Published Updated

Live Demo
Try it

The code

<section class="tr-13" aria-label="Bento box testimonial grid layout demo">
  <div class="tr-13__stage">
    <header class="tr-13__head">
      <p class="tr-13__eyebrow">Social proof, all of it</p>
      <h2 class="tr-13__title">One section. Five kinds of evidence.</h2>
    </header>

    <div class="tr-13__bento">
      <figure class="tr-13__tile tr-13__hero">
        <span class="tr-13__mark" aria-hidden="true">“</span>
        <blockquote>We benchmarked four vendors for six weeks. This one won on the boring things — audit logs, permissions, an API that behaved exactly like its docs said it would.</blockquote>
        <figcaption>
          <img src="https://images.unsplash.com/photo-1573497019940-1c28c88b4f3e?q=80&w=140&h=140&fit=crop&auto=format" alt="Portrait of Alessandra Rossi" width="48" height="48" loading="lazy" decoding="async">
          <span><b>Alessandra Rossi</b>CTO · Vaultline Financial</span>
        </figcaption>
      </figure>

      <div class="tr-13__tile tr-13__stat">
        <b class="tr-13__big"><span class="tr-13__n" aria-hidden="true"></span><span>%</span></b>
        <span class="tr-13__sr">98 percent</span>
        <p>renew after year one</p>
      </div>

      <div class="tr-13__tile tr-13__rate">
        <span class="tr-13__stars" style="--tr-13-pct:96%" role="img" aria-label="Rated 4.8 out of 5 across 3,912 reviews"></span>
        <b>4.8</b>
        <p>3,912 reviews across four platforms</p>
      </div>

      <figure class="tr-13__tile tr-13__photo">
        <img src="https://images.unsplash.com/photo-1522071820081-009f0129c71c?q=80&w=700&auto=format&fit=crop" alt="A product team reviewing work together at a table" width="520" height="600" loading="lazy" decoding="async">
        <figcaption><b>Fernbrook</b> onboarded 41 people in a day</figcaption>
      </figure>

      <div class="tr-13__tile tr-13__logos" aria-hidden="true">
        <p>Trusted by</p>
        <div>
          <span>NORTHWIND</span><span>MERIDIAN</span><span>AURYN</span><span>PORTSIDE</span><span>BLOMST</span><span>HALDEN</span>
        </div>
      </div>

      <figure class="tr-13__tile tr-13__quote">
        <blockquote>“Support answered a Sev-2 in nine minutes. At 4am.”</blockquote>
        <figcaption><b>Callum Doyle</b> · Head of Platform, Meridian</figcaption>
      </figure>

      <div class="tr-13__tile tr-13__cta">
        <p>Read 40+ full customer stories</p>
        <a class="tr-13__btn" href="#tr-13-stories">Browse case studies <span aria-hidden="true">→</span></a>
      </div>
    </div>
    <p class="tr-13__chip" aria-hidden="true">grid-template-areas · area remap at breakpoint · minmax auto rows · @property counter tile</p>
  </div>
</section>
@property --tr-13-n {
  syntax: '<integer>';
  inherits: false;
  initial-value: 0;
}

.tr-13,
.tr-13 *,
.tr-13 *::before,
.tr-13 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.tr-13 {
  width: 100%;
  min-height: 100vh;
  min-height: 100svh;
  display: block;
  --tr-13-bg: oklch(0.16 0.016 265);
  --tr-13-tile: oklch(0.21 0.02 265);
  --tr-13-ink: oklch(0.97 0.006 265);
  --tr-13-mut: oklch(0.71 0.018 265);
  --tr-13-acc: oklch(0.8 0.15 165);
  --tr-13-star: oklch(0.83 0.15 88);
  background: var(--tr-13-bg);
  color: var(--tr-13-ink);
  font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
  -webkit-font-smoothing: antialiased;
}

.tr-13__stage {
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  place-items: center;
  align-content: center;
  gap: clamp(18px,3vw,28px);
  padding: clamp(18px,4vw,48px);
}

.tr-13__head {
  text-align: center;
  display: grid;
  gap: 9px;
}

.tr-13__eyebrow {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--tr-13-acc);
}

.tr-13__title {
  font-size: clamp(23px,3.6vw,38px);
  font-weight: 670;
  letter-spacing: -.035em;
  text-wrap: balance;
}

.tr-13__bento {
  display: grid;
  width: min(100%,1120px);
  grid-template-columns: repeat(4,1fr);
  grid-auto-rows: minmax(132px,auto);
  gap: clamp(10px,1.3vw,15px);
  grid-template-areas: 'hero hero stat logos' 'hero hero photo logos' 'quote rate photo cta';
}

.tr-13__tile {
  position: relative;
  padding: clamp(16px,2vw,22px);
  border-radius: 18px;
  background: var(--tr-13-tile);
  border: 1px solid oklch(1 0 0/.08);
  overflow: hidden;
  animation: tr-13-in .7s cubic-bezier(.16,1,.3,1) both;
  transition: translate .3s cubic-bezier(.16,1,.3,1),border-color .3s;
}

.tr-13__tile:hover {
  translate: 0 -2px;
  border-color: color-mix(in oklch,var(--tr-13-acc) 38%,transparent);
}

@keyframes tr-13-in {
  from {
    opacity: 0;
    translate: 0 14px;
  }

  to {
    opacity: 1;
    translate: 0 0;
  }
}

.tr-13__hero {
  grid-area: hero;
  display: grid;
  align-content: space-between;
  gap: 20px;
  padding: clamp(22px,2.8vw,32px);
  background: linear-gradient(160deg,color-mix(in oklch,var(--tr-13-acc) 14%,var(--tr-13-tile)),var(--tr-13-tile) 65%);
  animation-delay: 0s;
}

.tr-13__mark {
  position: absolute;
  inset-block-start: 2px;
  inset-inline-end: 18px;
  font-family: Georgia,serif;
  font-size: 120px;
  line-height: 1;
  color: color-mix(in oklch,var(--tr-13-acc) 18%,transparent);
}

.tr-13__hero blockquote {
  position: relative;
  font-size: clamp(17px,2.1vw,23px);
  line-height: 1.45;
  letter-spacing: -.024em;
  text-wrap: pretty;
}

.tr-13__hero figcaption,
.tr-13__photo figcaption {
  display: flex;
  align-items: center;
  gap: 11px;
}

.tr-13__hero figcaption img {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  object-fit: cover;
  flex: none;
}

.tr-13__hero figcaption span {
  display: grid;
  font-size: 12px;
  line-height: 1.35;
  color: var(--tr-13-mut);
}

.tr-13__hero figcaption b {
  font-size: 14.5px;
  font-weight: 640;
  color: var(--tr-13-ink);
  letter-spacing: -.014em;
}

.tr-13__stat {
  grid-area: stat;
  display: grid;
  align-content: center;
  gap: 2px;
  animation-delay: .06s;
}

.tr-13__big {
  display: flex;
  align-items: baseline;
  font-size: clamp(34px,4.4vw,50px);
  font-weight: 720;
  letter-spacing: -.05em;
  line-height: 1;
  color: var(--tr-13-acc);
  font-variant-numeric: tabular-nums;
}

.tr-13__big span:last-child {
  font-size: .5em;
  margin-inline-start: 2px;
}

.tr-13__n {
  counter-reset: tr-13-c var(--tr-13-n);
  animation: tr-13-run 2.2s cubic-bezier(.16,1,.3,1) .3s both;
}

.tr-13__n::after {
  content: counter(tr-13-c);
}

@keyframes tr-13-run {
  from {
    --tr-13-n: 0;
  }

  to {
    --tr-13-n: 98;
  }
}

.tr-13__stat p {
  font-size: 12.5px;
  color: var(--tr-13-mut);
  line-height: 1.4;
  text-wrap: balance;
}

.tr-13__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

.tr-13__rate {
  grid-area: rate;
  display: grid;
  align-content: center;
  gap: 5px;
  animation-delay: .12s;
}

.tr-13__stars {
  position: relative;
  display: inline-block;
  font-size: 19px;
  line-height: 1;
  letter-spacing: 1.5px;
  width: fit-content;
}

.tr-13__stars::before {
  content: '★★★★★';
  color: oklch(1 0 0/.16);
}

.tr-13__stars::after {
  content: '★★★★★';
  color: var(--tr-13-star);
  position: absolute;
  inset: 0;
  clip-path: inset(0 calc(100% - var(--tr-13-pct,100%)) 0 0);
}

.tr-13__rate b {
  font-size: 28px;
  font-weight: 700;
  letter-spacing: -.04em;
  font-variant-numeric: tabular-nums;
}

.tr-13__rate p {
  font-size: 12px;
  color: var(--tr-13-mut);
  line-height: 1.4;
}

.tr-13__photo {
  grid-area: photo;
  padding: 0;
  animation-delay: .18s;
}

.tr-13__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  min-height: 180px;
  background: linear-gradient(140deg,oklch(0.4 0.05 265),oklch(0.3 0.04 300));
  transition: scale .6s cubic-bezier(.16,1,.3,1);
}

.tr-13__photo:hover img {
  scale: 1.05;
}

.tr-13__photo figcaption {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  padding: 16px;
  font-size: 12px;
  color: oklch(0.97 0 0);
  background: linear-gradient(transparent,oklch(0.12 0.01 265/.92));
}

.tr-13__photo figcaption b {
  font-weight: 660;
}

.tr-13__logos {
  grid-area: logos;
  display: grid;
  align-content: center;
  gap: 12px;
  animation-delay: .24s;
}

.tr-13__logos p {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--tr-13-mut);
}

.tr-13__logos div {
  display: grid;
  gap: 10px;
}

.tr-13__logos span {
  font-size: 13px;
  font-weight: 720;
  letter-spacing: .06em;
  color: oklch(1 0 0/.42);
  transition: color .25s;
}

.tr-13__logos:hover span {
  color: oklch(1 0 0/.7);
}

.tr-13__quote {
  grid-area: quote;
  display: grid;
  align-content: center;
  gap: 10px;
  animation-delay: .3s;
}

.tr-13__quote blockquote {
  font-size: 15px;
  line-height: 1.42;
  letter-spacing: -.016em;
  text-wrap: pretty;
}

.tr-13__quote figcaption {
  font-size: 11.5px;
  color: var(--tr-13-mut);
}

.tr-13__quote figcaption b {
  color: var(--tr-13-ink);
  font-weight: 620;
}

.tr-13__cta {
  grid-area: cta;
  display: grid;
  align-content: center;
  gap: 12px;
  background: linear-gradient(150deg,color-mix(in oklch,var(--tr-13-acc) 20%,var(--tr-13-tile)),var(--tr-13-tile));
  animation-delay: .36s;
}

.tr-13__cta p {
  font-size: 13.5px;
  line-height: 1.4;
  font-weight: 560;
  text-wrap: balance;
}

.tr-13__btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 16px;
  width: fit-content;
  border-radius: 10px;
  background: var(--tr-13-acc);
  color: oklch(0.18 0.03 165);
  font-size: 13px;
  font-weight: 660;
  text-decoration: none;
  transition: gap .25s cubic-bezier(.16,1,.3,1),background .25s;
}

.tr-13__btn:hover {
  gap: 12px;
  background: color-mix(in oklch,var(--tr-13-acc) 82%,white);
}

.tr-13__btn:focus-visible {
  outline: 3px solid var(--tr-13-acc);
  outline-offset: 3px;
}

.tr-13__chip {
  font-family: ui-monospace,Menlo,Consolas,monospace;
  font-size: 11.5px;
  color: var(--tr-13-mut);
  padding: 8px 15px;
  border: 1px solid oklch(1 0 0/.13);
  border-radius: 99px;
  text-align: center;
}

@media (max-width: 860px) {
  .tr-13__bento {
    grid-template-columns: repeat(2,1fr);
    grid-template-areas: 'hero hero' 'stat rate' 'photo photo' 'quote logos' 'cta cta';
  }
}

@media (max-width: 520px) {
  .tr-13__bento {
    grid-template-columns: 1fr;
    grid-template-areas: 'hero' 'stat' 'rate' 'photo' 'quote' 'logos' 'cta';
  }
}

@media (prefers-reduced-motion: reduce) {
  .tr-13__tile {
    animation: none;
  }

  .tr-13__n {
    animation-duration: 1ms;
  }

  .tr-13__photo:hover img {
    scale: 1;
  }
}
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Testimonials & Review from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Bento Box Testimonial Grid Layout
Source: https://codefronts.com/components/css-testimonials-reviews/blossom-bento/

The bento grid is the dominant landing-page layout of the decade because it lets one section carry several kinds of proof at once — a marquee quote, a hard metric, a logo wall, a rating and a photo, each sized to its own importance. This build uses explicit grid-template-areas so the composition is readable in the CSS and re-flows to a single column with one rewritten area map.
## HTML
```html
<section class="tr-13" aria-label="Bento box testimonial grid layout demo">
  <div class="tr-13__stage">
    <header class="tr-13__head">
      <p class="tr-13__eyebrow">Social proof, all of it</p>
      <h2 class="tr-13__title">One section. Five kinds of evidence.</h2>
    </header>

    <div class="tr-13__bento">
      <figure class="tr-13__tile tr-13__hero">
        <span class="tr-13__mark" aria-hidden="true">“</span>
        <blockquote>We benchmarked four vendors for six weeks. This one won on the boring things — audit logs, permissions, an API that behaved exactly like its docs said it would.</blockquote>
        <figcaption>
          <img src="https://images.unsplash.com/photo-1573497019940-1c28c88b4f3e?q=80&w=140&h=140&fit=crop&auto=format" alt="Portrait of Alessandra Rossi" width="48" height="48" loading="lazy" decoding="async">
          <span><b>Alessandra Rossi</b>CTO · Vaultline Financial</span>
        </figcaption>
      </figure>

      <div class="tr-13__tile tr-13__stat">
        <b class="tr-13__big"><span class="tr-13__n" aria-hidden="true"></span><span>%</span></b>
        <span class="tr-13__sr">98 percent</span>
        <p>renew after year one</p>
      </div>

      <div class="tr-13__tile tr-13__rate">
        <span class="tr-13__stars" style="--tr-13-pct:96%" role="img" aria-label="Rated 4.8 out of 5 across 3,912 reviews"></span>
        <b>4.8</b>
        <p>3,912 reviews across four platforms</p>
      </div>

      <figure class="tr-13__tile tr-13__photo">
        <img src="https://images.unsplash.com/photo-1522071820081-009f0129c71c?q=80&w=700&auto=format&fit=crop" alt="A product team reviewing work together at a table" width="520" height="600" loading="lazy" decoding="async">
        <figcaption><b>Fernbrook</b> onboarded 41 people in a day</figcaption>
      </figure>

      <div class="tr-13__tile tr-13__logos" aria-hidden="true">
        <p>Trusted by</p>
        <div>
          <span>NORTHWIND</span><span>MERIDIAN</span><span>AURYN</span><span>PORTSIDE</span><span>BLOMST</span><span>HALDEN</span>
        </div>
      </div>

      <figure class="tr-13__tile tr-13__quote">
        <blockquote>“Support answered a Sev-2 in nine minutes. At 4am.”</blockquote>
        <figcaption><b>Callum Doyle</b> · Head of Platform, Meridian</figcaption>
      </figure>

      <div class="tr-13__tile tr-13__cta">
        <p>Read 40+ full customer stories</p>
        <a class="tr-13__btn" href="#tr-13-stories">Browse case studies <span aria-hidden="true">→</span></a>
      </div>
    </div>
    <p class="tr-13__chip" aria-hidden="true">grid-template-areas · area remap at breakpoint · minmax auto rows · @property counter tile</p>
  </div>
</section>
```
## CSS
```css
@property --tr-13-n {
  syntax: '<integer>';
  inherits: false;
  initial-value: 0;
}

.tr-13,
.tr-13 *,
.tr-13 *::before,
.tr-13 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.tr-13 {
  width: 100%;
  min-height: 100vh;
  min-height: 100svh;
  display: block;
  --tr-13-bg: oklch(0.16 0.016 265);
  --tr-13-tile: oklch(0.21 0.02 265);
  --tr-13-ink: oklch(0.97 0.006 265);
  --tr-13-mut: oklch(0.71 0.018 265);
  --tr-13-acc: oklch(0.8 0.15 165);
  --tr-13-star: oklch(0.83 0.15 88);
  background: var(--tr-13-bg);
  color: var(--tr-13-ink);
  font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
  -webkit-font-smoothing: antialiased;
}

.tr-13__stage {
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  place-items: center;
  align-content: center;
  gap: clamp(18px,3vw,28px);
  padding: clamp(18px,4vw,48px);
}

.tr-13__head {
  text-align: center;
  display: grid;
  gap: 9px;
}

.tr-13__eyebrow {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--tr-13-acc);
}

.tr-13__title {
  font-size: clamp(23px,3.6vw,38px);
  font-weight: 670;
  letter-spacing: -.035em;
  text-wrap: balance;
}

.tr-13__bento {
  display: grid;
  width: min(100%,1120px);
  grid-template-columns: repeat(4,1fr);
  grid-auto-rows: minmax(132px,auto);
  gap: clamp(10px,1.3vw,15px);
  grid-template-areas: 'hero hero stat logos' 'hero hero photo logos' 'quote rate photo cta';
}

.tr-13__tile {
  position: relative;
  padding: clamp(16px,2vw,22px);
  border-radius: 18px;
  background: var(--tr-13-tile);
  border: 1px solid oklch(1 0 0/.08);
  overflow: hidden;
  animation: tr-13-in .7s cubic-bezier(.16,1,.3,1) both;
  transition: translate .3s cubic-bezier(.16,1,.3,1),border-color .3s;
}

.tr-13__tile:hover {
  translate: 0 -2px;
  border-color: color-mix(in oklch,var(--tr-13-acc) 38%,transparent);
}

@keyframes tr-13-in {
  from {
    opacity: 0;
    translate: 0 14px;
  }

  to {
    opacity: 1;
    translate: 0 0;
  }
}

.tr-13__hero {
  grid-area: hero;
  display: grid;
  align-content: space-between;
  gap: 20px;
  padding: clamp(22px,2.8vw,32px);
  background: linear-gradient(160deg,color-mix(in oklch,var(--tr-13-acc) 14%,var(--tr-13-tile)),var(--tr-13-tile) 65%);
  animation-delay: 0s;
}

.tr-13__mark {
  position: absolute;
  inset-block-start: 2px;
  inset-inline-end: 18px;
  font-family: Georgia,serif;
  font-size: 120px;
  line-height: 1;
  color: color-mix(in oklch,var(--tr-13-acc) 18%,transparent);
}

.tr-13__hero blockquote {
  position: relative;
  font-size: clamp(17px,2.1vw,23px);
  line-height: 1.45;
  letter-spacing: -.024em;
  text-wrap: pretty;
}

.tr-13__hero figcaption,
.tr-13__photo figcaption {
  display: flex;
  align-items: center;
  gap: 11px;
}

.tr-13__hero figcaption img {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  object-fit: cover;
  flex: none;
}

.tr-13__hero figcaption span {
  display: grid;
  font-size: 12px;
  line-height: 1.35;
  color: var(--tr-13-mut);
}

.tr-13__hero figcaption b {
  font-size: 14.5px;
  font-weight: 640;
  color: var(--tr-13-ink);
  letter-spacing: -.014em;
}

.tr-13__stat {
  grid-area: stat;
  display: grid;
  align-content: center;
  gap: 2px;
  animation-delay: .06s;
}

.tr-13__big {
  display: flex;
  align-items: baseline;
  font-size: clamp(34px,4.4vw,50px);
  font-weight: 720;
  letter-spacing: -.05em;
  line-height: 1;
  color: var(--tr-13-acc);
  font-variant-numeric: tabular-nums;
}

.tr-13__big span:last-child {
  font-size: .5em;
  margin-inline-start: 2px;
}

.tr-13__n {
  counter-reset: tr-13-c var(--tr-13-n);
  animation: tr-13-run 2.2s cubic-bezier(.16,1,.3,1) .3s both;
}

.tr-13__n::after {
  content: counter(tr-13-c);
}

@keyframes tr-13-run {
  from {
    --tr-13-n: 0;
  }

  to {
    --tr-13-n: 98;
  }
}

.tr-13__stat p {
  font-size: 12.5px;
  color: var(--tr-13-mut);
  line-height: 1.4;
  text-wrap: balance;
}

.tr-13__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

.tr-13__rate {
  grid-area: rate;
  display: grid;
  align-content: center;
  gap: 5px;
  animation-delay: .12s;
}

.tr-13__stars {
  position: relative;
  display: inline-block;
  font-size: 19px;
  line-height: 1;
  letter-spacing: 1.5px;
  width: fit-content;
}

.tr-13__stars::before {
  content: '★★★★★';
  color: oklch(1 0 0/.16);
}

.tr-13__stars::after {
  content: '★★★★★';
  color: var(--tr-13-star);
  position: absolute;
  inset: 0;
  clip-path: inset(0 calc(100% - var(--tr-13-pct,100%)) 0 0);
}

.tr-13__rate b {
  font-size: 28px;
  font-weight: 700;
  letter-spacing: -.04em;
  font-variant-numeric: tabular-nums;
}

.tr-13__rate p {
  font-size: 12px;
  color: var(--tr-13-mut);
  line-height: 1.4;
}

.tr-13__photo {
  grid-area: photo;
  padding: 0;
  animation-delay: .18s;
}

.tr-13__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  min-height: 180px;
  background: linear-gradient(140deg,oklch(0.4 0.05 265),oklch(0.3 0.04 300));
  transition: scale .6s cubic-bezier(.16,1,.3,1);
}

.tr-13__photo:hover img {
  scale: 1.05;
}

.tr-13__photo figcaption {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  padding: 16px;
  font-size: 12px;
  color: oklch(0.97 0 0);
  background: linear-gradient(transparent,oklch(0.12 0.01 265/.92));
}

.tr-13__photo figcaption b {
  font-weight: 660;
}

.tr-13__logos {
  grid-area: logos;
  display: grid;
  align-content: center;
  gap: 12px;
  animation-delay: .24s;
}

.tr-13__logos p {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--tr-13-mut);
}

.tr-13__logos div {
  display: grid;
  gap: 10px;
}

.tr-13__logos span {
  font-size: 13px;
  font-weight: 720;
  letter-spacing: .06em;
  color: oklch(1 0 0/.42);
  transition: color .25s;
}

.tr-13__logos:hover span {
  color: oklch(1 0 0/.7);
}

.tr-13__quote {
  grid-area: quote;
  display: grid;
  align-content: center;
  gap: 10px;
  animation-delay: .3s;
}

.tr-13__quote blockquote {
  font-size: 15px;
  line-height: 1.42;
  letter-spacing: -.016em;
  text-wrap: pretty;
}

.tr-13__quote figcaption {
  font-size: 11.5px;
  color: var(--tr-13-mut);
}

.tr-13__quote figcaption b {
  color: var(--tr-13-ink);
  font-weight: 620;
}

.tr-13__cta {
  grid-area: cta;
  display: grid;
  align-content: center;
  gap: 12px;
  background: linear-gradient(150deg,color-mix(in oklch,var(--tr-13-acc) 20%,var(--tr-13-tile)),var(--tr-13-tile));
  animation-delay: .36s;
}

.tr-13__cta p {
  font-size: 13.5px;
  line-height: 1.4;
  font-weight: 560;
  text-wrap: balance;
}

.tr-13__btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 16px;
  width: fit-content;
  border-radius: 10px;
  background: var(--tr-13-acc);
  color: oklch(0.18 0.03 165);
  font-size: 13px;
  font-weight: 660;
  text-decoration: none;
  transition: gap .25s cubic-bezier(.16,1,.3,1),background .25s;
}

.tr-13__btn:hover {
  gap: 12px;
  background: color-mix(in oklch,var(--tr-13-acc) 82%,white);
}

.tr-13__btn:focus-visible {
  outline: 3px solid var(--tr-13-acc);
  outline-offset: 3px;
}

.tr-13__chip {
  font-family: ui-monospace,Menlo,Consolas,monospace;
  font-size: 11.5px;
  color: var(--tr-13-mut);
  padding: 8px 15px;
  border: 1px solid oklch(1 0 0/.13);
  border-radius: 99px;
  text-align: center;
}

@media (max-width: 860px) {
  .tr-13__bento {
    grid-template-columns: repeat(2,1fr);
    grid-template-areas: 'hero hero' 'stat rate' 'photo photo' 'quote logos' 'cta cta';
  }
}

@media (max-width: 520px) {
  .tr-13__bento {
    grid-template-columns: 1fr;
    grid-template-areas: 'hero' 'stat' 'rate' 'photo' 'quote' 'logos' 'cta';
  }
}

@media (prefers-reduced-motion: reduce) {
  .tr-13__tile {
    animation: none;
  }

  .tr-13__n {
    animation-duration: 1ms;
  }

  .tr-13__photo:hover img {
    scale: 1;
  }
}
```

How this works

Named areas make an asymmetric grid maintainable. You can see the layout in the source:

.bento {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: minmax(140px, auto);
  grid-template-areas:
    'hero hero stat  logos'
    'hero hero photo logos'
    'quote rate photo cta';
  gap: 14px;
}
.hero { grid-area: hero; }

Changing the whole composition at a breakpoint is then one property, not a dozen span rules:

@media (max-width: 820px) {
  .bento { grid-template-columns: repeat(2, 1fr);
    grid-template-areas: 'hero hero' 'stat rate' 'photo photo' 'quote logos' 'cta cta'; }
}

Every tile is a <figure> or a labelled region, and the tiles that are purely visual (logo wall, photo) are marked aria-hidden where the same information is already carried in text — a bento grid should never make a screen-reader user tab through twelve decorative cells.

The hover treatment is deliberately quiet: a 1 px border brightening plus a 2 px lift. With this many tiles on screen, anything louder turns the section into a fairground.

The metric tile animates once on load with a registered @property counter (see demo 07 for the full explanation), giving the grid a single focal motion instead of eleven competing ones.

Make it yours

  • Rebalance importance by editing the area map alone — promoting the rating tile to a 2×2 takes one line and no markup change.
  • Add subgrid to a tile that contains its own rows (grid-template-rows: subgrid) so inner content aligns to the parent's rails across tiles.
  • Use container queries per tile so a card's internal layout responds to its size, not the viewport's — essential once the same tile appears in two different spans.
  • Give one tile a full-bleed photo with object-fit: cover and a bottom scrim; one image tile is plenty in a bento, two starts to look like a mood board.

Gotchas — read before shipping

  • Bento grids die on mobile if you only change column count — the tall tiles end up first. Always rewrite grid-template-areas at the breakpoint, not just the columns.
  • grid-auto-rows: 1fr forces equal heights and clips long quotes. Use minmax(140px, auto) so tiles grow with content.
  • Every area name in the map must form a rectangle, or the whole grid-template-areas declaration is invalid and silently dropped.
  • Decorative tiles still receive focus if they contain links. Give purely visual tiles no focusable children.
  • Mixed content sizes tempt you into eight font sizes. Cap at three type scales across the grid or it reads as clutter, not hierarchy.

Browser support

ChromeSafariFirefoxEdge
114+17.5+128+114+

Floor set by oklch(), color-mix(), @property, text-wrap as this demo is written. The core technique itself goes back further — Chrome 57+.

CSS Grid and grid-template-areas are universally supported since 2017. @property (used only for the metric counter) needs Chrome 85 / Safari 16.4 / Firefox 128; without it the number renders statically at its final value.

Search CodeFronts

Loading…