8 CSS Brutalist Designs

Selected Work Grid

A 2×3 work grid for a graphic designer, built entirely around collision and contrast.

Best fordesigner portfolios, agency case-study indexes, art-school project grids.

CSS + JS MIT licensed
Live Demo Open in tab
Open in playground

The code

<section class="br-swg" aria-label="Selected work portfolio grid demo">
  <div class="card">

    <div class="swg-cursor-dot" data-br-swg-dot aria-hidden="true"></div>
    <div class="swg-cursor-ring" data-br-swg-ring aria-hidden="true"></div>
    <div class="swg-cursor-label" data-br-swg-label aria-hidden="true">VIEW</div>

    <div class="hero-type" aria-hidden="true">
      <div class="hero-word hw-selected">SELECTED</div>
      <div class="hero-word hw-work">WORK</div>
      <div class="hero-word hw-year">2025</div>
    </div>

    <div class="stage">

      <div class="cell cell-1">
        <div class="cell-vis" aria-hidden="true"></div>
        <div class="cell-inner">
          <div class="cell-num">01 / 06</div>
          <div class="cell-title">BRAND<br />SYSTEM</div>
          <div class="cell-tag">Identity · 2024</div>
        </div>
      </div>

      <div class="cell cell-2">
        <div class="cell-vis" aria-hidden="true"></div>
        <div class="cell-inner">
          <div class="cell-num">02 / 06</div>
          <div class="cell-title">TYPE<br />MOTION</div>
          <div class="cell-tag">Animation · 2025</div>
        </div>
      </div>

      <div class="cell cell-3">
        <div class="cell-vis" aria-hidden="true">✕</div>
        <div class="cell-inner">
          <div class="cell-num">03 / 06</div>
          <div class="cell-title">WEB<br />CAMPAIGN</div>
          <div class="cell-tag">Digital · 2025</div>
        </div>
      </div>

      <div class="cell cell-4">
        <div class="cell-vis" aria-hidden="true">
          <div class="bar-set">
            <div class="bar-item b1"></div>
            <div class="bar-item b2"></div>
            <div class="bar-item b3"></div>
            <div class="bar-item b4"></div>
          </div>
        </div>
        <div class="cell-inner">
          <div class="cell-num">04 / 06</div>
          <div class="cell-title">DATA<br />VISUAL</div>
          <div class="cell-tag">Infographic · 2024</div>
        </div>
      </div>

      <div class="cell cell-5">
        <div class="cell-vis" aria-hidden="true">Aa</div>
        <div class="cell-inner">
          <div class="cell-num">05 / 06</div>
          <div class="cell-title">TYPEFACE<br />DESIGN</div>
          <div class="cell-tag">Typography · 2025</div>
        </div>
      </div>

      <div class="cell cell-6">
        <div class="cell-vis" aria-hidden="true"></div>
        <div class="cell-inner">
          <div class="cell-num">06 / 06</div>
          <div class="cell-title">SPATIAL<br />INSTALL</div>
          <div class="cell-tag">Exhibition · 2025</div>
        </div>
      </div>

    </div>

    <div class="ticker" aria-hidden="true">
      <div class="ticker-inner">
        <span class="ticker-item">Available for work</span><span class="ticker-sep">◆</span>
        <span class="ticker-item">Brand · Motion · Web · Type</span><span class="ticker-sep">◆</span>
        <span class="ticker-item">Based in Amsterdam</span><span class="ticker-sep">◆</span>
        <span class="ticker-item">[email protected]</span><span class="ticker-sep">◆</span>
        <span class="ticker-item">Available for work</span><span class="ticker-sep">◆</span>
        <span class="ticker-item">Brand · Motion · Web · Type</span><span class="ticker-sep">◆</span>
        <span class="ticker-item">Based in Amsterdam</span><span class="ticker-sep">◆</span>
        <span class="ticker-item">[email protected]</span><span class="ticker-sep">◆</span>
      </div>
    </div>

  </div>
</section>
/* ─── 04 Selected Work Grid — collision-typography portfolio ──── */
@import url('https://fonts.googleapis.com/css2?family=Anton&family=Syne:wght@400;700;800&family=Syne+Mono&display=swap');

.br-swg {
  --br-swg-bg: #f2ede6;
  --br-swg-black: #0d0d0d;
  --br-swg-white: #f2ede6;
  --br-swg-lime: #b6ff00;
  --br-swg-pink: #ff2d6b;
  --br-swg-blue: #0040ff;

  position: relative;
  width: 100%;
  height: 720px;
  background: var(--br-swg-bg);
  font-family: 'Syne', sans-serif;
  overflow: hidden;
  box-sizing: border-box;
}

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

.br-swg .card {
  position: absolute;
  inset: 0;
}

/* Custom cursor — scoped to wrapper, doesn't hijack global cursor */
.br-swg .swg-cursor-dot,
.br-swg .swg-cursor-ring,
.br-swg .swg-cursor-label {
  position: absolute;
  pointer-events: none;
  display: none;
}
.br-swg.cursor-active .swg-cursor-dot,
.br-swg.cursor-active .swg-cursor-ring,
.br-swg.cursor-active .swg-cursor-label { display: block; }

.br-swg.cursor-active * { cursor: none !important; }

.br-swg .swg-cursor-dot {
  width: 10px; height: 10px;
  background: var(--br-swg-black);
  border-radius: 50%;
  z-index: 9999;
  transform: translate(-50%, -50%);
  transition: width 0.2s, height 0.2s, background 0.2s;
  mix-blend-mode: difference;
}
.br-swg .swg-cursor-ring {
  width: 44px; height: 44px;
  border: 2px solid var(--br-swg-black);
  border-radius: 50%;
  z-index: 9998;
  transform: translate(-50%, -50%);
  transition: width 0.25s, height 0.25s, border-color 0.2s;
  mix-blend-mode: difference;
}
.br-swg .swg-cursor-label {
  z-index: 9997;
  font-family: 'Syne Mono', monospace;
  font-size: 10px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--br-swg-black);
  transform: translate(14px, -6px);
  opacity: 0;
  transition: opacity 0.15s;
  white-space: nowrap;
}
.br-swg.on-work .swg-cursor-dot { width: 60px; height: 60px; background: var(--br-swg-lime); }
.br-swg.on-work .swg-cursor-ring { width: 80px; height: 80px; border-color: var(--br-swg-lime); }
.br-swg.on-work .swg-cursor-label { opacity: 1; }

/* Hero type */
.br-swg .hero-type {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
  overflow: hidden;
}
.br-swg .hero-word {
  font-family: 'Anton', sans-serif;
  position: absolute;
  line-height: 0.88;
  letter-spacing: -0.03em;
  white-space: nowrap;
  user-select: none;
}
.br-swg .hw-selected { color: var(--br-swg-black); font-size: 22vw; top: -0.05em; left: -0.02em; z-index: 1; }
.br-swg .hw-work { color: transparent; font-size: 19vw; bottom: -0.1em; right: -0.02em; z-index: 0;
  -webkit-text-stroke: 2px var(--br-swg-black); }
.br-swg .hw-year { color: var(--br-swg-lime); font-size: 6vw; bottom: 56px; left: 20px; z-index: 3;
  mix-blend-mode: multiply; }

/* Stage grid */
.br-swg .stage {
  position: absolute;
  inset: 0 0 36px 0;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.br-swg .cell {
  position: relative;
  border: 3px solid var(--br-swg-black);
  border-left: none; border-top: none;
  overflow: hidden;
  z-index: 3;
}
.br-swg .cell:nth-child(3n) { border-right: none; }
.br-swg .cell:nth-child(n+4) { border-bottom: none; }

.br-swg .cell-inner {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 20px 22px;
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

.br-swg .cell-1 { background: var(--br-swg-black); border-left: 3px solid var(--br-swg-black); border-top: 3px solid var(--br-swg-black); }
.br-swg .cell-2 { background: var(--br-swg-bg); border-top: 3px solid var(--br-swg-black); }
.br-swg .cell-3 { background: var(--br-swg-pink); border-top: 3px solid var(--br-swg-black); border-right: none; }
.br-swg .cell-4 { background: var(--br-swg-blue); border-left: 3px solid var(--br-swg-black); border-bottom: none; }
.br-swg .cell-5 { background: var(--br-swg-bg); border-bottom: none; }
.br-swg .cell-6 { background: var(--br-swg-lime); border-right: none; border-bottom: none; }

.br-swg .cell:hover .cell-inner { transform: translateY(-8px); }
.br-swg .cell:hover { z-index: 10; }

.br-swg .cell-num {
  font-family: 'Syne Mono', monospace;
  font-size: 10px;
  letter-spacing: 3px;
  margin-bottom: 8px;
  opacity: 0.5;
}
.br-swg .cell-1 .cell-num { color: #555; }
.br-swg .cell-2 .cell-num, .br-swg .cell-5 .cell-num { color: #aaa; }
.br-swg .cell-3 .cell-num { color: rgba(255,255,255,0.5); }
.br-swg .cell-4 .cell-num { color: rgba(255,255,255,0.4); }
.br-swg .cell-6 .cell-num { color: rgba(0,0,0,0.4); }

.br-swg .cell-title {
  font-family: 'Anton', sans-serif;
  font-size: clamp(22px, 2.8vw, 36px);
  line-height: 0.95;
  letter-spacing: 0.01em;
}
.br-swg .cell-1 .cell-title { color: var(--br-swg-white); }
.br-swg .cell-2 .cell-title { color: var(--br-swg-black); }
.br-swg .cell-3 .cell-title { color: var(--br-swg-white); }
.br-swg .cell-4 .cell-title { color: var(--br-swg-lime); }
.br-swg .cell-5 .cell-title { color: var(--br-swg-black); }
.br-swg .cell-6 .cell-title { color: var(--br-swg-black); }

.br-swg .cell-tag {
  font-size: 9px;
  letter-spacing: 3px;
  text-transform: uppercase;
  margin-top: 8px;
  font-weight: 600;
}
.br-swg .cell-1 .cell-tag { color: var(--br-swg-lime); }
.br-swg .cell-2 .cell-tag { color: #888; }
.br-swg .cell-3 .cell-tag { color: rgba(255,255,255,0.7); }
.br-swg .cell-4 .cell-tag { color: rgba(255,255,255,0.6); }
.br-swg .cell-5 .cell-tag { color: #999; }
.br-swg .cell-6 .cell-tag { color: rgba(0,0,0,0.5); }

.br-swg .cell-vis { position: absolute; pointer-events: none; }

.br-swg .cell-1 .cell-vis {
  width: 120px; height: 120px;
  border-radius: 50%;
  border: 3px solid #2a2a2a;
  top: 20px; right: 20px;
}
.br-swg .cell-1 .cell-vis::after {
  content: '';
  width: 60px; height: 60px;
  border-radius: 50%;
  background: var(--br-swg-lime);
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
}

.br-swg .cell-2 .cell-vis {
  width: 100%; height: 100%;
  top: 0; left: 0;
  background: linear-gradient(135deg, transparent 48%, #ddd 48%, #ddd 52%, transparent 52%);
}

.br-swg .cell-3 .cell-vis {
  top: 16px; right: 16px;
  font-family: 'Anton', sans-serif;
  font-size: 80px;
  color: rgba(255,255,255,0.15);
  line-height: 1;
}

.br-swg .cell-4 .cell-vis { top: 20px; left: 20px; right: 20px; }
.br-swg .bar-set { display: flex; flex-direction: column; gap: 6px; }
.br-swg .bar-item { height: 4px; background: rgba(255,255,255,0.15); position: relative; }
.br-swg .bar-item::before {
  content: '';
  position: absolute; left: 0; top: 0; height: 100%;
  background: var(--br-swg-lime);
}
.br-swg .b1::before { width: 80%; }
.br-swg .b2::before { width: 55%; }
.br-swg .b3::before { width: 92%; }
.br-swg .b4::before { width: 40%; }

.br-swg .cell-5 .cell-vis {
  top: 10px; left: 16px;
  font-family: 'Anton', sans-serif;
  font-size: 100px;
  color: rgba(0,0,0,0.05);
  line-height: 1;
  letter-spacing: -5px;
}

.br-swg .cell-6 .cell-vis {
  top: 0; left: 0; right: 0; bottom: 0;
  background-image: radial-gradient(circle, rgba(0,0,0,0.2) 1.5px, transparent 1.5px);
  background-size: 20px 20px;
}

.br-swg .cell::after {
  content: '→';
  position: absolute;
  top: 20px; right: 22px;
  font-family: 'Anton', sans-serif;
  font-size: 28px;
  opacity: 0;
  transition: opacity 0.2s, transform 0.2s;
  transform: translateX(-8px);
  pointer-events: none;
}
.br-swg .cell-1::after { color: var(--br-swg-lime); }
.br-swg .cell-2::after, .br-swg .cell-5::after { color: var(--br-swg-black); }
.br-swg .cell-3::after { color: white; }
.br-swg .cell-4::after { color: var(--br-swg-lime); }
.br-swg .cell-6::after { color: var(--br-swg-black); }
.br-swg .cell:hover::after { opacity: 1; transform: translateX(0); }

/* Ticker — absolute to wrapper, not viewport */
.br-swg .ticker {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  background: var(--br-swg-black);
  padding: 7px 0;
  overflow: hidden;
  z-index: 20;
  border-top: 3px solid var(--br-swg-black);
  pointer-events: none;
}
.br-swg .ticker-inner {
  display: flex;
  gap: 0;
  animation: br-swg-ticker 18s linear infinite;
  white-space: nowrap;
}
@keyframes br-swg-ticker { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.br-swg .ticker-item {
  font-family: 'Syne Mono', monospace;
  font-size: 10px;
  letter-spacing: 4px;
  text-transform: uppercase;
  color: var(--br-swg-lime);
  padding: 0 32px;
}
.br-swg .ticker-sep { color: #333; padding: 0; font-family: 'Syne Mono', monospace; font-size: 10px; }

@media (prefers-reduced-motion: reduce) {
  .br-swg .ticker-inner,
  .br-swg .cell-inner,
  .br-swg .cell::after { animation: none !important; transition: none !important; }
}
(() => {
  const root = document.querySelector('.br-swg');
  if (!root) return;
  const dot = root.querySelector('[data-br-swg-dot]');
  const ring = root.querySelector('[data-br-swg-ring]');
  const label = root.querySelector('[data-br-swg-label]');
  if (!dot || !ring || !label) return;

  let mx = 0, my = 0, rx = 0, ry = 0, rafId = null;

  root.addEventListener('mouseenter', () => root.classList.add('cursor-active'));
  root.addEventListener('mouseleave', () => {
    root.classList.remove('cursor-active');
    root.classList.remove('on-work');
    if (rafId) { cancelAnimationFrame(rafId); rafId = null; }
  });

  root.addEventListener('mousemove', e => {
    const rect = root.getBoundingClientRect();
    mx = e.clientX - rect.left;
    my = e.clientY - rect.top;
    dot.style.left = mx + 'px';
    dot.style.top = my + 'px';
    label.style.left = mx + 'px';
    label.style.top = my + 'px';
    if (!rafId) rafId = requestAnimationFrame(lerpRing);
  });

  function lerpRing() {
    rx += (mx - rx) * 0.14;
    ry += (my - ry) * 0.14;
    ring.style.left = rx + 'px';
    ring.style.top = ry + 'px';
    if (Math.abs(mx - rx) > 0.5 || Math.abs(my - ry) > 0.5) {
      rafId = requestAnimationFrame(lerpRing);
    } else {
      rafId = null;
    }
  }

  root.querySelectorAll('.cell').forEach(cell => {
    cell.addEventListener('mouseenter', () => root.classList.add('on-work'));
    cell.addEventListener('mouseleave', () => root.classList.remove('on-work'));
  });
})();

Search CodeFronts

Loading…