12 CSS Retro UI Designs 12 / 12

Retro Desktop Portfolio Website Template

A classic desktop-OS portfolio: a System-style menu bar with live clock, desktop folder icons, and stacked windows (about / projects / contact) you can drag and bring-to-focus.

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

The code

<div class="ret-12">
  <div class="ret-12__menubar">
    <span class="apple">❖</span>
    <span>File</span><span>Edit</span><span>View</span><span>Special</span>
    <span class="spacer"><span>◐ 88%</span><span class="clock" id="ret-12-clock">12:00 PM</span></span>
  </div>

  <div class="ret-12__desk" id="ret-12-desk">
    <div class="ret-12__shortcuts">
      <div class="ret-12__sc"><i>📁</i><span>Work</span></div>
      <div class="ret-12__sc"><i>📄</i><span>Resume</span></div>
      <div class="ret-12__sc"><i>🗑️</i><span>Trash</span></div>
    </div>

    <div class="ret-12__window ret-12__about is-focus" data-win>
      <div class="ret-12__titlebar" data-drag><span class="dot r"></span><span class="dot"></span><b>about_me.txt</b><span class="x">▢</span></div>
      <div class="ret-12__content">
        <div class="ret-12__avatar">🧑‍💻</div>
        <h2>Hi, I'm Mara.<small>// CREATIVE DEVELOPER</small></h2>
        <p>I build playful interfaces with a soft spot for old machines. Drag these windows around — focus &amp; drag are tiny vanilla JS, everything else is pure CSS.</p>
        <div class="ret-12__tags"><span>CSS</span><span>Motion</span><span>WebGL</span><span>Type</span><span>Pixels</span></div>
      </div>
    </div>

    <div class="ret-12__window ret-12__projects" data-win>
      <div class="ret-12__titlebar" data-drag><span class="dot r"></span><span class="dot"></span><b>projects</b><span class="x">▢</span></div>
      <div class="ret-12__content">
        <h2 style="font-size:16px">Selected Work</h2>
        <hr class="ret-12__divider">
        <div class="ret-12__proj"><i>🎨</i><div class="meta"><b>Pixel Painter</b><small>Canvas · 2025</small></div><span class="arrow">→</span></div>
        <div class="ret-12__proj"><i>🎹</i><div class="meta"><b>Synth Web Toy</b><small>WebAudio · 2024</small></div><span class="arrow">→</span></div>
        <div class="ret-12__proj"><i>🌀</i><div class="meta"><b>CRT Shader Lab</b><small>GLSL · 2024</small></div><span class="arrow">→</span></div>
      </div>
    </div>

    <div class="ret-12__window ret-12__contact" data-win>
      <div class="ret-12__titlebar" data-drag><span class="dot r"></span><span class="dot"></span><b>contact</b><span class="x">▢</span></div>
      <div class="ret-12__content">
        <a href="#">→ [email protected]</a>
        <a href="#">→ github.com/mara</a>
        <a href="#">→ dribbble.com/mara</a>
        <a href="#">→ read.cv/mara</a>
      </div>
    </div>

    <div class="ret-12__hint">▲ drag any title bar · click to focus ▲</div>
  </div>
</div>
@import url('https://fonts.googleapis.com/css2?family=Chicago&family=Pixelify+Sans:wght@400;700&family=Space+Mono:wght@400;700&display=swap');

.ret-12, .ret-12 *, .ret-12 *::before, .ret-12 *::after { box-sizing: border-box; margin: 0; padding: 0; }
.ret-12 ::selection{background:#000;color:#d6f5e3}

.ret-12{
  --bg:#3a6b5e;
  --win:#e8e4d8;
  --ink:#1a1a1a;
  --bar:#1a1a1a;
  --accent:#ff5a3c;
  --accent2:#3c7dff;
  --line:#1a1a1a;
  font-family:'Space Mono',monospace;
  background:var(--bg);
  background-image:radial-gradient(rgba(255,255,255,.06) 1px,transparent 1px);
  background-size:6px 6px;
  min-height:100vh;position:relative;overflow:hidden;color:var(--ink);
  padding:10px;
}
/* menu bar */
.ret-12__menubar{display:flex;align-items:center;gap:18px;background:var(--win);border:2px solid var(--ink);padding:5px 14px;
  box-shadow:3px 3px 0 var(--ink);font-family:'Pixelify Sans';font-size:15px;position:relative;z-index:100}
.ret-12__menubar .apple{font-weight:700}
.ret-12__menubar span{cursor:default}
.ret-12__menubar .spacer{margin-left:auto;font-size:13px;display:flex;gap:14px;align-items:center}
.ret-12__menubar .clock{font-family:'Space Mono';font-size:12px}

.ret-12__desk{position:relative;height:calc(100vh - 70px);margin-top:10px}

/* desktop folder icons */
.ret-12__shortcuts{position:absolute;top:6px;right:6px;display:flex;flex-direction:column;gap:18px;z-index:1}
.ret-12__sc{width:74px;text-align:center;cursor:pointer;color:var(--win);text-shadow:1px 1px 0 #000}
.ret-12__sc i{display:block;font-size:30px;filter:drop-shadow(2px 2px 0 rgba(0,0,0,.4))}
.ret-12__sc span{font-size:11px;font-family:'Pixelify Sans';display:inline-block;margin-top:3px;padding:1px 4px}
.ret-12__sc:hover span{background:var(--ink);color:var(--win)}

/* windows */
.ret-12__window{position:absolute;background:var(--win);border:2px solid var(--ink);box-shadow:5px 5px 0 rgba(0,0,0,.5);
  display:flex;flex-direction:column;min-width:240px}
.ret-12__window.is-focus{box-shadow:7px 7px 0 var(--ink);z-index:50}
.ret-12__titlebar{display:flex;align-items:center;gap:8px;background:var(--bar);color:var(--win);padding:5px 8px;cursor:grab;user-select:none}
.ret-12__titlebar.is-drag{cursor:grabbing}
.ret-12__titlebar .dot{width:13px;height:13px;border:2px solid var(--win);border-radius:50%;flex:0 0 auto}
.ret-12__titlebar .dot.r{background:var(--accent)}
.ret-12__titlebar b{font-family:'Pixelify Sans';font-size:14px;letter-spacing:.02em;flex:1;
  background:repeating-linear-gradient(var(--win) 0 1px,transparent 1px 3px);padding:2px 8px;text-align:center;color:var(--win)}
.ret-12__titlebar .x{margin-left:auto}
.ret-12__content{padding:16px;font-size:12px;line-height:1.55}
.ret-12__content h2{font-family:'Pixelify Sans';font-size:20px;margin-bottom:4px}
.ret-12__content h2 small{display:block;font-family:'Space Mono';font-size:11px;color:#5a6b64;letter-spacing:.1em;margin-top:4px}
.ret-12__content p{color:#3a3a3a}
.ret-12__divider{border:0;border-top:2px dashed var(--ink);margin:12px 0}

/* about window */
.ret-12__about{width:300px;top:18px;left:14px}
.ret-12__avatar{width:64px;height:64px;border:2px solid var(--ink);float:left;margin:0 14px 8px 0;
  background:repeating-conic-gradient(var(--accent) 0 90deg,var(--accent2) 0 180deg) 0 0/16px 16px;display:grid;place-items:center;font-size:30px;background-blend-mode:multiply}
.ret-12__tags{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px;clear:both}
.ret-12__tags span{font-size:10px;border:1.5px solid var(--ink);padding:3px 7px;font-family:'Pixelify Sans'}

/* projects window */
.ret-12__projects{width:330px;top:120px;left:230px}
@media(max-width:680px){.ret-12__projects{left:14px;top:300px}}
.ret-12__proj{display:flex;align-items:center;gap:10px;border:1.5px solid var(--ink);padding:9px;margin-bottom:8px;cursor:pointer;transition:transform .1s,background .1s}
.ret-12__proj:hover{transform:translate(-2px,-2px);background:#fff;box-shadow:3px 3px 0 var(--ink)}
.ret-12__proj i{font-size:22px}
.ret-12__proj .meta b{font-family:'Pixelify Sans';font-size:13px;display:block}
.ret-12__proj .meta small{font-size:10px;color:#5a6b64}
.ret-12__proj .arrow{margin-left:auto;font-weight:700}

/* contact window */
.ret-12__contact{width:248px;top:330px;left:30px}
@media(max-width:680px){.ret-12__contact{display:none}}
.ret-12__contact a{display:block;color:var(--accent2);text-decoration:none;border-bottom:1px dotted var(--accent2);padding:4px 0;font-size:12px}
.ret-12__contact a:hover{background:var(--accent2);color:#fff;padding-left:6px}

.ret-12__hint{position:absolute;bottom:6px;left:50%;transform:translateX(-50%);font-size:10px;color:rgba(255,255,255,.7);letter-spacing:.1em;z-index:1}

@media(max-width:680px){.ret-12__about{left:14px;width:calc(100% - 60px);max-width:300px}.ret-12__shortcuts{display:none}}
@media (prefers-reduced-motion: reduce){.ret-12 *{transition:none !important}}
(() => {
  const root = document.querySelector('.ret-12');
  if (!root) return;
  const desk = root.querySelector('#ret-12-desk');
  const wins = Array.from(root.querySelectorAll('[data-win]'));
  let z = 50;

  function focus(win){
    wins.forEach(w => w.classList.remove('is-focus'));
    win.classList.add('is-focus');
    win.style.zIndex = ++z;
  }
  wins.forEach(win => {
    win.addEventListener('mousedown', () => focus(win), true);
    const bar = win.querySelector('[data-drag]');
    let sx, sy, ox, oy, dragging = false;
    const start = (cx, cy) => {
      dragging = true; focus(win);
      const r = win.getBoundingClientRect();
      const d = desk.getBoundingClientRect();
      ox = r.left - d.left; oy = r.top - d.top; sx = cx; sy = cy;
      win.style.left = ox + 'px'; win.style.top = oy + 'px'; win.style.right = 'auto';
      bar.classList.add('is-drag');
    };
    const move = (cx, cy) => {
      if (!dragging) return;
      let nx = ox + (cx - sx), ny = oy + (cy - sy);
      const d = desk.getBoundingClientRect();
      nx = Math.max(0, Math.min(nx, d.width - 60));
      ny = Math.max(0, Math.min(ny, d.height - 30));
      win.style.left = nx + 'px'; win.style.top = ny + 'px';
    };
    const end = () => { dragging = false; bar.classList.remove('is-drag'); };
    bar.addEventListener('mousedown', e => { e.preventDefault(); start(e.clientX, e.clientY); });
    window.addEventListener('mousemove', e => move(e.clientX, e.clientY));
    window.addEventListener('mouseup', end);
    bar.addEventListener('touchstart', e => { start(e.touches[0].clientX, e.touches[0].clientY); }, {passive:true});
    window.addEventListener('touchmove', e => { if(dragging){ move(e.touches[0].clientX, e.touches[0].clientY); } }, {passive:true});
    window.addEventListener('touchend', end);
  });

  const clock = root.querySelector('#ret-12-clock');
  const tick = () => {
    const d = new Date();
    let h = d.getHours(), m = String(d.getMinutes()).padStart(2,'0');
    const ap = h >= 12 ? 'PM' : 'AM'; h = h % 12 || 12;
    clock.textContent = `${h}:${m} ${ap}`;
  };
  tick(); setInterval(tick, 10000);
})();

Search CodeFronts

Loading…