SelectorSync
Selectors connected — from HTML to components.
By Anish Miya · Publisher: anish-miya
Autocomplete, navigate and rename static classes and IDs across HTML, CSS, JavaScript/TypeScript, React JSX/TSX, Vue and Svelte. Version 1.1 adds framework-aware parsers, inline event handlers and real CSS declaration completions inside static style attributes.
Where it works
| Context |
Supported behaviour |
.css and plain-CSS <style> blocks |
. class and # ID suggestions; indexed references and rename. |
HTML <script> / module scripts |
Suggestions inside supported DOM API string arguments. |
HTML onclick, oninput, onchange, other on… attributes |
Selector-call suggestions and indexed literal references, including entity-encoded quotes. |
HTML/Vue/Svelte style="…" |
Standard CSS property/value suggestions powered by the VS Code CSS language service. A declaration like color:#fff is never an ID selector. |
Static class, className, id values |
Context-specific name suggestions and static definitions. |
React .jsx / .tsx |
Literal className/id, static literal-expression values and supported DOM calls inside event expressions. |
Vue .vue |
Static template attributes, whole-string literal bindings, directive event expressions, interpolated selector calls, script/setup and plain-CSS style blocks. |
Svelte .svelte |
Static attributes/literal expressions, on:click and onclick expression handlers, class:name references, script and plain-CSS style blocks. |
for/htmlFor, supported ARIA IDREFs, local href="#id" |
ID reference indexing/rename and ID-only completions. External URLs are not renamed. |
Quick start
- Open the project folder in VS Code 1.85+.
- Add a static class or ID in markup or a supported component.
- Type
. / # in CSS, or type inside a supported DOM API string. Typing/Backspace reopens matching JS suggestions without changing global editor settings.
- Type a property or value inside a static
style attribute; use Ctrl+Space if the popup is dismissed.
- Run SelectorSync: Reindex Workspace if needed.
<button id="hero" class="action" style="color: red;"
onclick="document.querySelector('.action').focus()">Go</button>
<style>.action { border-radius: 8px; }</style>
<script>document.getElementById('hero');</script>
const Button = () => (
<button className="action" id="hero"
onClick={() => document.querySelector('.action')?.classList.add('active')}>
Go
</button>
);
<template>
<button class="action" @click="document.querySelector('.action')">Go</button>
</template>
<style scoped>.action { color: red; }</style>
<button class="action" onclick={() => document.querySelector('.action')}>Go</button>
<style>.action { color: red; }</style>
Vue/Svelte files are also matched by file extension, even without a framework language mode. Install your preferred official framework tooling for syntax highlighting, type checking and framework-specific language features. SelectorSync does not replace those tools.
API-aware suggestions
querySelector, querySelectorAll, closest, matches: .class / #id selectors.
getElementById: IDs only, no # inserted.
getElementsByClassName: classes only, no . inserted; space-separated names are supported.
classList.add, remove, toggle, contains, replace: class literals in their relevant argument positions.
Whitespace and optional-chained member access are recognised. getElementsByName is not an ID API and is not treated as one. Generated/compound selector arguments and interpolated template literals are not guessed. Choosing a suggested .class/#id in an empty/bare query-selector prefix inserts the marker; an unselected bare string keeps its normal tag-selector meaning.
Rename safely
Recommended: cursor on a selector name → F2 → new name → inspect changes → Save All. Definitions and references use parent-document offsets, including inline attributes and multiple embedded blocks.
For a manual edit, change exactly one static class/ID token in HTML, JSX/TSX, Vue or Svelte, then save that source file. With rename-on-save enabled, matching indexed references are updated. Other edited documents remain unsaved for review: use File → Save All when satisfied.
Ambiguous edits, new-name collisions, class-list additions/removals, broad formatting/markup changes and unsupported dynamic expressions are skipped. Use F2 for an intentional rename. New rename targets must be portable identifiers; names requiring CSS escaping are rejected rather than inserted incorrectly. CSS escaped identifiers/attribute values are not treated as plain class references.
Important: matching is by selector kind/name across the indexed workspace, not by framework runtime scope. A Vue scoped class or same-named class in multiple components may share a rename plan. Review changes; use separate workspaces/exclusions for unrelated projects. Disable automatic rename-on-save if you prefer explicit F2-only changes. This is not a complete framework symbol-resolution engine.
Scope and deliberate limits
Supported files: HTML/HTM, CSS, JS/MJS/CJS/JSX, TS/TSX/MTS/CTS, Vue and Svelte.
- Static literal values are indexed;
className={condition ? 'a' : 'b'}, object/array bindings, class-name helper libraries and generated selectors are not interpreted as definitions.
- React
style={{…}} and Vue/Svelte expression-bound styles are JS/TS expressions, not CSS declaration strings. Use framework/TypeScript tooling for their object keys and types.
- SCSS/Sass/Less/Stylus, CSS Modules semantic scoping, arbitrary preprocessors, CSS-in-JS/tagged templates, server templates and
v-html/{@html} generated markup are not fully supported.
- Invalid/incomplete JSX/Svelte can use narrow event-completion recovery, but recovery regions are never used to manufacture rename references/definitions.
- Entity-encoded HTML handler quotes are mapped to original offsets. Automatic inference for escaped/encoded identifier spellings remains conservative; prefer simple literal names.
- The default cap is 5,000 indexed files. Dependency/build folders are excluded. Unindexed/unsupported references are not changed.
Settings
Search SelectorSync in Settings. Existing setting IDs remain compatible:
smartSelectorIntellisense.enableCssSuggestions
smartSelectorIntellisense.enableJsSuggestions (also controls markup class/ID suggestions)
smartSelectorIntellisense.enableInlineStyleSuggestions
smartSelectorIntellisense.enableRename
smartSelectorIntellisense.autoRenameOnSave
smartSelectorIntellisense.excludeFolders
smartSelectorIntellisense.maxIndexedFiles
smartSelectorIntellisense.debugLogging
For diagnostics, enable debug logging, run Reindex Workspace, then open View → Output → SelectorSync. Check language mode, exclusions and the indexing cap. Cursor movement, undo/redo, multi-cursor edits and accepting a completion do not force repetitive automatic popups.
Privacy, dependencies and verification
Parsing, indexing and CSS completion run locally. The extension does not execute your component/project code, add telemetry, upload source files or require an external account. Rename operations edit selected workspace documents: review before saving. Marketplace install counts/reviews are separate platform features.
Framework parsing uses bundled Babel, Vue and Svelte parsers; inline styles use the VS Code CSS language service. Full applicable dependency notices are included in THIRD_PARTY_NOTICES.txt.
Version 1.1.0 passes 71 automated regression tests, including mocked editor activation/save-event propagation, offsets, framework contexts, conservative negatives and standard CSS property/value completion. Editor APIs are mocked; this is not a claim of certification or physical VS Code/framework-tooling integration tests. Test your project before broad rollout.
Updates & license
Marketplace updates use the stable identity anish-miya.smart-selector-intellisense, subject to VS Code/user auto-update settings. See the Changelog. Use the Marketplace review section for non-sensitive feedback; no separate issue tracker is configured yet.
Developer: Anish Miya · License: MIT, with retained contributor/dependency notices.