Contain Your CSS: How Stylus Keeps User Styles Safe with Site‑Scoped Rules
Avoid accidental style leakage with Stylus by scoping CSS to specific origins using @-moz-document / @document rules. Learn how the extension injects styles safely, see a concrete dark‑theme example, and understand trade‑offs like browser support and selector specificity.
04 May 2026, 02:57 UTC

Problem: Global CSS Injection Can Break the Web
When you add a user style that targets generic selectors like body or *, the style may unintentionally affect every site you visit. A single typo can break a layout, hide a login button, or even interfere with accessibility features. For power users who maintain multiple site‑specific themes, the temptation to write broad rules is high, but the risk of leaking styles into unrelated pages is real.
Thesis: Stylus Uses @-moz-document / @document to Keep Styles Intentionally Scoped
Stylus, a popular browser extension for custom CSS, solves this problem by letting you wrap your rules in @-moz-document or the standard @document at‑rule. These directives tell the extension to inject the CSS only when the current page’s URL matches a pattern. The result is a safe, opt‑in theming system that prevents accidental style leakage while still offering full control over each site.
1. The Mechanics of @-moz-document and @document
Both at‑rules are part of CSS’s at‑rule family. @-moz-document is a legacy rule that Firefox originally introduced, and Stylus emulates it for cross‑browser compatibility. The standard @document is supported by modern browsers (Chrome, Edge, Safari) but has a slightly different syntax.
@-moz-document url-prefix("https://example.com/") {
body { background: #111; }
}
@document url("https://example.org/*") {
body { background: #222; }
}
When Stylus loads a page, it evaluates each style’s applies-to list. If the current URL satisfies any rule, the CSS inside the block is injected; otherwise it is ignored. This evaluation happens on navigation events, so enabling or disabling a style is instant and efficient.
2. How Stylus Stores and Applies Scoped Styles
- Storage: Each style is a JSON object stored in the extension’s local or sync storage. The object contains
name,description,applies-to(array of URL patterns), andcss(raw source). - Isolation: The extension injects CSS into the page context after the DOM loads, but it does so from an isolated extension environment. No JavaScript from the style is executed; only declarative CSS runs.
- Priority: If multiple styles match the same URL, Stylus applies them in the order they appear in the editor. You can reorder styles via the UI to control overriding.
3. Worked Example: Dark‑Theme Example.com
Let’s walk through creating a simple dark theme for example.com and verifying that it doesn’t leak to other sites.
- Open Stylus (click the extension icon, then Options).
- Create a new style:
- Name: Example.com Dark
- Description: Dark background for example.com only
- Applies‑to:
@-moz-document domain("example.com") - CSS:
@-moz-document domain("example.com") { body { background: #000; color: #fff; } }
- Save and enable the style.
- Navigate to example.com. The background should be black.
- Open a different site (e.g., mozilla.org). The page should render normally; the black background should not appear.
- To confirm, open DevTools, go to the Sources tab, find
stylus.cssunder the extension’s namespace, and verify that the rule is present only for example.com.
If you disable the style and reload example.com, the original background returns, proving the injection is truly scoped.
4. Trade‑offs and Limitations
- Browser Support:
@-moz-documentis emulated, so behavior may differ between Firefox and Chromium‑based browsers. Test your style in the browsers you target. - Selector Specificity: Overly broad selectors inside a scoped block can still override site defaults and break functionality (e.g.,
* { display: none; }). Always use specific selectors and test with the site’s devtools. - Sync Constraints: When using the browser’s sync storage, large styles or many styles may hit quota limits. Keep CSS concise and consider splitting large themes into separate styles.
- No JavaScript: Stylus cannot inject scripts, so dynamic theming (e.g., toggling based on time of day) must rely on CSS features like
prefers-color-schemeor manual toggles. - Content Security Policy (CSP): Some sites use strict CSP that blocks inline styles. Stylus injects via
<style>tags, which may be blocked; in such cases the style won’t apply.
Actionable Takeaway
When building or maintaining user styles with Stylus, always wrap site‑specific rules in @-moz-document or @document. This guarantees that your CSS lives only where you intend it to, keeps your browsing experience safe, and makes debugging far easier. Remember to keep selectors specific, test across browsers, and use the extension’s built‑in preview to catch unintended side effects before you enable a style in production.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.