Discord's UI looks complex, but its skeleton is one of the cleanest layout exercises in frontend: four columns side by side, each doing one job. If you can build this, you understand 90% of "app shell" layouts. Let me break down exactly how it works — pure HTML and CSS, no JavaScript needed.
This is Day 7 of DesignFromZero, where I rebuild a polished real-world UI from scratch every day.
The four columns
From left to right, Discord is:
- Server rail — the skinny strip of round server icons.
-
Channel list — categories and
# text-channels. - Chat area — the messages, plus the input box at the bottom.
- Member sidebar — who's online.
The whole thing is one flex row:
.app {
display: flex;
height: 100vh;
}
.server-rail { width: 72px; }
.channel-list { width: 240px; }
.chat { flex: 1; } /* takes the rest */
.member-list { width: 240px; }
flex: 1 on the chat column is the key move — the three side columns get fixed widths, and chat absorbs everything left over. Resize the window and only the messages stretch.
The dark palette is the whole vibe
Discord's look is mostly three greys plus one accent. Get these right and it instantly reads as Discord:
:root {
--rail: #1e1f22; /* darkest — server rail */
--sidebar: #2b2d31; /* channels + members */
--chat: #313338; /* lightest — message area */
--blurple: #5865f2; /* the famous accent */
--text: #dbdee1;
--muted: #949ba4;
}
The trick most clones miss: the columns get progressively lighter from left to right. That subtle gradient of greys is what gives the UI depth without a single shadow.
Server icons: the squircle-to-circle hover
Each server icon is a rounded square that morphs toward a circle on hover — a tiny detail that makes it feel alive:
.server-icon {
width: 48px; height: 48px;
border-radius: 24px; /* default: rounded */
transition: border-radius .15s;
display: grid; place-items: center;
}
.server-icon:hover { border-radius: 16px; background: var(--blurple); }
Message rows: a two-column grid
Each message is an avatar on the left and a stack (username + timestamp, then the text) on the right. CSS Grid makes this trivial and keeps every message's text perfectly aligned under the name:
.message {
display: grid;
grid-template-columns: 40px 1fr; /* avatar | content */
gap: 12px;
padding: 4px 16px;
}
.message:hover { background: rgba(0,0,0,.06); } /* row highlight */
That 40px 1fr is the heart of the chat layout — fixed avatar column, flexible text column.
Channel typography
Channels are dim by default and brighten on hover/active — the # is just a literal character with muted color. The "active channel" gets a lighter background pill:
.channel { color: var(--muted); padding: 6px 8px; border-radius: 4px; }
.channel:hover { color: var(--text); background: rgba(255,255,255,.04); }
.channel.active { color: #fff; background: rgba(255,255,255,.08); }
In the live version I built, all four columns are wired up with real-looking servers, categorized channels, message rows with avatars and timestamps, and the online member list.
The takeaway
The lesson here isn't "memorize Discord." It's the pattern: fixed side columns + one flex: 1 content column + a grid for repeating rows. Slack, Notion, VS Code, Linear — they're all variations on this exact skeleton. Build it once and you can build all of them.
👉 See the live clone: https://dev48v.infy.uk/design/day7-discord-channels.html
🌐 All designs: https://dev48v.infy.uk/designfromzero.php
Tomorrow: Slack's input bar — autogrow textarea + rich toolbar.
For further actions, you may consider blocking this person and/or reporting abuse
