Navigate, create, and rename CSS rules directly from your JSX/TSX — without leaving your editor.
Jump & Peek — F12 on any className or id to jump to the CSS rule. Split panel by default. Ctrl+K Ctrl+P to peek inline. If multiple CSS files match, a picker lets you choose.
Hover Preview — hover any className or id to see the matching CSS rule body in a tooltip. Multi-match shows every source.
Reverse Navigation — F12 on a .selector inside a CSS file to find every JSX/TSX file that uses it.
Auto-create — Ctrl+. on a missing class or id to create the rule (or the whole CSS file + import) and land your cursor inside the block.
Autocomplete — Type inside className="" for selector suggestions from your imported CSS. Type . at the start of a CSS line for class names from your JSX files.
Workspace CSS Union — child components see CSS imported by ancestors. App.tsx imports globals.css, your child component uses className="container" without re-importing — Jump / Peek / Hover / Autocomplete all work across the project.
Aliased imports — import '@/styles/globals.css' (or any path alias) resolves through your tsconfig.json / jsconfig.json compilerOptions.paths.
CSS variable jump — F12 on var(--primary) jumps to its --primary: definition. Reverse-nav from the definition lists every var() call. Multi-theme defs (e.g. :root + .theme-dark) trigger a QuickPick so you can pick the right one. Hover shows every definition with its value, or — on a definition — the usage count. Fallback (var(--primary, blue)) and nested (var(--a, var(--b))) forms both detected.
Alt+R or F2 on any class or id — renames across all CSS and JSX/TSX files at once. Scoped to the nearest package.json so sub-packages are never touched.
| Key | Action |
|---|---|
F12 |
Jump to CSS rule |
Ctrl+K Ctrl+P |
Peek CSS rule |
Ctrl+. |
Quick Fix — create rule / create file |
Alt+R / F2 |
Rename project-wide |
| Setting | Default | Description |
|---|---|---|
cssBridge.openLocation |
beside |
beside = split panel, active = replace current tab |
cssBridge.autoCreateImport |
true |
Allow auto-creating CSS file and import |
cssBridge.includeWorkspaceCss |
true |
Include CSS imported anywhere in the project (not just the current file's direct imports) — enables the Workspace CSS Union feature |
cssBridge.verboseLogging |
false |
Log every provider call (Hover, Definition, Completion, Rename, CodeAction) to the output channel for live debugging |
cssBridge.autoDiagnoseOnEditorChange |
false |
On every JSX/TSX/CSS file you switch to, dump scope, resolved imports, and workspace CSS pool to the output channel |
cssBridge.classNameHelpers |
["clsx", "classnames", "cn", "cx", "twMerge"] |
Function names treated as className helpers — string-literal arguments and object keys inside calls to these are scanned alongside className="...". Add custom helpers (e.g. cva, tw) here |
Run from the Command Palette (Ctrl+Shift+P):
| Command | Purpose |
|---|---|
CSS Bridge: Jump to CSS Rule |
Same as F12 — kept for explicit access |
CSS Bridge: Peek CSS Rule |
Same as Ctrl+K Ctrl+P |
CSS Bridge: Create CSS Rule / Create CSS File and Import |
Internal — invoked by Ctrl+. Quick Fix |
CSS Bridge: Show Output Log |
Open the extension's output channel |
CSS Bridge: Diagnose |
Dump scope detection, alias config, direct CSS imports, workspace CSS pool, and cursor context. Paste it when reporting bugs to skip the back-and-forth |
- Runtime
${expression}parts of template literals are dropped —`btn-${size}`matchesbtn-(partial), notbtn-lg. Static prefixes/suffixes still work - Tagged template helpers (
tw`...`,styled`...`) andcva()config-object form are not detected — add the call name tocssBridge.classNameHelpersfor plain-call helpers - CSS Modules (
styles.btn) — not supported; needs separate import-resolver rewrite Ctrl+Spacerequired after#for id completion in CSS (VS Code color picker limitation)Ctrl+Clickalways opens in same group — useF12instead
New feature — CSS variable jump:
- Forward jump —
F12/Ctrl+Clickonvar(--primary)lands on its--primary:definition. If multiple themes define the same name (:rootlight +.theme-darketc.), the QuickPick disambiguator lists all of them so you can pick. - Reverse navigation —
F12on a--primary:definition lists everyvar(--primary)call in the project. - Hover preview on
var(--foo)— shows every definition:selector → value · file:line. Hover on a definition instead summarizes how many places consume it. - Fallback & nested forms —
var(--primary, blue)andvar(--a, var(--b))resolve correctly (the regex captures--primary/--a/--bas separate detections). - Diagnose now includes per-file
Var defs/Var usescounts plus the cursor-detected var with its forward/reverse target list.
Internals:
- New
parseVars(filePath)in the CSS parser — postcsswalkDeclsfor--name:definitions, regex over comment-stripped content forvar(--name)usages. Cached separately fromparseSelectors(keeps v1.0–v1.2 selector path untouched). - Block comments are stripped to same-length whitespace before the use regex runs, so
/* var(--ghost) */is correctly ignored without breaking offset math. - Scope-bounded via
globFiles(scope, ['.css'])— vars stay intra-CSS, no JSX index involvement.
New features:
- Dynamic
classNameexpressions — Jump / Hover / Rename / Reverse-nav now work insideclassName={...}. Recognised shapes: template literals (`btn ${active ? 'is-active' : ''}`), ternaries,&&/||/??short-circuits, string concatenation, and arrays/objects nested inside. clsx/classnames/cn/cx/twMergehelpers — string-literal arguments (and object keys like{ 'btn-active': flag }) are scanned alongsideclassName="...". Custom helper names extend the list via the new setting.
Setting:
cssBridge.classNameHelpers— array of function names treated as className helpers. Default:["clsx", "classnames", "cn", "cx", "twMerge"]. Add your own (e.g.cva, project-specific helpers).
Internals:
- New AST-based class index module — single
@babel/parserwalk per file, mtime + document-version cached, replaces the per-feature regex scanners. Keystroke fast-path on plainclassName="..."preserved (no parse cost). - Perf: Pre-warm parse on file open + 80 ms parse throttle so the first F12 inside
className={...}doesn't pay the inline parse cost; CodeAction's lightbulb skips the AST fallback to keep typing snappy on big files. - Diagnose command now reports class-index counts (
attr-string/attr-expr/helper) and the source label of the cursor token, so you can verify dynamic detection without speculation.
- Polish: Toggling
cssBridge.verboseLoggingon now surfaces the output channel automatically. Previously the channel was silently writing log entries but stayed hidden until you ranCSS Bridge: Show Output Log— confusing if you'd just flipped the setting expecting to see logs. - Docs: README updated with the v1.1.0 features (Hover Preview, Workspace CSS Union, Aliased imports), new settings, and command reference.
New features:
- Workspace CSS Union — child components now see CSS imported by ancestors. Common case:
App.tsximportsglobals.css, child component usesclassName="container"without re-importing. F12 / Hover / Autocomplete / Code Action all work across the project. Toggle viacssBridge.includeWorkspaceCss(defaulttrue). - Aliased imports —
import '@/styles/globals.css'(or any path alias) now resolves throughtsconfig.json/jsconfig.jsoncompilerOptions.paths. - Hover preview — hover any
className/idto see the matching CSS rule body without leaving the editor. Multi-match preview shows every source. - Better project detection — recognizes Vite / Next / Remix / Rsbuild / Webpack monorepos where
reactis hoisted by workspaces. Replaces the v1.0.x package.json-only boundary check.
Setting:
cssBridge.includeWorkspaceCss—trueto include CSS imported anywhere in the project;falsefor strict per-file imports only.
New commands:
CSS Bridge: Show Output Log— open the extension's output channel.CSS Bridge: Diagnose— dump scope detection, resolved imports, alias config, workspace CSS pool, and cursor context to the output channel. Paste it when reporting bugs to short-circuit "F12 doesn't jump" speculation.
- Fix:
data-id,aria-id, and other*-idattributes are no longer falsely matched asid=. Same fix preventsmyCustomClassName=from being treated asclassName=. Affects Jump, Peek, Autocomplete, and Rename. - Fix: Reverse navigation (CSS → JSX, F12 on a
.selector) and Rename no longer match attribute-shaped text inside JS/JSX comments. - Fix: CSS-side autocomplete on
#now returns id suggestions correctly. Items also keep their./#prefix on accept (no more dropped or duplicated trigger char). - Feat:
Ctrl+K Ctrl+P(Peek) now also works from a CSS file — peeks JSX usages of the selector under the cursor. - Perf: Cache JSX/TSX import resolution by mtime — no more re-parsing with Babel on every cursor move.
Initial release.

