VS Code CSS conventions, file organization, class naming, standard sizes, SplitView/Grid layout, scrollable content, responsive layout, and text overflow/ellipsis patterns. Use when writing CSS, building layouts, or fixing text truncation issues.
VS Code CSS conventions, file organization, class naming, standard sizes, SplitView/Grid layout, scrollable content, responsive layout, and text overflow/ellipsis patterns. Use when writing CSS, building layouts, or fixing text truncation issues.
This skill covers CSS file organization, naming, standard sizes, programmatic layout (SplitView, Grid, scrollable), responsive patterns, and text overflow handling.
1. File Organization
CSS files are co-located with their TypeScript components:
State classes: .visible, .focused, .active, .highlight
Feature-specific classes use kebab-case without prefix: .my-feature, .outline-pane,
.welcome-view-content
3. Standard Sizes
Element
Size
Part title height
35px
Title padding (horizontal)
8px
Title label inner padding
12px
Action area padding
5px
Action icon size
16px
Body font-size
13px (workbench), 11px (HTML body)
Line height
1.4em
Validation message font-size
12px (line-height: 17px)
For padding/margin/gap, border-radius, font-size/font-weight,
codicon size and border width, prefer the design-system size tokens over
raw px — see §10 Design-System Size Tokens.
Canonical reference: .github/instructions/design-tokens.instructions.md
(auto-injected for src/vs/**/*.css).
4. CSS Selector Quality
Anti-pattern (flagged)
Correct pattern
ID selectors for styling (#my-widget)
Class selectors (.my-widget)
Overly specific selectors
Minimal specificity needed
Styles in the wrong file
Co-located with the component
Missing min-width: 0 on flex children
Prevents truncation issues
Forgetting pointer-events: none on hidden overlays
Prevents click-through bugs
Never Add New !important
Do not introduce !important in new or modified CSS. When a declaration loses
the cascade, inspect the competing selector and increase specificity with the
smallest appropriate component, workbench, or state-class prefix instead.
Existing !important declarations may be preserved and must not be removed
mechanically during unrelated edits. Do not copy them, add new ones, or use
them to avoid understanding selector ownership.
The narrow exception is shared focus/active-outline suppression, where
outline: 0 !important is intentionally used to override native or global focus
indicators and prevent flashing outlines during pointer activation. Keep this
exception scoped to focus-indicator behavior; feature styling must still resolve
cascade conflicts through selector specificity.
Sidebar/panel can be resized narrower than the title
View pane header titles
View containers can be narrow
List/tree row labels
Rows have a fixed width from the list container
Tab labels (editor tabs)
Many tabs shrink to fit
Button labels in welcome views
Buttons have max-width constraints
Status bar items
Many items compete for horizontal space
Notification message text
Notification toast/center has fixed width
Tooltip/hover headings
Hovers have max-width
Dropdown/select items
Select boxes have bounded width
Badge text / descriptions
Auxiliary text in constrained columns
Flex Container Gotchas
Flex children default to min-width: auto, which preventstext-overflow: ellipsis from working because the flex item refuses to shrink below its content width. Fix this by setting min-width: 0 on the flex child:
/* WRONG — ellipsis will NOT trigger inside a flex container */.flex-parent {
display: flex;
}
.flex-parent > .label {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* CORRECT — add min-width: 0 so the flex item can shrink */.flex-parent > .label {
min-width: 0; /* ← this is the fix */overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
This pattern is used throughout VS Code — for example, .monaco-icon-label-container sets min-width: 0 and flex: 1 to allow label text to truncate.
Fixed vs Flexible Elements
When a row has both fixed-size elements (icons, action buttons) and flexible text:
This is the standard pattern for tree rows, list items, tab labels, and view pane headers.
Hover for Full Text
When text is truncated with ellipsis, the full text must be accessible via hover tooltip. Use IHoverService.setupDelayedHover() with the full untruncated text so users can read it:
VS Code ships a design-system size ramp, registered in
src/vs/platform/theme/common/sizes/baseSizes.ts (agents font ramp in
src/vs/sessions/common/sizes.ts) and emitted as --vscode-* CSS variables.
When writing or editing CSS, prefer the token var over a raw px value wherever a
token exists. The full tables + rationale live in the auto-injected
.github/instructions/design-tokens.instructions.md (canonical source — keep
this section in sync with it). This section captures the decision logic for
deeper styling tasks.
Every --vscode-* size var you reference must already exist in
build/lib/stylelint/vscode-known-variables.json ("sizes" array,
alphabetically sorted) or stylelint/hygiene fails. Adding a new token means
adding it both in baseSizes.ts and that JSON file.
What matters is the value, not the token. Adopting the var() is optional —
a raw px value is fine as long as it lands on the scale. What breaks rhythm is
an off-scale value (3, 5, 7, 14, 26px…). Snap off-scale values to the nearest
scale value, ties round up (5px → 6px, 3px → 4px, 1px → 2px,
26px → 28px). Each length of a shorthand is checked independently
(0 5px → 0 6px). Leave auto, %, em/rem, var()/calc() untouched.
Pills (radius ≈ half the element height — e.g. 28h/14r, 36h/18r,
22×22/11r) → --vscode-cornerRadius-circle, not xLarge. The
literal-nearest token would square them and lose the fully-rounded intent.
Leave untouched:50%, 0, 0px, inherit, any calc()/var().
Preserve !important.
Font size & weight
Generic UI ramp — pair a size token with a weight token (mirrors the
agents ramp; "Strong" = matching size token + semiBold, never a separate size):
Both weight ramps are two weights only: regular (400) and
semiBold (600) — generic --vscode-fontWeight-*, agents
--vscode-agents-fontWeight-*.
No medium (500).font-weight: 500 is off the ramp — snap to semiBold.
Likewise 700/bold → round to the nearer of 400/600.
"Strong" is not a separate size. "Body 1 Strong" = the matching
--vscode-fontSize-* (or --vscode-agents-fontSize-*) size token + semiBold.
Never add a strong size.
Codicons are only ever 16px or 12px — never 14px or any in-between value.
px
Variable
Use
16
--vscode-codiconFontSize (base)
default icon size
12
--vscode-codiconFontSize-compact
dense/inline chrome
Compact-glyph convention: when sizing an icon at the compact 12px size, also
swap the registered glyph to its *Compact variant (e.g. Codicon.close →
Codicon.closeCompact, Codicon.add → Codicon.addCompact). CSS font-size
alone only scales the icon — it does not change to the visually-optimized
compact glyph; that requires changing the registered icon (Action2 icon: /
renderIcon). Only swap the glyph when no CSS selector targets the original
glyph class (e.g. .codicon-close); selectors keyed on the glyph class
(.codicon-add, .codicon-chevron-down) break when the class becomes
-compact, so update those selectors too (or size via a glyph-independent
wrapper class like .monaco-button). Some icons (settings/sliders, agent, vm,
info, lock, plus) have no compact variant — keep the regular glyph at 12px.
Stroke — border width
A single stroke thickness: 1px → --vscode-strokeThickness. Applies to the
border: 1px solid <color> shorthand and border-width: 1px. Other widths have
no token — leave them.