30 CSS Grid Layouts29 / 30

Pure CSSMIT licensed

Logo Wall

The 'trusted by' section done properly: an auto-fit wall where hairline dividers between every cell come from a 1px gap over a background color — one declaration replacing the border-collapse puzzle of nth-child edge cases. Logos sit grayscale at 60%, waking to full color on hover.

Published Updated

Live Demo
Try it

The code

<section class="cgl-29" aria-label="Logo wall demo">
  <h3 class="cgl-29__title">Powering front-ends at</h3>
  <ul class="cgl-29__wall">
    <li><a href="#0" style="--f:Georgia,serif"><b>Meridian</b></a></li>
    <li><a href="#0" style="--f:ui-monospace,monospace"><b>hexlab_</b></a></li>
    <li><a href="#0"><b>NORTHBEAM</b></a></li>
    <li><a href="#0" style="--f:Georgia,serif"><b><i>Foundry &amp; Co.</i></b></a></li>
    <li><a href="#0"><b>plexus</b></a></li>
    <li><a href="#0" style="--f:ui-monospace,monospace"><b>[cadence]</b></a></li>
    <li><a href="#0"><b>Waypoint</b></a></li>
    <li><a href="#0" style="--f:Georgia,serif"><b>Aurelia</b></a></li>
  </ul>
</section>
.cgl-29,
.cgl-29 *,
.cgl-29 *::before,
.cgl-29 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.cgl-29 {
  width: 100%;
  min-height: 100vh;
  --paper: oklch(0.97 0.006 90);
  --hairline: oklch(0.86 0.012 90);
  --ink: oklch(0.3 0.02 60);
  font-family: system-ui,sans-serif;
  background: var(--paper);
  padding: 1.8rem 1.4rem;
}

.cgl-29 .cgl-29__title {
  font-size: .72rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  text-align: center;
  color: color-mix(in oklab,var(--ink) 55%,var(--paper));
  margin-block-end: 1.2rem;
}

.cgl-29 .cgl-29__wall {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit,minmax(min(140px,100%),1fr));
  gap: 1px;
  background: var(--hairline);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  overflow: hidden;
}

.cgl-29 .cgl-29__wall li {
  background: var(--paper);
}

.cgl-29 .cgl-29__wall a {
  display: grid;
  place-items: center;
  min-block-size: 76px;
  padding: 1rem;
  text-decoration: none;
  filter: grayscale(1) opacity(.6);
  transition: filter .3s ease;
}

.cgl-29 .cgl-29__wall a:hover,
.cgl-29 .cgl-29__wall a:focus-visible {
  filter: none;
  outline: none;
  background: color-mix(in oklab,var(--hairline) 30%,var(--paper));
}

.cgl-29 .cgl-29__wall b {
  font-family: var(--f,system-ui);
  font-size: 1.02rem;
  letter-spacing: .02em;
  color: var(--ink);
}

@media (prefers-reduced-motion: reduce) {
  .cgl-29 .cgl-29__wall a {
    transition: none;
  }
}
/* No JavaScript — gap:1px over a hairline background draws every divider; grayscale filters unify the marks. */
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 Grid Layout 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: Logo Wall
Source: https://codefronts.com/layouts/css-grid-layouts/logo-wall/

The 'trusted by' section done properly: an auto-fit wall where hairline dividers between every cell come from a 1px gap over a background color — one declaration replacing the border-collapse puzzle of nth-child edge cases. Logos sit grayscale at 60%, waking to full color on hover.
## HTML
```html
<section class="cgl-29" aria-label="Logo wall demo">
  <h3 class="cgl-29__title">Powering front-ends at</h3>
  <ul class="cgl-29__wall">
    <li><a href="#0" style="--f:Georgia,serif"><b>Meridian</b></a></li>
    <li><a href="#0" style="--f:ui-monospace,monospace"><b>hexlab_</b></a></li>
    <li><a href="#0"><b>NORTHBEAM</b></a></li>
    <li><a href="#0" style="--f:Georgia,serif"><b><i>Foundry &amp; Co.</i></b></a></li>
    <li><a href="#0"><b>plexus</b></a></li>
    <li><a href="#0" style="--f:ui-monospace,monospace"><b>[cadence]</b></a></li>
    <li><a href="#0"><b>Waypoint</b></a></li>
    <li><a href="#0" style="--f:Georgia,serif"><b>Aurelia</b></a></li>
  </ul>
</section>
```
## CSS
```css
.cgl-29,
.cgl-29 *,
.cgl-29 *::before,
.cgl-29 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.cgl-29 {
  width: 100%;
  min-height: 100vh;
  --paper: oklch(0.97 0.006 90);
  --hairline: oklch(0.86 0.012 90);
  --ink: oklch(0.3 0.02 60);
  font-family: system-ui,sans-serif;
  background: var(--paper);
  padding: 1.8rem 1.4rem;
}

.cgl-29 .cgl-29__title {
  font-size: .72rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  text-align: center;
  color: color-mix(in oklab,var(--ink) 55%,var(--paper));
  margin-block-end: 1.2rem;
}

.cgl-29 .cgl-29__wall {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit,minmax(min(140px,100%),1fr));
  gap: 1px;
  background: var(--hairline);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  overflow: hidden;
}

.cgl-29 .cgl-29__wall li {
  background: var(--paper);
}

.cgl-29 .cgl-29__wall a {
  display: grid;
  place-items: center;
  min-block-size: 76px;
  padding: 1rem;
  text-decoration: none;
  filter: grayscale(1) opacity(.6);
  transition: filter .3s ease;
}

.cgl-29 .cgl-29__wall a:hover,
.cgl-29 .cgl-29__wall a:focus-visible {
  filter: none;
  outline: none;
  background: color-mix(in oklab,var(--hairline) 30%,var(--paper));
}

.cgl-29 .cgl-29__wall b {
  font-family: var(--f,system-ui);
  font-size: 1.02rem;
  letter-spacing: .02em;
  color: var(--ink);
}

@media (prefers-reduced-motion: reduce) {
  .cgl-29 .cgl-29__wall a {
    transition: none;
  }
}
```

## JavaScript
```js
/* No JavaScript — gap:1px over a hairline background draws every divider; grayscale filters unify the marks. */
```

How this works

The divider trick: the wall's background is the hairline color, gap: 1px, and every cell paints its own opaque background — the gap lets the wall's background show through as perfect 1px rules between ALL cells, at every column count auto-fit produces. No :nth-child(4n) border surgery, no doubled edges, no breakage when the count changes.

Cells are display: grid; place-items: center with a min-block-size keeping the wall's rhythm. The monochrome treatment is filter: grayscale(1) opacity(.6), lifting on hover/focus-within with a transition — the standard restraint that keeps 24 competing brand colours from shouting over your page. Logos here are styled wordmarks; swap in SVG logos with max-inline-size: 60%.

Make it yours

  • Divider color = the wall's background — one custom property.
  • Remove OUTER hairlines (as here) with overflow:hidden + radius, or keep them by padding the wall 1px.
  • Swap wordmarks for <img>/<svg> capped at max-inline-size:60%; max-block-size:28px.
  • Loop a marquee variant by wrapping this wall in the scroll-snap rail from demo 27.

Gotchas — read before shipping

  • Cells MUST be opaque — a transparent cell reveals hairline color as a full block, not a rule.
  • grayscale(1) on low-contrast logos can fall below visible contrast — check each mark at 60% opacity.
  • Don't animate filter on huge walls; it repaints. This scale is fine; hundreds of cells aren't.

Browser support

ChromeSafariFirefoxEdge
111+16.2+113+111+

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

The whole trick is original grid + filters — universally deployable, including the divider technique.

Techniques used in this demo

Search CodeFronts

Loading…