12 CSS Retro UI Designs08 / 12

CSS + JSMIT licensed

ASCII Art Web Interface Code

A live, typeable bash shell with an ASCII logo, ANSI-coloured output and a blinking caret — type real commands (help, ls, neofetch, cowsay, echo, clear) and watch them execute. The phosphor look, window chrome and caret are pure CSS; a tiny vanilla-JS interpreter drives the interactivity. IBM Plex Mono on a hatched dark room.

Published

Live Demo
Try it

The code

<div class="ret-08">
  <div class="ret-08__term">
    <div class="ret-08__bar"><i></i><i></i><i></i><span>guest@codefronts: ~/retro — bash</span></div>
    <div class="ret-08__body" id="ret-08-body">
<pre>   ___          _      ___              _
  / __|___  ___| |___ / __|_ _ ___ _ _| |_ ___
 | (__/ _ \/ _` / -_) _/ '_/ _ \ ' \  _(_-<
  \___\___/\__,_\___\__|_| \___/_||_\__/__/</pre>
      <div class="l"><span class="d">Last login: Tue Jun 03 on ttys001</span></div>
      <div class="l"><span class="d"># Type a command and hit Enter. Try: <span class="y">help</span>, <span class="y">ls</span>, <span class="y">neofetch</span>, <span class="y">cowsay hi</span></span></div>
      <div id="ret-08-out"></div>
      <div class="ret-08__input-line">
        <span class="ret-08__ps1">guest@codefronts<span class="p">:~$</span></span>
        <span class="ret-08__typed" id="ret-08-typed"></span><span class="ret-08__cur"></span>
      </div>
    </div>
  </div>
</div>
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;700&display=swap');

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

.ret-08 ::selection {
  background: #ffaf00;
  color: #0c0c0c;
}

.ret-08 {
  --bg: #0c0c0c;
  --panel: #161616;
  --fg: #e4e4e4;
  --green: #33d17a;
  --blue: #5c9eff;
  --yellow: #ffaf00;
  --red: #f25f5c;
  --magenta: #c264f0;
  --dim: #6a6a6a;
  font-family: 'IBM Plex Mono',monospace;
  background: repeating-linear-gradient(45deg,#0a0a0a 0 12px,#0c0c0c 12px 24px);
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: clamp(12px,3vw,40px);
  color: var(--fg);
}

.ret-08__term {
  width: min(780px,100%);
  height: min(560px,82vh);
  display: flex;
  flex-direction: column;
  background: var(--bg);
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(0,0,0,.7),0 0 0 1px rgba(255,255,255,.06);
}

.ret-08__bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  background: linear-gradient(180deg,#2a2a2a,#1c1c1c);
  border-bottom: 1px solid #000;
}

.ret-08__bar i {
  width: 12px;
  height: 12px;
  border-radius: 50%;
}

.ret-08__bar i:nth-child(1) {
  background: #ff5f56;
}

.ret-08__bar i:nth-child(2) {
  background: #ffbd2e;
}

.ret-08__bar i:nth-child(3) {
  background: #27c93f;
}

.ret-08__bar span {
  margin-left: 10px;
  font-size: .78rem;
  color: var(--dim);
}

.ret-08__body {
  flex: 1;
  overflow-y: auto;
  padding: 16px 18px;
  font-size: clamp(12px,1.5vw,14px);
  line-height: 1.55;
}

.ret-08__body::-webkit-scrollbar {
  width: 8px;
}

.ret-08__body::-webkit-scrollbar-thumb {
  background: #2a2a2a;
  border-radius: 4px;
}

.ret-08 pre {
  white-space: pre;
  font-family: inherit;
  color: var(--magenta);
  line-height: 1.1;
  font-size: clamp(8px,1.4vw,12px);
  margin-bottom: 8px;
}

.ret-08 .l {
  white-space: pre-wrap;
  word-break: break-word;
}

.ret-08 .g {
  color: var(--green);
}

.ret-08 .b {
  color: var(--blue);
}

.ret-08 .y {
  color: var(--yellow);
}

.ret-08 .r {
  color: var(--red);
}

.ret-08 .m {
  color: var(--magenta);
}

.ret-08 .d {
  color: var(--dim);
}

.ret-08__prompt-l {
  color: var(--green);
  font-weight: 700;
}

.ret-08__prompt-l .p {
  color: var(--blue);
}

.ret-08__input-line {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 4px;
}

.ret-08__ps1 {
  color: var(--green);
  font-weight: 700;
  white-space: nowrap;
}

.ret-08__ps1 .p {
  color: var(--blue);
}

.ret-08__typed {
  color: var(--fg);
}

.ret-08__cur {
  display: inline-block;
  width: 8px;
  height: 1.05em;
  background: var(--fg);
  transform: translateY(2px);
  animation: ret-08-bl 1.1s steps(2) infinite;
}

@keyframes ret-08-bl {
  50% {
    opacity: 0;
  }
}

.ret-08__hint {
  margin-top: 10px;
  color: var(--dim);
  font-size: .74rem;
}

.ret-08 a {
  color: var(--blue);
  text-decoration: underline;
}

@media (prefers-reduced-motion: reduce) {
  .ret-08__cur {
    animation: none;
  }
}
(() => {
  const root = document.querySelector('.ret-08');
  if (!root) return;
  const body = root.querySelector('#ret-08-body');
  const out  = root.querySelector('#ret-08-out');
  const typedEl = root.querySelector('#ret-08-typed');
  let buf = '';
  const esc = s => s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');

  const cmds = {
    help: () => `<span class="g">Available:</span> help · ls · pwd · whoami · date · neofetch · cowsay &lt;text&gt; · echo &lt;text&gt; · clear`,
    ls: () => `<span class="b">projects/</span>  <span class="b">art/</span>  readme.md  <span class="g">retro.sh</span>  .secret`,
    pwd: () => `/home/guest/retro`,
    whoami: () => `guest <span class="d">(uid=1000 groups=demos,retro)</span>`,
    date: () => new Date().toString(),
    neofetch: () => `<span class="m">  ___   </span> <span class="g">guest</span>@<span class="g">codefronts</span>
<span class="m"> / _ \\  </span> <span class="y">OS:</span>    RetroLinux 8.6 "Phosphor"
<span class="m">| | | | </span> <span class="y">Shell:</span> bash 5.1 · pure CSS+JS
<span class="m">| |_| | </span> <span class="y">Term:</span>  codefronts-term
<span class="m"> \\___/  </span> <span class="y">Theme:</span> ANSI green-on-black`,
    clear: () => { out.innerHTML=''; return null; }
  };

  function run(raw){
    const line = `<div class="l"><span class="ret-08__ps1">guest@codefronts<span class="p">:~$</span></span> ${esc(raw)}</div>`;
    let res = '';
    const trimmed = raw.trim();
    const [c, ...rest] = trimmed.split(/\s+/);
    const arg = rest.join(' ');
    if (trimmed === '') { res=''; }
    else if (c === 'echo') res = esc(arg);
    else if (c === 'cowsay') {
      const t = esc(arg || 'moo');
      const bar = '_'.repeat(t.length + 2);
      const bar2 = '-'.repeat(t.length + 2);
      res = `<span class="y"> ${bar}\n&lt; ${t} &gt;\n ${bar2}\n        \\   ^__^\n         \\  (oo)\\_______\n            (__)\\       )\\/\\\n                ||----w |\n                ||     ||</span>`;
    }
    else if (cmds[c]) { const r = cmds[c](); if (r===null){return;} res = r; }
    else res = `<span class="r">bash: ${esc(c)}: command not found</span> <span class="d">(try 'help')</span>`;
    out.insertAdjacentHTML('beforeend', line + (res!=='' ? `<div class="l">${res}</div>` : ''));
    body.scrollTop = body.scrollHeight;
  }

  window.addEventListener('keydown', (e) => {
    if (e.metaKey || e.ctrlKey || e.altKey) return;
    if (e.key === 'Enter') { run(buf); buf=''; }
    else if (e.key === 'Backspace') { buf = buf.slice(0,-1); e.preventDefault(); }
    else if (e.key.length === 1) { buf += e.key; }
    else return;
    typedEl.textContent = buf;
  });
  // seed one example
  run('neofetch');
})();
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 Retro UI Design 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: ASCII Art Web Interface Code
Source: https://codefronts.com/design-styles/css-retro-designs/ascii-art-web-interface-code/

A live, typeable bash shell with an ASCII logo, ANSI-coloured output and a blinking caret — type real commands (help, ls, neofetch, cowsay, echo, clear) and watch them execute. The phosphor look, window chrome and caret are pure CSS; a tiny vanilla-JS interpreter drives the interactivity. IBM Plex Mono on a hatched dark room.
## HTML
```html
<div class="ret-08">
  <div class="ret-08__term">
    <div class="ret-08__bar"><i></i><i></i><i></i><span>guest@codefronts: ~/retro — bash</span></div>
    <div class="ret-08__body" id="ret-08-body">
<pre>   ___          _      ___              _
  / __|___  ___| |___ / __|_ _ ___ _ _| |_ ___
 | (__/ _ \/ _` / -_) _/ '_/ _ \ ' \  _(_-<
  \___\___/\__,_\___\__|_| \___/_||_\__/__/</pre>
      <div class="l"><span class="d">Last login: Tue Jun 03 on ttys001</span></div>
      <div class="l"><span class="d"># Type a command and hit Enter. Try: <span class="y">help</span>, <span class="y">ls</span>, <span class="y">neofetch</span>, <span class="y">cowsay hi</span></span></div>
      <div id="ret-08-out"></div>
      <div class="ret-08__input-line">
        <span class="ret-08__ps1">guest@codefronts<span class="p">:~$</span></span>
        <span class="ret-08__typed" id="ret-08-typed"></span><span class="ret-08__cur"></span>
      </div>
    </div>
  </div>
</div>
```
## CSS
```css
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;700&display=swap');

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

.ret-08 ::selection {
  background: #ffaf00;
  color: #0c0c0c;
}

.ret-08 {
  --bg: #0c0c0c;
  --panel: #161616;
  --fg: #e4e4e4;
  --green: #33d17a;
  --blue: #5c9eff;
  --yellow: #ffaf00;
  --red: #f25f5c;
  --magenta: #c264f0;
  --dim: #6a6a6a;
  font-family: 'IBM Plex Mono',monospace;
  background: repeating-linear-gradient(45deg,#0a0a0a 0 12px,#0c0c0c 12px 24px);
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: clamp(12px,3vw,40px);
  color: var(--fg);
}

.ret-08__term {
  width: min(780px,100%);
  height: min(560px,82vh);
  display: flex;
  flex-direction: column;
  background: var(--bg);
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(0,0,0,.7),0 0 0 1px rgba(255,255,255,.06);
}

.ret-08__bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  background: linear-gradient(180deg,#2a2a2a,#1c1c1c);
  border-bottom: 1px solid #000;
}

.ret-08__bar i {
  width: 12px;
  height: 12px;
  border-radius: 50%;
}

.ret-08__bar i:nth-child(1) {
  background: #ff5f56;
}

.ret-08__bar i:nth-child(2) {
  background: #ffbd2e;
}

.ret-08__bar i:nth-child(3) {
  background: #27c93f;
}

.ret-08__bar span {
  margin-left: 10px;
  font-size: .78rem;
  color: var(--dim);
}

.ret-08__body {
  flex: 1;
  overflow-y: auto;
  padding: 16px 18px;
  font-size: clamp(12px,1.5vw,14px);
  line-height: 1.55;
}

.ret-08__body::-webkit-scrollbar {
  width: 8px;
}

.ret-08__body::-webkit-scrollbar-thumb {
  background: #2a2a2a;
  border-radius: 4px;
}

.ret-08 pre {
  white-space: pre;
  font-family: inherit;
  color: var(--magenta);
  line-height: 1.1;
  font-size: clamp(8px,1.4vw,12px);
  margin-bottom: 8px;
}

.ret-08 .l {
  white-space: pre-wrap;
  word-break: break-word;
}

.ret-08 .g {
  color: var(--green);
}

.ret-08 .b {
  color: var(--blue);
}

.ret-08 .y {
  color: var(--yellow);
}

.ret-08 .r {
  color: var(--red);
}

.ret-08 .m {
  color: var(--magenta);
}

.ret-08 .d {
  color: var(--dim);
}

.ret-08__prompt-l {
  color: var(--green);
  font-weight: 700;
}

.ret-08__prompt-l .p {
  color: var(--blue);
}

.ret-08__input-line {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 4px;
}

.ret-08__ps1 {
  color: var(--green);
  font-weight: 700;
  white-space: nowrap;
}

.ret-08__ps1 .p {
  color: var(--blue);
}

.ret-08__typed {
  color: var(--fg);
}

.ret-08__cur {
  display: inline-block;
  width: 8px;
  height: 1.05em;
  background: var(--fg);
  transform: translateY(2px);
  animation: ret-08-bl 1.1s steps(2) infinite;
}

@keyframes ret-08-bl {
  50% {
    opacity: 0;
  }
}

.ret-08__hint {
  margin-top: 10px;
  color: var(--dim);
  font-size: .74rem;
}

.ret-08 a {
  color: var(--blue);
  text-decoration: underline;
}

@media (prefers-reduced-motion: reduce) {
  .ret-08__cur {
    animation: none;
  }
}
```

## JavaScript
```js
(() => {
  const root = document.querySelector('.ret-08');
  if (!root) return;
  const body = root.querySelector('#ret-08-body');
  const out  = root.querySelector('#ret-08-out');
  const typedEl = root.querySelector('#ret-08-typed');
  let buf = '';
  const esc = s => s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');

  const cmds = {
    help: () => `<span class="g">Available:</span> help · ls · pwd · whoami · date · neofetch · cowsay &lt;text&gt; · echo &lt;text&gt; · clear`,
    ls: () => `<span class="b">projects/</span>  <span class="b">art/</span>  readme.md  <span class="g">retro.sh</span>  .secret`,
    pwd: () => `/home/guest/retro`,
    whoami: () => `guest <span class="d">(uid=1000 groups=demos,retro)</span>`,
    date: () => new Date().toString(),
    neofetch: () => `<span class="m">  ___   </span> <span class="g">guest</span>@<span class="g">codefronts</span>
<span class="m"> / _ \\  </span> <span class="y">OS:</span>    RetroLinux 8.6 "Phosphor"
<span class="m">| | | | </span> <span class="y">Shell:</span> bash 5.1 · pure CSS+JS
<span class="m">| |_| | </span> <span class="y">Term:</span>  codefronts-term
<span class="m"> \\___/  </span> <span class="y">Theme:</span> ANSI green-on-black`,
    clear: () => { out.innerHTML=''; return null; }
  };

  function run(raw){
    const line = `<div class="l"><span class="ret-08__ps1">guest@codefronts<span class="p">:~$</span></span> ${esc(raw)}</div>`;
    let res = '';
    const trimmed = raw.trim();
    const [c, ...rest] = trimmed.split(/\s+/);
    const arg = rest.join(' ');
    if (trimmed === '') { res=''; }
    else if (c === 'echo') res = esc(arg);
    else if (c === 'cowsay') {
      const t = esc(arg || 'moo');
      const bar = '_'.repeat(t.length + 2);
      const bar2 = '-'.repeat(t.length + 2);
      res = `<span class="y"> ${bar}\n&lt; ${t} &gt;\n ${bar2}\n        \\   ^__^\n         \\  (oo)\\_______\n            (__)\\       )\\/\\\n                ||----w |\n                ||     ||</span>`;
    }
    else if (cmds[c]) { const r = cmds[c](); if (r===null){return;} res = r; }
    else res = `<span class="r">bash: ${esc(c)}: command not found</span> <span class="d">(try 'help')</span>`;
    out.insertAdjacentHTML('beforeend', line + (res!=='' ? `<div class="l">${res}</div>` : ''));
    body.scrollTop = body.scrollHeight;
  }

  window.addEventListener('keydown', (e) => {
    if (e.metaKey || e.ctrlKey || e.altKey) return;
    if (e.key === 'Enter') { run(buf); buf=''; }
    else if (e.key === 'Backspace') { buf = buf.slice(0,-1); e.preventDefault(); }
    else if (e.key.length === 1) { buf += e.key; }
    else return;
    typedEl.textContent = buf;
  });
  // seed one example
  run('neofetch');
})();
```

Techniques used in this demo

Search CodeFronts

Loading…