Files
youtube-studio-flow/documentation/YouTube Studio Flow/04 - Design Guidelines/02 - CSS Conventions.md
T

4.9 KiB

02 - CSS Conventions

Rules for writing CSS in YouTube Studio Flow. These apply to all frontend work. For the token values these rules reference, see 01 - Visual Design.


Always use CSS Modules

Every component gets its own ComponentName.module.css file, co-located with the component. Class names are consumed as:

import styles from './ComponentName.module.css';

<div className={styles.container}>...</div>

Global styles live exclusively in globals.css. Do not add component-specific rules to global files.


Never use inline hex colors

All color values must come from CSS variables defined in globals.css. This is what makes the dark theme work — swapping variable values at the root switches the entire app.

/* WRONG */
color: #01696f;
background: #f9f8f5;
border: 1px solid #d4d1ca;

/* CORRECT */
color: var(--color-primary);
background: var(--color-surface);
border: 1px solid var(--color-border);

This applies everywhere: component CSS, inline styles, and any dynamically constructed style objects.


Never use raw px for spacing

Use --space-* variables for all margins, padding, and gaps. Raw pixel values make the spacing system incoherent and break visual rhythm.

/* WRONG */
padding: 16px 24px;
gap: 8px;
margin-bottom: 12px;

/* CORRECT */
padding: var(--space-4) var(--space-6);
gap: var(--space-2);
margin-bottom: var(--space-3);

The spacing scale runs from --space-1 (0.25rem) to --space-16 (4rem). See 01 - Visual Design for the full table.


The min-width: 0 rule

Flex and grid children default to min-width: auto, which means they cannot shrink below their content's natural size. In practice this causes horizontal overflow — the child pushes past its container instead of wrapping or truncating.

Add min-width: 0 to any flex or grid child that contains text, a table, a wide image, or another flex/grid container:

.wrapper {
  display: flex;
}

.main {
  flex: 1;
  min-width: 0; /* required — prevents horizontal scrollbar */
}

This must be applied at every level of nesting. A min-width: 0 on an outer element does not propagate to inner flex containers.


The overflow-x: hidden backstop

The .content wrapper in DashboardLayout.module.css carries overflow-x: hidden as a definitive backstop against page-level horizontal overflow. Do not remove this rule. It is a last-resort containment boundary, not a substitute for fixing min-width at the source.


Global utility classes

Prefer these over writing new styles for common UI elements.

Buttons — from globals.css

<button class="btn btn-primary">Save</button>
<button class="btn btn-secondary">Cancel</button>

Do not write custom button styles for standard primary/secondary actions.

Pills and badges — from globals.css

<span class="pill pill-primary">Active</span>
<span class="pill pill-warn">Warning</span>
<span class="pill pill-purple">Draft</span>

Pills use --radius-full and are intended for status chips, labels, and category tags.

Form fields — from FormField.module.css

Import this file as f by convention:

import f from '@/components/shared/FormField.module.css';

Available classes:

<div className={f.field}>
  <label className={f.label}>Title</label>
  <input className={f.input} />
</div>

<div className={f.row}>
  {/* two fields side by side */}
</div>

<div className={f.actions}>
  {/* right-aligned action buttons */}
</div>
Class Purpose
f.field Vertical label + input stack
f.label Styled form label
f.input Standard text input
f.select Dropdown/select element
f.row Horizontal pair of fields
f.actions Right-aligned button row

Dropdowns and selects

Use className={f.select} from FormField.module.css. When a select needs to be inline or auto-sized, override width only:

<select className={f.select} style={{ width: 'auto' }}>

Do not write custom select styles. The f.select class handles appearance, border, padding, color, and focus state consistently across themes.


Transitions

Use these values for interactive elements:

Situation Value
Color, background, border on hover transition: color 0.15s, background 0.15s
General interactive element transition: all 0.15s
Layout change (sidebar width) transition: width 0.2s

Do not use durations longer than 0.2s for micro-interactions. Reserve longer durations for full-screen transitions if they are ever introduced.


Comments

Only comment CSS when the reason is not obvious from the code. Acceptable:

.main {
  flex: 1;
  min-width: 0; /* prevents horizontal overflow in flex child */
}

.overlay {
  pointer-events: none; /* must not intercept clicks on siblings */
}

Not acceptable: describing what the rule does, restating what is visually apparent, notes about which feature uses the class.