05 / 32
All 32 in 32 Tailwind CSS Tabs
- 01Tailwind CSS Tabs with Sliding Underline Indicator
- 02Neon Glow Tailwind Tabs with Per-Tab Accent Colors
- 03Neo-Brutalist Tailwind Tabs with Press Effect
- 04Color-Coded Tailwind CSS Tabs Component
- 05VS Code Style File Tabs in Tailwind CSS
- 06iOS Segmented Control in Tailwind CSS
- 07Bento Grid Card Tabs in Tailwind CSS
- 08Vertical Tabs with Timeline Progress in Tailwind CSS
- 09Terminal Window Tabs in Tailwind CSS (Retro CRT)
- 10Expanding Icon Tabs in Tailwind CSS
- 11Typewriter Animation Tabs in Tailwind CSS
- 12Tailwind Tabs with Particle Burst Animation
- 13Animated Counter Tabs in Tailwind CSS (Type Specimen)
- 14Oversized Cropped Text Tabs in Tailwind CSS
- 15Tailwind Sidebar Navigation with Sliding Indicator
- 16Tailwind Bottom Navigation Bar with Expanding Labels
- 17Variable Font Weight Tabs in Tailwind CSS
- 18Uppercase Tabs with Thick Sliding Bar in Tailwind CSS
- 19Drop Cap Initial Letter Tabs in Tailwind CSS
- 20Industrial Stencil Tabs in Tailwind CSS
- 21Bracket Selection Tabs in Tailwind CSS
- 22Bauhaus Color Block Tabs in Tailwind CSS
- 23Inverted Rubber Stamp Tabs in Tailwind CSS
- 24Outlined Tabs with Corner Markers in Tailwind CSS
- 25Tailwind Pill Tab Bar with Icons
- 26Risograph Print Effect Tabs in Tailwind CSS
- 27Animated SVG Underline Tabs in Tailwind CSS
- 28Font Specimen Glyph Tabs in Tailwind CSS
- 29Sliding Pill Tabs with Icons in Tailwind CSS
- 30Folded Corner Tabs in Tailwind CSS (clip-path)
- 31Bookmark Ribbon Navigation in Tailwind CSS
- 32Neumorphic Inset Tabs in Tailwind CSS
VS Code Style File Tabs in Tailwind CSS
IDE file tabs with language dots, an accent stripe on the active tab and an editor body that merges with it. The port adds what a real editor shows: a breadcrumb, CSS-counter line numbers that don't copy, a close glyph on the active tab and a status bar — all from utilities.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="ttb-05 group/tabs grid min-h-svh w-full place-items-center bg-ttb05-bg px-5 py-14 font-ttb05-mono text-ttb05-ink" aria-label="VS Code style file tabs demo">
<div class="grid w-full justify-items-center gap-7">
<div class="w-full max-w-xl overflow-hidden rounded-xl bg-ttb05-editor shadow-[0_24px_60px_-20px_rgb(0_0_0/0.7)] ring-1 ring-white/8">
<div role="radiogroup" aria-label="Open files" class="flex overflow-x-auto border-b border-ttb05-line bg-ttb05-chrome [scrollbar-width:none]">
<label class="group/tab relative -mb-px flex min-h-11 flex-none cursor-pointer items-center gap-2 border-r border-b border-r-ttb05-line border-b-transparent px-4 text-[12.5px] text-ttb05-mut transition-colors before:absolute before:inset-x-0 before:top-0 before:h-0.5 hover:bg-white/4 hover:text-ttb05-ink has-checked:border-b-ttb05-editor has-checked:bg-ttb05-editor has-checked:text-ttb05-ink has-checked:before:bg-ttb05-acc has-focus-visible:outline-1 has-focus-visible:-outline-offset-4 has-focus-visible:outline-dashed has-focus-visible:outline-ttb05-acc"><input class="sr-only" type="radio" name="ttb05" id="ttb05-r1" checked><span aria-hidden="true" class="size-2 rounded-full bg-ttb05-ts"></span>app.tsx<span aria-hidden="true" class="ml-1 text-ttb05-mut opacity-0 group-has-checked/tab:opacity-100">×</span></label>
<label class="group/tab relative -mb-px flex min-h-11 flex-none cursor-pointer items-center gap-2 border-r border-b border-r-ttb05-line border-b-transparent px-4 text-[12.5px] text-ttb05-mut transition-colors before:absolute before:inset-x-0 before:top-0 before:h-0.5 hover:bg-white/4 hover:text-ttb05-ink has-checked:border-b-ttb05-editor has-checked:bg-ttb05-editor has-checked:text-ttb05-ink has-checked:before:bg-ttb05-acc has-focus-visible:outline-1 has-focus-visible:-outline-offset-4 has-focus-visible:outline-dashed has-focus-visible:outline-ttb05-acc"><input class="sr-only" type="radio" name="ttb05" id="ttb05-r2"><span aria-hidden="true" class="size-2 rounded-full bg-ttb05-js"></span>config.js<span aria-hidden="true" class="ml-1 text-ttb05-mut opacity-0 group-has-checked/tab:opacity-100">×</span></label>
<label class="group/tab relative -mb-px flex min-h-11 flex-none cursor-pointer items-center gap-2 border-r border-b border-r-ttb05-line border-b-transparent px-4 text-[12.5px] text-ttb05-mut transition-colors before:absolute before:inset-x-0 before:top-0 before:h-0.5 hover:bg-white/4 hover:text-ttb05-ink has-checked:border-b-ttb05-editor has-checked:bg-ttb05-editor has-checked:text-ttb05-ink has-checked:before:bg-ttb05-acc has-focus-visible:outline-1 has-focus-visible:-outline-offset-4 has-focus-visible:outline-dashed has-focus-visible:outline-ttb05-acc"><input class="sr-only" type="radio" name="ttb05" id="ttb05-r3"><span aria-hidden="true" class="size-2 rounded-full bg-ttb05-css"></span>styles.css<span aria-hidden="true" class="ml-1 text-ttb05-mut opacity-0 group-has-checked/tab:opacity-100">×</span></label>
</div>
<div class="min-h-40 py-3 text-[12.5px] leading-[1.75]">
<div class="hidden group-has-[#ttb05-r1:checked]/tabs:block"><p class="px-4 pb-2 text-[11px] text-ttb05-mut">src › app.tsx</p><code class="block [counter-reset:ttb05] [&>span]:block [&>span]:pr-4 [&>span]:whitespace-pre [&>span]:[counter-increment:ttb05] [&>span]:before:mr-4 [&>span]:before:inline-block [&>span]:before:w-8 [&>span]:before:text-right [&>span]:before:text-ttb05-lineno [&>span]:before:select-none [&>span]:before:content-[counter(ttb05)]"><span><span class="text-ttb05-kw">import</span> { Shell } <span class="text-ttb05-kw">from</span> <span class="text-ttb05-str">'./shell'</span>;</span><span> </span><span><span class="text-ttb05-kw">export default function</span> <span class="text-ttb05-fn">App</span>() {</span><span> <span class="text-ttb05-kw">return</span> <<span class="text-ttb05-tag">Shell</span> />;</span><span>}</span></code></div>
<div class="hidden group-has-[#ttb05-r2:checked]/tabs:block"><p class="px-4 pb-2 text-[11px] text-ttb05-mut">config.js</p><code class="block [counter-reset:ttb05] [&>span]:block [&>span]:pr-4 [&>span]:whitespace-pre [&>span]:[counter-increment:ttb05] [&>span]:before:mr-4 [&>span]:before:inline-block [&>span]:before:w-8 [&>span]:before:text-right [&>span]:before:text-ttb05-lineno [&>span]:before:select-none [&>span]:before:content-[counter(ttb05)]"><span>module.exports = {</span><span> <span class="text-ttb05-fn">port</span>: <span class="text-ttb05-num">3000</span>,</span><span> <span class="text-ttb05-fn">strict</span>: <span class="text-ttb05-kw">true</span>,</span><span>};</span></code></div>
<div class="hidden group-has-[#ttb05-r3:checked]/tabs:block"><p class="px-4 pb-2 text-[11px] text-ttb05-mut">src › styles.css</p><code class="block [counter-reset:ttb05] [&>span]:block [&>span]:pr-4 [&>span]:whitespace-pre [&>span]:[counter-increment:ttb05] [&>span]:before:mr-4 [&>span]:before:inline-block [&>span]:before:w-8 [&>span]:before:text-right [&>span]:before:text-ttb05-lineno [&>span]:before:select-none [&>span]:before:content-[counter(ttb05)]"><span><span class="text-ttb05-tag">:root</span> {</span><span> <span class="text-ttb05-fn">color-scheme</span>: dark;</span><span> <span class="text-ttb05-fn">--radius</span>: <span class="text-ttb05-num">12px</span>;</span><span>}</span></code></div>
</div>
<div class="flex justify-between bg-ttb05-acc-deep px-3.5 py-1 font-ttb05-sans text-[11px] text-white"><span>main</span><span>UTF-8 · Spaces: 2</span></div>
</div>
<p aria-hidden="true" class="rounded-full border border-white/10 px-3.5 py-2 text-[11.5px] text-ttb05-mut">-mb-px merge · has-checked:before:bg-acc · counter() gutter</p>
</div>
</section><section class="ttb-05 group/tabs grid min-h-svh w-full place-items-center bg-ttb05-bg px-5 py-14 font-ttb05-mono text-ttb05-ink" aria-label="VS Code style file tabs demo">
<div class="grid w-full justify-items-center gap-7">
<div class="w-full max-w-xl overflow-hidden rounded-xl bg-ttb05-editor shadow-[0_24px_60px_-20px_rgb(0_0_0/0.7)] ring-1 ring-white/8">
<div role="radiogroup" aria-label="Open files" class="flex overflow-x-auto border-b border-ttb05-line bg-ttb05-chrome [scrollbar-width:none]">
<label class="group/tab relative -mb-px flex min-h-11 flex-none cursor-pointer items-center gap-2 border-r border-b border-r-ttb05-line border-b-transparent px-4 text-[12.5px] text-ttb05-mut transition-colors before:absolute before:inset-x-0 before:top-0 before:h-0.5 hover:bg-white/4 hover:text-ttb05-ink has-checked:border-b-ttb05-editor has-checked:bg-ttb05-editor has-checked:text-ttb05-ink has-checked:before:bg-ttb05-acc has-focus-visible:outline-1 has-focus-visible:-outline-offset-4 has-focus-visible:outline-dashed has-focus-visible:outline-ttb05-acc"><input class="sr-only" type="radio" name="ttb05" id="ttb05-r1" checked><span aria-hidden="true" class="size-2 rounded-full bg-ttb05-ts"></span>app.tsx<span aria-hidden="true" class="ml-1 text-ttb05-mut opacity-0 group-has-checked/tab:opacity-100">×</span></label>
<label class="group/tab relative -mb-px flex min-h-11 flex-none cursor-pointer items-center gap-2 border-r border-b border-r-ttb05-line border-b-transparent px-4 text-[12.5px] text-ttb05-mut transition-colors before:absolute before:inset-x-0 before:top-0 before:h-0.5 hover:bg-white/4 hover:text-ttb05-ink has-checked:border-b-ttb05-editor has-checked:bg-ttb05-editor has-checked:text-ttb05-ink has-checked:before:bg-ttb05-acc has-focus-visible:outline-1 has-focus-visible:-outline-offset-4 has-focus-visible:outline-dashed has-focus-visible:outline-ttb05-acc"><input class="sr-only" type="radio" name="ttb05" id="ttb05-r2"><span aria-hidden="true" class="size-2 rounded-full bg-ttb05-js"></span>config.js<span aria-hidden="true" class="ml-1 text-ttb05-mut opacity-0 group-has-checked/tab:opacity-100">×</span></label>
<label class="group/tab relative -mb-px flex min-h-11 flex-none cursor-pointer items-center gap-2 border-r border-b border-r-ttb05-line border-b-transparent px-4 text-[12.5px] text-ttb05-mut transition-colors before:absolute before:inset-x-0 before:top-0 before:h-0.5 hover:bg-white/4 hover:text-ttb05-ink has-checked:border-b-ttb05-editor has-checked:bg-ttb05-editor has-checked:text-ttb05-ink has-checked:before:bg-ttb05-acc has-focus-visible:outline-1 has-focus-visible:-outline-offset-4 has-focus-visible:outline-dashed has-focus-visible:outline-ttb05-acc"><input class="sr-only" type="radio" name="ttb05" id="ttb05-r3"><span aria-hidden="true" class="size-2 rounded-full bg-ttb05-css"></span>styles.css<span aria-hidden="true" class="ml-1 text-ttb05-mut opacity-0 group-has-checked/tab:opacity-100">×</span></label>
</div>
<div class="min-h-40 py-3 text-[12.5px] leading-[1.75]">
<div class="hidden group-has-[#ttb05-r1:checked]/tabs:block"><p class="px-4 pb-2 text-[11px] text-ttb05-mut">src › app.tsx</p><code class="block [counter-reset:ttb05] [&>span]:block [&>span]:pr-4 [&>span]:whitespace-pre [&>span]:[counter-increment:ttb05] [&>span]:before:mr-4 [&>span]:before:inline-block [&>span]:before:w-8 [&>span]:before:text-right [&>span]:before:text-ttb05-lineno [&>span]:before:select-none [&>span]:before:content-[counter(ttb05)]"><span><span class="text-ttb05-kw">import</span> { Shell } <span class="text-ttb05-kw">from</span> <span class="text-ttb05-str">'./shell'</span>;</span><span> </span><span><span class="text-ttb05-kw">export default function</span> <span class="text-ttb05-fn">App</span>() {</span><span> <span class="text-ttb05-kw">return</span> <<span class="text-ttb05-tag">Shell</span> />;</span><span>}</span></code></div>
<div class="hidden group-has-[#ttb05-r2:checked]/tabs:block"><p class="px-4 pb-2 text-[11px] text-ttb05-mut">config.js</p><code class="block [counter-reset:ttb05] [&>span]:block [&>span]:pr-4 [&>span]:whitespace-pre [&>span]:[counter-increment:ttb05] [&>span]:before:mr-4 [&>span]:before:inline-block [&>span]:before:w-8 [&>span]:before:text-right [&>span]:before:text-ttb05-lineno [&>span]:before:select-none [&>span]:before:content-[counter(ttb05)]"><span>module.exports = {</span><span> <span class="text-ttb05-fn">port</span>: <span class="text-ttb05-num">3000</span>,</span><span> <span class="text-ttb05-fn">strict</span>: <span class="text-ttb05-kw">true</span>,</span><span>};</span></code></div>
<div class="hidden group-has-[#ttb05-r3:checked]/tabs:block"><p class="px-4 pb-2 text-[11px] text-ttb05-mut">src › styles.css</p><code class="block [counter-reset:ttb05] [&>span]:block [&>span]:pr-4 [&>span]:whitespace-pre [&>span]:[counter-increment:ttb05] [&>span]:before:mr-4 [&>span]:before:inline-block [&>span]:before:w-8 [&>span]:before:text-right [&>span]:before:text-ttb05-lineno [&>span]:before:select-none [&>span]:before:content-[counter(ttb05)]"><span><span class="text-ttb05-tag">:root</span> {</span><span> <span class="text-ttb05-fn">color-scheme</span>: dark;</span><span> <span class="text-ttb05-fn">--radius</span>: <span class="text-ttb05-num">12px</span>;</span><span>}</span></code></div>
</div>
<div class="flex justify-between bg-ttb05-acc-deep px-3.5 py-1 font-ttb05-sans text-[11px] text-white"><span>main</span><span>UTF-8 · Spaces: 2</span></div>
</div>
<p aria-hidden="true" class="rounded-full border border-white/10 px-3.5 py-2 text-[11.5px] text-ttb05-mut">-mb-px merge · has-checked:before:bg-acc · counter() gutter</p>
</div>
</section>@import "tailwindcss";
@theme {
--color-ttb05-bg: #111114;
--color-ttb05-bg: oklch(0.179 0.006 285.8);
--color-ttb05-editor: #1e1e1e;
--color-ttb05-editor: oklch(0.235 0 0);
--color-ttb05-chrome: #2a2a2a;
--color-ttb05-chrome: oklch(0.285 0 0);
--color-ttb05-line: #161616;
--color-ttb05-line: oklch(0.200 0 0);
--color-ttb05-ink: #ececec;
--color-ttb05-ink: oklch(0.943 0 0);
--color-ttb05-mut: #a3a3a3;
--color-ttb05-mut: oklch(0.715 0 0);
--color-ttb05-lineno: #858585;
--color-ttb05-lineno: oklch(0.617 0 0);
--color-ttb05-acc: #4fc1ff;
--color-ttb05-acc: oklch(0.772 0.135 236.2);
--color-ttb05-acc-deep: #0a6cbd;
--color-ttb05-acc-deep: oklch(0.526 0.150 251.3);
--color-ttb05-ts: #3178c6;
--color-ttb05-ts: oklch(0.567 0.140 253.3);
--color-ttb05-js: #f0db4f;
--color-ttb05-js: oklch(0.884 0.156 100.7);
--color-ttb05-css: #2965f1;
--color-ttb05-css: oklch(0.556 0.220 263.4);
--color-ttb05-kw: #c586c0;
--color-ttb05-kw: oklch(0.702 0.109 329.4);
--color-ttb05-str: #ce9178;
--color-ttb05-str: oklch(0.710 0.083 43.2);
--color-ttb05-fn: #9cdcfe;
--color-ttb05-fn: oklch(0.863 0.080 232.1);
--color-ttb05-tag: #4ec9b0;
--color-ttb05-tag: oklch(0.760 0.115 177.2);
--color-ttb05-num: #b5cea8;
--color-ttb05-num: oklch(0.823 0.059 134.9);
--font-ttb05-mono: 'JetBrains Mono', ui-monospace, monospace;
--font-ttb05-sans: 'Geist', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.ttb-05 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-ttb05-bg: #111114;
--color-ttb05-bg: oklch(0.179 0.006 285.8);
--color-ttb05-editor: #1e1e1e;
--color-ttb05-editor: oklch(0.235 0 0);
--color-ttb05-chrome: #2a2a2a;
--color-ttb05-chrome: oklch(0.285 0 0);
--color-ttb05-line: #161616;
--color-ttb05-line: oklch(0.200 0 0);
--color-ttb05-ink: #ececec;
--color-ttb05-ink: oklch(0.943 0 0);
--color-ttb05-mut: #a3a3a3;
--color-ttb05-mut: oklch(0.715 0 0);
--color-ttb05-lineno: #858585;
--color-ttb05-lineno: oklch(0.617 0 0);
--color-ttb05-acc: #4fc1ff;
--color-ttb05-acc: oklch(0.772 0.135 236.2);
--color-ttb05-acc-deep: #0a6cbd;
--color-ttb05-acc-deep: oklch(0.526 0.150 251.3);
--color-ttb05-ts: #3178c6;
--color-ttb05-ts: oklch(0.567 0.140 253.3);
--color-ttb05-js: #f0db4f;
--color-ttb05-js: oklch(0.884 0.156 100.7);
--color-ttb05-css: #2965f1;
--color-ttb05-css: oklch(0.556 0.220 263.4);
--color-ttb05-kw: #c586c0;
--color-ttb05-kw: oklch(0.702 0.109 329.4);
--color-ttb05-str: #ce9178;
--color-ttb05-str: oklch(0.710 0.083 43.2);
--color-ttb05-fn: #9cdcfe;
--color-ttb05-fn: oklch(0.863 0.080 232.1);
--color-ttb05-tag: #4ec9b0;
--color-ttb05-tag: oklch(0.760 0.115 177.2);
--color-ttb05-num: #b5cea8;
--color-ttb05-num: oklch(0.823 0.059 134.9);
--font-ttb05-mono: 'JetBrains Mono', ui-monospace, monospace;
--font-ttb05-sans: 'Geist', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.ttb-05 {
width: 100%;
min-height: 100svh;
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-ttb05-bg: #111114;
--color-ttb05-bg: oklch(0.179 0.006 285.8);
--color-ttb05-editor: #1e1e1e;
--color-ttb05-editor: oklch(0.235 0 0);
--color-ttb05-chrome: #2a2a2a;
--color-ttb05-chrome: oklch(0.285 0 0);
--color-ttb05-line: #161616;
--color-ttb05-line: oklch(0.200 0 0);
--color-ttb05-ink: #ececec;
--color-ttb05-ink: oklch(0.943 0 0);
--color-ttb05-mut: #a3a3a3;
--color-ttb05-mut: oklch(0.715 0 0);
--color-ttb05-lineno: #858585;
--color-ttb05-lineno: oklch(0.617 0 0);
--color-ttb05-acc: #4fc1ff;
--color-ttb05-acc: oklch(0.772 0.135 236.2);
--color-ttb05-acc-deep: #0a6cbd;
--color-ttb05-acc-deep: oklch(0.526 0.150 251.3);
--color-ttb05-ts: #3178c6;
--color-ttb05-ts: oklch(0.567 0.140 253.3);
--color-ttb05-js: #f0db4f;
--color-ttb05-js: oklch(0.884 0.156 100.7);
--color-ttb05-css: #2965f1;
--color-ttb05-css: oklch(0.556 0.220 263.4);
--color-ttb05-kw: #c586c0;
--color-ttb05-kw: oklch(0.702 0.109 329.4);
--color-ttb05-str: #ce9178;
--color-ttb05-str: oklch(0.710 0.083 43.2);
--color-ttb05-fn: #9cdcfe;
--color-ttb05-fn: oklch(0.863 0.080 232.1);
--color-ttb05-tag: #4ec9b0;
--color-ttb05-tag: oklch(0.760 0.115 177.2);
--color-ttb05-num: #b5cea8;
--color-ttb05-num: oklch(0.823 0.059 134.9);
--font-ttb05-mono: 'JetBrains Mono', ui-monospace, monospace;
--font-ttb05-sans: 'Geist', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.ttb-05 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-ttb05-bg: #111114;
--color-ttb05-bg: oklch(0.179 0.006 285.8);
--color-ttb05-editor: #1e1e1e;
--color-ttb05-editor: oklch(0.235 0 0);
--color-ttb05-chrome: #2a2a2a;
--color-ttb05-chrome: oklch(0.285 0 0);
--color-ttb05-line: #161616;
--color-ttb05-line: oklch(0.200 0 0);
--color-ttb05-ink: #ececec;
--color-ttb05-ink: oklch(0.943 0 0);
--color-ttb05-mut: #a3a3a3;
--color-ttb05-mut: oklch(0.715 0 0);
--color-ttb05-lineno: #858585;
--color-ttb05-lineno: oklch(0.617 0 0);
--color-ttb05-acc: #4fc1ff;
--color-ttb05-acc: oklch(0.772 0.135 236.2);
--color-ttb05-acc-deep: #0a6cbd;
--color-ttb05-acc-deep: oklch(0.526 0.150 251.3);
--color-ttb05-ts: #3178c6;
--color-ttb05-ts: oklch(0.567 0.140 253.3);
--color-ttb05-js: #f0db4f;
--color-ttb05-js: oklch(0.884 0.156 100.7);
--color-ttb05-css: #2965f1;
--color-ttb05-css: oklch(0.556 0.220 263.4);
--color-ttb05-kw: #c586c0;
--color-ttb05-kw: oklch(0.702 0.109 329.4);
--color-ttb05-str: #ce9178;
--color-ttb05-str: oklch(0.710 0.083 43.2);
--color-ttb05-fn: #9cdcfe;
--color-ttb05-fn: oklch(0.863 0.080 232.1);
--color-ttb05-tag: #4ec9b0;
--color-ttb05-tag: oklch(0.760 0.115 177.2);
--color-ttb05-num: #b5cea8;
--color-ttb05-num: oklch(0.823 0.059 134.9);
--font-ttb05-mono: 'JetBrains Mono', ui-monospace, monospace;
--font-ttb05-sans: 'Geist', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.ttb-05 {
width: 100%;
min-height: 100svh;
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Geist:wght@400..700&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Geist:wght@400..700&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
input:checked + .tt25b::beforebecamehas-checked:before:bg-ttb05-accon a pseudo-element that always exists, so the stripe colour can transition.margin-bottom:-1pxcarried over as-mb-px; the divider sits on the chrome row so nothing clips the overlap.- UI upgrade from the CSS original: a breadcrumb, syntax-highlighted code, CSS-counter line numbers that don't copy (
before:select-none), a close glyph on the active tab and a VS Code status bar. - UI upgrade: resting tab labels raised from 60% white (≈4.3:1 on chrome) to a solid 5.9:1, tabs are 44px tall, and the row scrolls horizontally on phones instead of squeezing filenames.
Here's a working CSS demo 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: VS Code Style File Tabs in Tailwind CSS
Source: https://codefronts.com/navigation/tailwind-css-tabs/vs-code-style-file-tabs-tailwind-css/
IDE file tabs with language dots, an accent stripe on the active tab and an editor body that merges with it. The port adds what a real editor shows: a breadcrumb, CSS-counter line numbers that don't copy, a close glyph on the active tab and a status bar — all from utilities.
## HTML
```html
<section class="ttb-05 group/tabs grid min-h-svh w-full place-items-center bg-ttb05-bg px-5 py-14 font-ttb05-mono text-ttb05-ink" aria-label="VS Code style file tabs demo">
<div class="grid w-full justify-items-center gap-7">
<div class="w-full max-w-xl overflow-hidden rounded-xl bg-ttb05-editor shadow-[0_24px_60px_-20px_rgb(0_0_0/0.7)] ring-1 ring-white/8">
<div role="radiogroup" aria-label="Open files" class="flex overflow-x-auto border-b border-ttb05-line bg-ttb05-chrome [scrollbar-width:none]">
<label class="group/tab relative -mb-px flex min-h-11 flex-none cursor-pointer items-center gap-2 border-r border-b border-r-ttb05-line border-b-transparent px-4 text-[12.5px] text-ttb05-mut transition-colors before:absolute before:inset-x-0 before:top-0 before:h-0.5 hover:bg-white/4 hover:text-ttb05-ink has-checked:border-b-ttb05-editor has-checked:bg-ttb05-editor has-checked:text-ttb05-ink has-checked:before:bg-ttb05-acc has-focus-visible:outline-1 has-focus-visible:-outline-offset-4 has-focus-visible:outline-dashed has-focus-visible:outline-ttb05-acc"><input class="sr-only" type="radio" name="ttb05" id="ttb05-r1" checked><span aria-hidden="true" class="size-2 rounded-full bg-ttb05-ts"></span>app.tsx<span aria-hidden="true" class="ml-1 text-ttb05-mut opacity-0 group-has-checked/tab:opacity-100">×</span></label>
<label class="group/tab relative -mb-px flex min-h-11 flex-none cursor-pointer items-center gap-2 border-r border-b border-r-ttb05-line border-b-transparent px-4 text-[12.5px] text-ttb05-mut transition-colors before:absolute before:inset-x-0 before:top-0 before:h-0.5 hover:bg-white/4 hover:text-ttb05-ink has-checked:border-b-ttb05-editor has-checked:bg-ttb05-editor has-checked:text-ttb05-ink has-checked:before:bg-ttb05-acc has-focus-visible:outline-1 has-focus-visible:-outline-offset-4 has-focus-visible:outline-dashed has-focus-visible:outline-ttb05-acc"><input class="sr-only" type="radio" name="ttb05" id="ttb05-r2"><span aria-hidden="true" class="size-2 rounded-full bg-ttb05-js"></span>config.js<span aria-hidden="true" class="ml-1 text-ttb05-mut opacity-0 group-has-checked/tab:opacity-100">×</span></label>
<label class="group/tab relative -mb-px flex min-h-11 flex-none cursor-pointer items-center gap-2 border-r border-b border-r-ttb05-line border-b-transparent px-4 text-[12.5px] text-ttb05-mut transition-colors before:absolute before:inset-x-0 before:top-0 before:h-0.5 hover:bg-white/4 hover:text-ttb05-ink has-checked:border-b-ttb05-editor has-checked:bg-ttb05-editor has-checked:text-ttb05-ink has-checked:before:bg-ttb05-acc has-focus-visible:outline-1 has-focus-visible:-outline-offset-4 has-focus-visible:outline-dashed has-focus-visible:outline-ttb05-acc"><input class="sr-only" type="radio" name="ttb05" id="ttb05-r3"><span aria-hidden="true" class="size-2 rounded-full bg-ttb05-css"></span>styles.css<span aria-hidden="true" class="ml-1 text-ttb05-mut opacity-0 group-has-checked/tab:opacity-100">×</span></label>
</div>
<div class="min-h-40 py-3 text-[12.5px] leading-[1.75]">
<div class="hidden group-has-[#ttb05-r1:checked]/tabs:block"><p class="px-4 pb-2 text-[11px] text-ttb05-mut">src › app.tsx</p><code class="block [counter-reset:ttb05] [&>span]:block [&>span]:pr-4 [&>span]:whitespace-pre [&>span]:[counter-increment:ttb05] [&>span]:before:mr-4 [&>span]:before:inline-block [&>span]:before:w-8 [&>span]:before:text-right [&>span]:before:text-ttb05-lineno [&>span]:before:select-none [&>span]:before:content-[counter(ttb05)]"><span><span class="text-ttb05-kw">import</span> { Shell } <span class="text-ttb05-kw">from</span> <span class="text-ttb05-str">'./shell'</span>;</span><span> </span><span><span class="text-ttb05-kw">export default function</span> <span class="text-ttb05-fn">App</span>() {</span><span> <span class="text-ttb05-kw">return</span> <<span class="text-ttb05-tag">Shell</span> />;</span><span>}</span></code></div>
<div class="hidden group-has-[#ttb05-r2:checked]/tabs:block"><p class="px-4 pb-2 text-[11px] text-ttb05-mut">config.js</p><code class="block [counter-reset:ttb05] [&>span]:block [&>span]:pr-4 [&>span]:whitespace-pre [&>span]:[counter-increment:ttb05] [&>span]:before:mr-4 [&>span]:before:inline-block [&>span]:before:w-8 [&>span]:before:text-right [&>span]:before:text-ttb05-lineno [&>span]:before:select-none [&>span]:before:content-[counter(ttb05)]"><span>module.exports = {</span><span> <span class="text-ttb05-fn">port</span>: <span class="text-ttb05-num">3000</span>,</span><span> <span class="text-ttb05-fn">strict</span>: <span class="text-ttb05-kw">true</span>,</span><span>};</span></code></div>
<div class="hidden group-has-[#ttb05-r3:checked]/tabs:block"><p class="px-4 pb-2 text-[11px] text-ttb05-mut">src › styles.css</p><code class="block [counter-reset:ttb05] [&>span]:block [&>span]:pr-4 [&>span]:whitespace-pre [&>span]:[counter-increment:ttb05] [&>span]:before:mr-4 [&>span]:before:inline-block [&>span]:before:w-8 [&>span]:before:text-right [&>span]:before:text-ttb05-lineno [&>span]:before:select-none [&>span]:before:content-[counter(ttb05)]"><span><span class="text-ttb05-tag">:root</span> {</span><span> <span class="text-ttb05-fn">color-scheme</span>: dark;</span><span> <span class="text-ttb05-fn">--radius</span>: <span class="text-ttb05-num">12px</span>;</span><span>}</span></code></div>
</div>
<div class="flex justify-between bg-ttb05-acc-deep px-3.5 py-1 font-ttb05-sans text-[11px] text-white"><span>main</span><span>UTF-8 · Spaces: 2</span></div>
</div>
<p aria-hidden="true" class="rounded-full border border-white/10 px-3.5 py-2 text-[11.5px] text-ttb05-mut">-mb-px merge · has-checked:before:bg-acc · counter() gutter</p>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-ttb05-bg: #111114;
--color-ttb05-bg: oklch(0.179 0.006 285.8);
--color-ttb05-editor: #1e1e1e;
--color-ttb05-editor: oklch(0.235 0 0);
--color-ttb05-chrome: #2a2a2a;
--color-ttb05-chrome: oklch(0.285 0 0);
--color-ttb05-line: #161616;
--color-ttb05-line: oklch(0.200 0 0);
--color-ttb05-ink: #ececec;
--color-ttb05-ink: oklch(0.943 0 0);
--color-ttb05-mut: #a3a3a3;
--color-ttb05-mut: oklch(0.715 0 0);
--color-ttb05-lineno: #858585;
--color-ttb05-lineno: oklch(0.617 0 0);
--color-ttb05-acc: #4fc1ff;
--color-ttb05-acc: oklch(0.772 0.135 236.2);
--color-ttb05-acc-deep: #0a6cbd;
--color-ttb05-acc-deep: oklch(0.526 0.150 251.3);
--color-ttb05-ts: #3178c6;
--color-ttb05-ts: oklch(0.567 0.140 253.3);
--color-ttb05-js: #f0db4f;
--color-ttb05-js: oklch(0.884 0.156 100.7);
--color-ttb05-css: #2965f1;
--color-ttb05-css: oklch(0.556 0.220 263.4);
--color-ttb05-kw: #c586c0;
--color-ttb05-kw: oklch(0.702 0.109 329.4);
--color-ttb05-str: #ce9178;
--color-ttb05-str: oklch(0.710 0.083 43.2);
--color-ttb05-fn: #9cdcfe;
--color-ttb05-fn: oklch(0.863 0.080 232.1);
--color-ttb05-tag: #4ec9b0;
--color-ttb05-tag: oklch(0.760 0.115 177.2);
--color-ttb05-num: #b5cea8;
--color-ttb05-num: oklch(0.823 0.059 134.9);
--font-ttb05-mono: 'JetBrains Mono', ui-monospace, monospace;
--font-ttb05-sans: 'Geist', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.ttb-05 {
width: 100%;
min-height: 100svh;
}
```Here's a working CSS demo 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: VS Code Style File Tabs in Tailwind CSS
Source: https://codefronts.com/navigation/tailwind-css-tabs/vs-code-style-file-tabs-tailwind-css/
IDE file tabs with language dots, an accent stripe on the active tab and an editor body that merges with it. The port adds what a real editor shows: a breadcrumb, CSS-counter line numbers that don't copy, a close glyph on the active tab and a status bar — all from utilities.
## HTML
```html
<section class="ttb-05 group/tabs grid min-h-svh w-full place-items-center bg-ttb05-bg px-5 py-14 font-ttb05-mono text-ttb05-ink" aria-label="VS Code style file tabs demo">
<div class="grid w-full justify-items-center gap-7">
<div class="w-full max-w-xl overflow-hidden rounded-xl bg-ttb05-editor shadow-[0_24px_60px_-20px_rgb(0_0_0/0.7)] ring-1 ring-white/8">
<div role="radiogroup" aria-label="Open files" class="flex overflow-x-auto border-b border-ttb05-line bg-ttb05-chrome [scrollbar-width:none]">
<label class="group/tab relative -mb-px flex min-h-11 flex-none cursor-pointer items-center gap-2 border-r border-b border-r-ttb05-line border-b-transparent px-4 text-[12.5px] text-ttb05-mut transition-colors before:absolute before:inset-x-0 before:top-0 before:h-0.5 hover:bg-white/4 hover:text-ttb05-ink has-checked:border-b-ttb05-editor has-checked:bg-ttb05-editor has-checked:text-ttb05-ink has-checked:before:bg-ttb05-acc has-focus-visible:outline-1 has-focus-visible:-outline-offset-4 has-focus-visible:outline-dashed has-focus-visible:outline-ttb05-acc"><input class="sr-only" type="radio" name="ttb05" id="ttb05-r1" checked><span aria-hidden="true" class="size-2 rounded-full bg-ttb05-ts"></span>app.tsx<span aria-hidden="true" class="ml-1 text-ttb05-mut opacity-0 group-has-checked/tab:opacity-100">×</span></label>
<label class="group/tab relative -mb-px flex min-h-11 flex-none cursor-pointer items-center gap-2 border-r border-b border-r-ttb05-line border-b-transparent px-4 text-[12.5px] text-ttb05-mut transition-colors before:absolute before:inset-x-0 before:top-0 before:h-0.5 hover:bg-white/4 hover:text-ttb05-ink has-checked:border-b-ttb05-editor has-checked:bg-ttb05-editor has-checked:text-ttb05-ink has-checked:before:bg-ttb05-acc has-focus-visible:outline-1 has-focus-visible:-outline-offset-4 has-focus-visible:outline-dashed has-focus-visible:outline-ttb05-acc"><input class="sr-only" type="radio" name="ttb05" id="ttb05-r2"><span aria-hidden="true" class="size-2 rounded-full bg-ttb05-js"></span>config.js<span aria-hidden="true" class="ml-1 text-ttb05-mut opacity-0 group-has-checked/tab:opacity-100">×</span></label>
<label class="group/tab relative -mb-px flex min-h-11 flex-none cursor-pointer items-center gap-2 border-r border-b border-r-ttb05-line border-b-transparent px-4 text-[12.5px] text-ttb05-mut transition-colors before:absolute before:inset-x-0 before:top-0 before:h-0.5 hover:bg-white/4 hover:text-ttb05-ink has-checked:border-b-ttb05-editor has-checked:bg-ttb05-editor has-checked:text-ttb05-ink has-checked:before:bg-ttb05-acc has-focus-visible:outline-1 has-focus-visible:-outline-offset-4 has-focus-visible:outline-dashed has-focus-visible:outline-ttb05-acc"><input class="sr-only" type="radio" name="ttb05" id="ttb05-r3"><span aria-hidden="true" class="size-2 rounded-full bg-ttb05-css"></span>styles.css<span aria-hidden="true" class="ml-1 text-ttb05-mut opacity-0 group-has-checked/tab:opacity-100">×</span></label>
</div>
<div class="min-h-40 py-3 text-[12.5px] leading-[1.75]">
<div class="hidden group-has-[#ttb05-r1:checked]/tabs:block"><p class="px-4 pb-2 text-[11px] text-ttb05-mut">src › app.tsx</p><code class="block [counter-reset:ttb05] [&>span]:block [&>span]:pr-4 [&>span]:whitespace-pre [&>span]:[counter-increment:ttb05] [&>span]:before:mr-4 [&>span]:before:inline-block [&>span]:before:w-8 [&>span]:before:text-right [&>span]:before:text-ttb05-lineno [&>span]:before:select-none [&>span]:before:content-[counter(ttb05)]"><span><span class="text-ttb05-kw">import</span> { Shell } <span class="text-ttb05-kw">from</span> <span class="text-ttb05-str">'./shell'</span>;</span><span> </span><span><span class="text-ttb05-kw">export default function</span> <span class="text-ttb05-fn">App</span>() {</span><span> <span class="text-ttb05-kw">return</span> <<span class="text-ttb05-tag">Shell</span> />;</span><span>}</span></code></div>
<div class="hidden group-has-[#ttb05-r2:checked]/tabs:block"><p class="px-4 pb-2 text-[11px] text-ttb05-mut">config.js</p><code class="block [counter-reset:ttb05] [&>span]:block [&>span]:pr-4 [&>span]:whitespace-pre [&>span]:[counter-increment:ttb05] [&>span]:before:mr-4 [&>span]:before:inline-block [&>span]:before:w-8 [&>span]:before:text-right [&>span]:before:text-ttb05-lineno [&>span]:before:select-none [&>span]:before:content-[counter(ttb05)]"><span>module.exports = {</span><span> <span class="text-ttb05-fn">port</span>: <span class="text-ttb05-num">3000</span>,</span><span> <span class="text-ttb05-fn">strict</span>: <span class="text-ttb05-kw">true</span>,</span><span>};</span></code></div>
<div class="hidden group-has-[#ttb05-r3:checked]/tabs:block"><p class="px-4 pb-2 text-[11px] text-ttb05-mut">src › styles.css</p><code class="block [counter-reset:ttb05] [&>span]:block [&>span]:pr-4 [&>span]:whitespace-pre [&>span]:[counter-increment:ttb05] [&>span]:before:mr-4 [&>span]:before:inline-block [&>span]:before:w-8 [&>span]:before:text-right [&>span]:before:text-ttb05-lineno [&>span]:before:select-none [&>span]:before:content-[counter(ttb05)]"><span><span class="text-ttb05-tag">:root</span> {</span><span> <span class="text-ttb05-fn">color-scheme</span>: dark;</span><span> <span class="text-ttb05-fn">--radius</span>: <span class="text-ttb05-num">12px</span>;</span><span>}</span></code></div>
</div>
<div class="flex justify-between bg-ttb05-acc-deep px-3.5 py-1 font-ttb05-sans text-[11px] text-white"><span>main</span><span>UTF-8 · Spaces: 2</span></div>
</div>
<p aria-hidden="true" class="rounded-full border border-white/10 px-3.5 py-2 text-[11.5px] text-ttb05-mut">-mb-px merge · has-checked:before:bg-acc · counter() gutter</p>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-ttb05-bg: #111114;
--color-ttb05-bg: oklch(0.179 0.006 285.8);
--color-ttb05-editor: #1e1e1e;
--color-ttb05-editor: oklch(0.235 0 0);
--color-ttb05-chrome: #2a2a2a;
--color-ttb05-chrome: oklch(0.285 0 0);
--color-ttb05-line: #161616;
--color-ttb05-line: oklch(0.200 0 0);
--color-ttb05-ink: #ececec;
--color-ttb05-ink: oklch(0.943 0 0);
--color-ttb05-mut: #a3a3a3;
--color-ttb05-mut: oklch(0.715 0 0);
--color-ttb05-lineno: #858585;
--color-ttb05-lineno: oklch(0.617 0 0);
--color-ttb05-acc: #4fc1ff;
--color-ttb05-acc: oklch(0.772 0.135 236.2);
--color-ttb05-acc-deep: #0a6cbd;
--color-ttb05-acc-deep: oklch(0.526 0.150 251.3);
--color-ttb05-ts: #3178c6;
--color-ttb05-ts: oklch(0.567 0.140 253.3);
--color-ttb05-js: #f0db4f;
--color-ttb05-js: oklch(0.884 0.156 100.7);
--color-ttb05-css: #2965f1;
--color-ttb05-css: oklch(0.556 0.220 263.4);
--color-ttb05-kw: #c586c0;
--color-ttb05-kw: oklch(0.702 0.109 329.4);
--color-ttb05-str: #ce9178;
--color-ttb05-str: oklch(0.710 0.083 43.2);
--color-ttb05-fn: #9cdcfe;
--color-ttb05-fn: oklch(0.863 0.080 232.1);
--color-ttb05-tag: #4ec9b0;
--color-ttb05-tag: oklch(0.760 0.115 177.2);
--color-ttb05-num: #b5cea8;
--color-ttb05-num: oklch(0.823 0.059 134.9);
--font-ttb05-mono: 'JetBrains Mono', ui-monospace, monospace;
--font-ttb05-sans: 'Geist', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.ttb-05 {
width: 100%;
min-height: 100svh;
}
```How this works
The tab becomes the editor. The checked tab takes the editor's background and a 1px negative bottom margin, so it covers the divider and visually joins the body:
<label class="-mb-px border-b border-transparent bg-ttb05-chrome
has-checked:border-ttb05-editor has-checked:bg-ttb05-editor
before:absolute before:inset-x-0 before:top-0 before:h-0.5
has-checked:before:bg-ttb05-acc">Line numbers are counters. One rule on the <code> element numbers every line span, and select-none keeps them out of the clipboard.
Make it yours
- Light theme: editor
#ffffff, chrome#f3f3f3, accent#0078d4. - More languages: extend dots — Rust
#dea584, Go#00add8, Python#3776ab. - Hide the close glyph entirely if your tabs can't close.
Gotchas — read before shipping
- A parent with
overflow-hiddenclips the-mb-pxoverlap — it is why the chrome row is not the clipping element. - The close glyph is decorative (
aria-hidden); a real close action needs its own button outside the label. - Long filenames need
truncate; the tab row scrolls horizontally on phones.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Counters and user-select are universal; the floor is Tailwind v4's sheet.