css-style-tracer
v0.2.0
Published
Trace the CSS cascade chain of any element via Chrome DevTools Protocol: find the winning rule, its file:line source, what it overrides, and inherited styles. CLI + MCP server + AI skill. Fixes 'AI edits CSS but it does not take effect' by giving agents r
Maintainers
Readme
css-style-tracer
Trace the CSS cascade chain of any page element via the Chrome DevTools Protocol — the same engine behind Chrome DevTools' Styles panel.
Given an element, it tells you:
- Which rule actually wins for each property, and its exact
file:linesource - Which rules it overrides (and which override it)
- Cascade layer context (
@layer) — critical for Tailwind v4 / modern CSS - Media query / container query wrapping each rule
- Pseudo-element styles (
::before,::after, etc.) - Inline styles (highest priority)
- Inherited styles from every ancestor, with their sources
- Shadow DOM piercing — finds elements inside Web Components
- Tailwind-aware conclusions — tells you to edit
classNamein JSX, not the generated CSS - A per-property "where to edit" conclusion
This is the fix for "I changed the CSS but nothing happened" — instead of guessing which rule takes effect, you read the runtime ground truth first, then edit the exact winning rule.
Why
CSS is resolved at runtime by the browser's cascade: specificity, source order, cascade layers, !important, inheritance, inline styles, and the hundreds of global rules a component library injects. Statically reading .css files cannot tell you the effective value. This tool asks the browser directly.
Install
Requires Node.js >= 18 and a locally installed Chrome / Chromium (puppeteer-core drives the system browser; nothing is downloaded).
npm install -g css-style-tracerOr run without installing:
npx css-style-tracer <url> <selector>CLI usage
css-style-tracer <url> <selector> [options]| Option | Description |
| --- | --- |
| --prop=a,b | Focus properties (comma-separated); adds a per-property "where to edit" conclusion |
| --json | Output structured JSON (for scripts / AI parsing) |
| --connect=<url> | Attach to a running Chrome (e.g. http://127.0.0.1:9222) to keep login state |
| --headed | Run Chrome headed (default headless) |
| --wait=<ms> | Extra wait after load for SPA rendering (default 800) |
| --chrome=<path> | Custom Chrome executable path (auto-detected by default) |
| --mcp | Run as an MCP server (see below) |
Examples:
# Where does .modal-title get its text-align from?
css-style-tracer http://localhost:5173 ".modal-title" --prop=text-align,margin-left
# Machine-readable output
css-style-tracer http://localhost:5173 "#submitBtn" --json
# Authenticated page: start Chrome with --remote-debugging-port=9222 first
css-style-tracer http://localhost:5173 "#app" --connect=http://127.0.0.1:9222Sample output
【级联链 · 匹配规则】(优先级 高 → 低;◀WIN=生效,✗=被覆盖)
[0] #main .box @ /app.css:9
color: blue; ◀ WIN
[1] .box @ /app.css:3
color: red; ✗ 被 [0] #main .box 覆盖
【结论 · 该改哪里】
● color(当前渲染值: rgb(0, 0, 255))
生效来源: #main .box @ /app.css:10
→ 直接修改上面这条规则的 color,或新增一条优先级更高的规则。Use as an MCP server (any AI client)
Expose the trace_styles tool to Claude Code, Cursor, Qoder, Windsurf, or any MCP-compatible client:
{
"mcpServers": {
"css-style-tracer": {
"command": "npx",
"args": ["-y", "css-style-tracer", "--mcp"]
}
}
}The AI agent can then call trace_styles({ url, selector, props }) to get the cascade chain before editing styles.
Use as an AI skill (Qoder / Codex)
Copy the bundled skill into your skills directory so the agent proactively traces before editing CSS:
mkdir -p ~/.codex/skills/css-style-tracer
cp node_modules/css-style-tracer/skill/SKILL.md ~/.codex/skills/css-style-tracer/SKILL.md(Or from a clone: cp skill/SKILL.md ~/.codex/skills/css-style-tracer/SKILL.md.)
Use as a library
import { traceStyles } from 'css-style-tracer';
const result = await traceStyles({
url: 'http://localhost:5173',
selector: '.modal-title',
props: ['text-align'],
});
console.log(result.conclusions[0].winner); // { selector, loc: 'file:line', value }Returned shape: { url, selector, element, computed, cascade[], inline[], inherited[], conclusions[] }.
Notes
- Cascade Layers: if the winning rule is inside
@layer(...), the report shows it and warns that un-layered rules of equal specificity take priority. - Tailwind / UnoCSS: when the winning rule is a utility class from a generated/injected stylesheet, the conclusion tells you to edit
classNamein your component instead of the CSS file. - Shadow DOM: selectors automatically pierce open shadow roots (Web Components / Lit / Shoelace).
- Pseudo-elements:
::before/::afterstyles are reported in a dedicated section. - Media queries: rules wrapped in
@media/@containershow the query context. - Vite dev mode: injected
<style>tags are resolved back to their original source file viadata-vite-dev-id/data-href. - Component libraries: if the winning rule belongs to a third-party library, add a higher-specificity override in your own stylesheet instead of editing the library.
- Chrome is auto-detected on macOS, Linux, and Windows; use
--chrometo override.
License
MIT
