diff --git a/.github/ISSUE_TEMPLATE/css-linked-parameters.md b/.github/ISSUE_TEMPLATE/css-linked-parameters.md index bb31982ab..7328fccc5 100644 --- a/.github/ISSUE_TEMPLATE/css-linked-parameters.md +++ b/.github/ISSUE_TEMPLATE/css-linked-parameters.md @@ -1,8 +1,8 @@ --- -name: CSS Linked Parameters +name: CSS Linked Parameters Support for External SVG Images about: new issue -title: "[CSS Linked Parameters] " +title: "[CSS Linked Parameters Support for External SVG Images] <TITLE HERE>" labels: CSS Linked Parameters -assignees: goldenboy777 +assignees: rahulthebuilder --- diff --git a/README.md b/README.md index 5e746f5cd..12d322833 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ we move them into the [Alumni section](#alumni-) below. | [Offline Audio Context Streaming](OfflineAudioContext/explainer.md) | <a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/labels/OfflineAudioContextStreaming">![GitHub issues by-label](https://img.shields.io/github/issues/MicrosoftEdge/MSEdgeExplainers/OfflineAudioContextStreaming?label=issues)</a> | [New Issue...](https://github.com/MicrosoftEdge/MSEdgeExplainers/issues/new?assignees=nishitha-burman&labels=OfflineAudioContextStreaming&title=%5BOfflineAudioContextStreaming%5D+%3CTITLE+HERE%3E) | Audio | | [Network Efficiency Guardrails](PerformanceControlOfEmbeddedContent/neg-explainer.md) | <a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/labels/Network%20Efficiency%20Guardrails">![GitHub issues by-label](https://img.shields.io/github/issues/MicrosoftEdge/MSEdgeExplainers/Network%20Efficiency%20Guardrails?label=issues)</a> | [New Issue...](https://github.com/MicrosoftEdge/MSEdgeExplainers/issues/new?template=network-efficiency-guardrails.md) | WICG | | [Conditional Tracing for LoAF](ConditionalTracing/explainer-for-loaf.md) | <a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/labels/Conditional%20Tracing%20for%20LoAF">![GitHub issues by-label](https://img.shields.io/github/issues/MicrosoftEdge/MSEdgeExplainers/Conditional%20Tracing%20for%20LoAF?label=issues)</a> | [New Issue...](https://github.com/MicrosoftEdge/MSEdgeExplainers/issues/new?template=conditonal-tracing-loaf.md) | Web Perf | -| [CSS Linked Parameters](SVG/CSSLinkedParameters/explainer.md) | <a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/labels/CSS%20Linked%20Parameters">![GitHub issues by-label](https://img.shields.io/github/issues/MicrosoftEdge/MSEdgeExplainers/CSS%20Linked%20Parameters?label=issues)</a> | [New issue...](https://github.com/MicrosoftEdge/MSEdgeExplainers/issues/new?assignees=goldenboy777&labels=CSS%20Linked%20Parameters&template=css-linked-parameters.md&title=%5BCSS+Linked+Parameters%5D+%3CTITLE+HERE%3E) | CSS | +| [CSS Linked Parameters Support for External SVG Images](SVG/CSSLinkedParameters/explainer.md) | <a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/labels/CSS%20Linked%20Parameters">![GitHub issues by-label](https://img.shields.io/github/issues/MicrosoftEdge/MSEdgeExplainers/CSS%20Linked%20Parameters?label=issues)</a> | [New issue...](https://github.com/MicrosoftEdge/MSEdgeExplainers/issues/new?template=css-linked-parameters.md) | CSS | # Brainstorming 🧠 diff --git a/SVG/CSSLinkedParameters/explainer.md b/SVG/CSSLinkedParameters/explainer.md index 5ffc2054e..bfb822759 100644 --- a/SVG/CSSLinkedParameters/explainer.md +++ b/SVG/CSSLinkedParameters/explainer.md @@ -1,14 +1,13 @@ -# CSS Linked Parameters - -**Written:** 2026-06-19 +# CSS Linked Parameters Support for External SVG Images ## Authors - Divyansh Mangal (dmangal@microsoft.com) +- Rahul Singh (rahsin@microsoft.com) ## Status of this Document -This document is an **explainer** for an implementation of an existing consensus standard ([CSS Linked Parameters Module Level 1](https://drafts.csswg.org/css-link-params/)). This explainer captures developer benefit, key implementation decisions, and Chromium-specific implementation details. +The CSS Linked Parameters Module Level 1 has been published as a [W3C Working Draft](https://www.w3.org/TR/css-link-params/). This explainer describes how CSS Linked Parameters apply to external SVG images, including developer benefits and key design decisions. ## Participate @@ -17,48 +16,29 @@ This document is an **explainer** for an implementation of an existing consensus - [File a new spec issue](https://github.com/w3c/csswg-drafts/issues/new?title=%5Bcss-link-params%5D) - [File an Edge explainer issue](https://github.com/MicrosoftEdge/MSEdgeExplainers/issues/new?labels=CSS+Linked+Parameters) -## Table of Contents - -- [Introduction](#introduction) -- [User-Facing Problem](#user-facing-problem) -- [Goals](#goals) -- [Non-Goals](#non-goals) -- [Proposed Approach](#proposed-approach) -- [Key Design Decisions](#key-design-decisions) -- [Alternatives Considered](#alternatives-considered) -- [Accessibility, Internationalization, Privacy, and Security Considerations](#accessibility-internationalization-privacy-and-security-considerations) -- [Stakeholder Feedback / Opposition](#stakeholder-feedback--opposition) -- [References & Acknowledgements](#references--acknowledgements) - --- ## Introduction -CSS Linked Parameters allow passing named CSS values into external resources such as SVG images, where they become accessible as [custom environment variables](https://drafts.csswg.org/css-env/#environment) via `env()`. Values can be set through the `link-parameters` CSS property, through `param()` fragment identifiers in URLs, or through `param()` modifiers in the CSS `url()` function. This enables developers to create reusable, templated SVG images that adapt to a site's theme colors, sizes, or other design tokens, without duplicating files, inlining SVG, or relying on JavaScript. +CSS Linked Parameters provides a way for developers to pass CSS values for named parameters into linked resources. This explainer covers CSS Linked Parameters support for external SVG images loaded through `<img>` or CSS image properties such as `background-image`. Parameters can be supplied through the `link-parameters` property, link parameter directives in URLs, or `param()` modifiers in `url()`. Developers specify each parameter using `param(<dashed-ident>, <declaration-value>?)`, and the linked SVG accesses it as a [custom environment variable](https://drafts.csswg.org/css-env/#environment) through `env()`. This allows a single cacheable SVG file to adapt to different theme colors or design tokens without being inlined or duplicated. --- ## User-Facing Problem -SVG images are widely used for icons, illustrations, and UI elements. When SVG is inlined in HTML, it can be styled with CSS, for example, changing `fill` on hover. However, when SVG is referenced externally (via `<img>`, `background-image`, `list-style-image`, etc.), CSS inheritance and selectors from the outer page do not apply. The only ways to customize the appearance of an external SVG are: +SVG images are widely used for icons, illustrations, and UI elements. Inline SVG can be styled with CSS from the embedding page, but external SVG images loaded through `<img>` or CSS image properties do not inherit styles or match selectors from that page. This makes it difficult to adapt a reusable external SVG image to different themes or design contexts. -1. **Duplicate the SVG file** with different hard-coded colors/values for each variant. -2. **Inline the SVG** directly in the HTML, losing caching benefits and increasing document size. -3. **Use JavaScript** to fetch, modify, and inject SVG content dynamically. +This limitation particularly affects developers building design systems and icon libraries, and teams maintaining multi-brand or themed web applications. They commonly rely on workarounds, each with drawbacks: -None of these approaches scale well: - -| Approach | Drawbacks | +| Workaround | Drawbacks | |---|---| -| Duplicate SVG files | Maintenance burden; increased network requests; no dynamic changes | -| Inline SVG | No caching across pages; bloated HTML; content not reusable | -| JavaScript injection | Increased complexity; delayed rendering; CSP restrictions | - -**Who is affected:** Front-end developers building design systems and icon libraries; teams maintaining multi-brand or themed web applications; any developer using external SVG images that need to adapt to their surrounding context. +| Maintain separate SVG files for each variant | Duplicates assets and cache entries, increases maintenance, and requires changing the image URL to switch variants | +| Inline the SVG and style it with mechanisms such as `currentColor` | Increases HTML size and prevents the SVG from being cached and reused independently as an image resource | +| Fetch, modify, and inject SVG with JavaScript using libraries such as [SVGInject](https://github.com/iconfu/svg-inject) or [SVGInjector](https://github.com/iconic/SVGInjector) | Adds script complexity, can delay rendering, and may be restricted by Content Security Policy | -**Current workarounds:** Developers commonly use inline SVG with `currentColor`, CSS masks with `background-color`, or complex JavaScript SVG injection libraries (e.g., [svg-inject](https://github.com/niclasvaneyk/svg-inject), [SVGInjector](https://github.com/iconic/SVGInjector)). All trade off caching, complexity, or performance. Some resort to applying chains of CSS filters to approximate color changes, a hacky and imprecise technique. +### Evidence of developer demand -**Developer demand:** In the [State of CSS 2025](https://2025.stateofcss.com/en-US/features/) survey, 84 respondents entered freeform answers about SVG pain points. A large proportion are complaints such as: +In the [State of CSS 2025](https://2025.stateofcss.com/en-US/features/) survey, 84 respondents provided freeform answers about SVG pain points. Styling and coloring external SVGs was the most common theme. Examples included: > "Cannot use currentColor in svg image, only inline svg" @@ -66,20 +46,20 @@ None of these approaches scale well: > "Ability to use currentColor and css variables for SVG set using background-image" -On Stack Overflow, variations of "How to change SVG color on hover" are perennial β€” [first asked over a decade ago](https://stackoverflow.com/questions/22252472/how-can-i-change-the-color-of-an-svg-element) (3.5 million views, 50+ answers) and [still regularly re-asked](https://stackoverflow.com/questions/24933430/img-src-svg-changing-the-styles-with-css). CSS author Roma Komarov has also documented [existing workarounds and their limitations](https://kizu.dev/svg-linked-parameters-workaround/). +Questions about changing SVG colors have attracted substantial attention on Stack Overflow, including [a question from 2014](https://stackoverflow.com/questions/22252472/how-can-i-change-the-color-of-an-svg-element) with more than 3.5 million views and more than 50 answers. Roma Komarov has also documented [existing workarounds and their limitations](https://kizu.dev/svg-linked-parameters-workaround/). --- ## Goals -1. **Enable parameterized external SVG images** β€” allow developers to pass named values into external SVG resources that can be read via `env()` in the SVG's own stylesheets. -2. **Supported everywhere SVG files are embedded** β€” work with `<img>`, `background-image`, `list-style-image`, and other contexts that load external SVG as an image resource -3. **Interop** β€” implement according to the [CSS Linked Parameters Module Level 1](https://drafts.csswg.org/css-link-params/) specification to ensure cross-browser compatibility as other engines adopt the spec. -4. **Graceful degradation** β€” SVG images that use [`env()`](https://caniuse.com/css-env-function) with fallback values continue to render correctly in browsers that do not support link parameters. +- **Enable parameterized external SVG images** β€” allow developers to pass named values into external SVG images that can be read via `env()` in the SVG's own stylesheets. +- **Support external SVG images across image-loading contexts** β€” work with `<img>` and CSS image properties such as `background-image` and `list-style-image`. +- **Interop** β€” align implementations of CSS Linked Parameters for external SVG images with the [CSS Linked Parameters Module Level 1](https://drafts.csswg.org/css-link-params/) specification to support interoperability across browser engines. +- **Graceful degradation** β€” SVG images that use [`env()`](https://caniuse.com/css-env-function) with fallback values continue to render correctly in browsers that do not support link parameters. ## Non-Goals -- **Cross-origin parameter passing** β€” link parameters are subject to the same security restrictions as other cross-origin resource interactions. +- **Other linked-resource contexts** β€” This explainer covers external SVG images only. Applying CSS Linked Parameters to documents loaded through `<iframe>` or other non-image resource contexts is outside its scope. --- @@ -87,7 +67,7 @@ On Stack Overflow, variations of "How to change SVG color on hover" are perennia ### 1. The `link-parameters` CSS property -A new CSS property, `link-parameters`, sets named parameters on an element. These parameters apply to the element itself (if it represents an external resource, like `<img>`) and to all external CSS resources referenced on that element (like `background-image`). +A new CSS property, `link-parameters`, sets named parameters on an element or pseudo-element. For the scope covered by this explainer, those parameters are passed to external SVG images represented by the element, such as an `<img>` source, and to external SVG images referenced by CSS image properties, such as `background-image`. ```css /* Set a single parameter */ @@ -113,7 +93,7 @@ img { | Name | `link-parameters` | | Value | `none \| <param()>#` | | Initial value | `none` | -| Applies to | all elements | +| Applies to | all elements and pseudo-elements | | Inherited | no | | Animation type | discrete | @@ -123,17 +103,19 @@ Where `<param()>` is defined as: <param()> = param( <dashed-ident>, <declaration-value>? ) ``` +The value after the comma is optional; if omitted, it represents an empty value, as in `param(--foo,)`. + Per [CSSWG resolution](https://github.com/w3c/csswg-drafts/issues/13767), the comma after `<dashed-ident>` is mandatory. `param(--foo)` without a comma is a parse error. -### 2. URL fragment parameters +### 2. Link parameter directives in URLs -Parameters can also be passed through URL fragments: +Parameters can also be passed directly in an external SVG image URL using a [link parameter directive](https://drafts.csswg.org/css-link-params/#url-frag): ```html -<img src="icon.svg#param(--color,green)"> +<img src="icon.svg#:~:param(--color,green)"> -<!-- Multiple parameters separated by & --> -<img src="icon.svg#param(--color,green)¶m(--size,24px)"> +<!-- Multiple link parameter directives separated by & --> +<img src="icon.svg#:~:param(--color,green)¶m(--size,24px)"> ``` ### 3. `url()` function modifier @@ -142,13 +124,13 @@ The `param()` function can be used as a `<url-modifier>` inside `url()`: ```css .icon { - background-image: url("icon.svg", param(--color, green)); + background-image: url("icon.svg" param(--color, green)); } ``` ### How the SVG consumes parameters -In the linked SVG resource, parameters are exposed as [custom environment variables](https://drafts.csswg.org/css-env/#environment), accessible via `env()`: +In the linked SVG resource, parameters are exposed as custom environment variables, accessible via `env()`: ```svg <svg xmlns="http://www.w3.org/2000/svg"> @@ -157,16 +139,18 @@ In the linked SVG resource, parameters are exposed as [custom environment variab </svg> ``` -The `env()` function's second argument provides a fallback value used when no parameter is passed, ensuring the SVG remains usable standalone. +The `env()` function's second argument provides a fallback value when no parameter is passed, such as when the SVG is used standalone. ### Merging order -When parameters are specified via multiple mechanisms, they are merged in this order (last wins for duplicate names): +When link parameters are specified through more than one mechanism, they are appended to a single list for the external SVG image in this order: 1. `link-parameters` CSS property -2. URL fragment `param()` identifiers +2. Link parameter directives in the URL 3. `url()` function `param()` modifiers +If multiple link parameters have the same name, the last one in the list is used. + ### Before and after ```html @@ -194,36 +178,31 @@ When parameters are specified via multiple mechanisms, they are merged in this o ## Key Design Decisions -1. **`env()` rather than `var()` for consumption.** Link parameters are exposed as custom *environment* variables, not custom *properties*. This is intentional: `env()` is globally scoped and does not participate in the cascade, making it appropriate for externally-injected values. Custom properties (`var()`) are part of the cascade and could conflict with the SVG's own stylesheet. +1. **`env()` rather than `var()` for consumption.** Link parameters are exposed as custom environment variables in the linked SVG and consumed through `env()`. Environment variables have one value throughout the SVG document and do not participate in the cascade, while custom properties consumed through `var()` do. Using environment variables therefore avoids defining how values from the embedding page would interact with the SVG's own cascade. -2. **`link-parameters` applies to all external resources on the element.** This means a single `link-parameters` declaration on an element affects its `<img>` source, `background-image`, `list-style-image`, and any other CSS-referenced external resources. This keeps the API simple, developers don't need per-resource parameter overrides for the common case. - -3. **Phased implementation.** Our Chromium implementation is split into phases (see the [Chromium design document](https://docs.google.com/document/d/1Dn0v19ljsQD8EKSxsAj2JhoG7DbK_Y3kZc7z8Fu36jg) for full details): - - **Phase 1 (current):** The `link-parameters` CSS property β€” parsing, computed style, and SVG image pipeline wiring via `env()` variables. - - **Phase 2:** URL fragment `param()` parsing and application. - - **Phase 3:** `url()` function `param()` modifier support. +2. **A single declaration applies across external SVG image-loading contexts.** On an `<img>`, `link-parameters` applies to its external SVG source. On any element or pseudo-element, it applies to external SVG images loaded by CSS image properties. This keeps the API consistent across the supported image-loading contexts. --- ## Alternatives Considered -1. **Extending CSS custom properties to cross document boundaries.** Custom properties participate in the cascade and inherit through the DOM tree. Extending them into external resources would require defining how an outer document's cascade interacts with the inner document's cascade β€” creating ambiguity about specificity, inheritance, and which properties "win." Link parameters sidestep this by using `env()`, which is explicitly outside the cascade and has clear, context-free resolution semantics. +1. **Extending CSS custom properties into external SVG image documents.** This would require defining how custom properties from the embedding page participate in the linked SVG document's cascade and inheritance. -2. **SVG `<use>` with external references.** `<use>` references clone a subtree into the current document, which means the referenced content becomes part of the embedding page's DOM and is subject to its styles. This is fundamentally different from the `<img>` / `background-image` use case, where the external resource renders in its own isolated context. Link parameters address the isolated-context case β€” enabling parameterization without merging documents. +2. **SVG `<use>` with external references.** An external `<use>` reference renders the referenced content in a [use-element shadow tree](https://www.w3.org/TR/SVG2/struct.html#UseShadowTree). The content can inherit styles from the host `<use>` element, but selectors in the embedding document cannot target elements in that shadow tree. This approach requires an inline SVG container and does not address external SVG images loaded through `<img>` or CSS image properties. -3. **CSS `currentColor` inheritance.** Only works for a single color value, and only when the SVG uses `currentColor`, too limited for multi-parameter theming. +3. **CSS `currentColor` inheritance.** This would provide a single inherited color value and require the SVG to use `currentColor`, making it insufficient for multi-parameter theming. --- ## Accessibility, Internationalization, Privacy, and Security Considerations -- **Accessibility:** No negative impact. Link parameters do not introduce new interactive elements or change document semantics. They indirectly benefit accessibility by making it easier to maintain consistent, well-themed SVG images across a site without resorting to complex JavaScript. +- **Accessibility:** Link parameters affect visual styling but do not add or change document semantics or interaction behavior. -- **Internationalization:** No impact. Parameter names are `<dashed-ident>` tokens (ASCII); parameter values are arbitrary CSS values. No text direction, locale, or language concerns. +- **Internationalization:** Link parameters use existing CSS syntax and introduce no new text-direction, locale, or language behavior. -- **Privacy:** No new concerns. Link parameters are visible only within the rendering pipeline of the linked resource. They do not create new network requests, do not expose information to third parties, and do not expand the fingerprinting surface. The values passed are controlled entirely by the page author. +- **Privacy:** Link parameters are set by the embedding page and applied locally while rendering the linked SVG. They are not included in the SVG resource request and do not create additional network requests. -- **Security:** Link parameters are subject to the same-origin restrictions that apply to external resource rendering. Parameters are consumed only as CSS environment variables within the linked document, they cannot execute script, modify DOM, or access the embedding document's state. The `env()` function already exists in CSS and introduces no new execution capabilities. +- **Security:** Link parameters can be used with both same-origin and cross-origin external SVG images. Parameter values are applied locally during rendering and do not change existing resource-loading or origin checks. External SVG images remain isolated with scripts and plugins disabled, and non-data subresource requests blocked. Parameter values affect only CSS properties where the linked SVG explicitly uses the corresponding `env()` variable. --- @@ -231,21 +210,18 @@ When parameters are specified via multiple mechanisms, they are merged in this o | Stakeholder | Signal | Evidence | |---|---|---| -| **CSSWG** | βœ… Positive | [Resolution to publish FPWD](https://github.com/w3c/csswg-drafts/issues/14028); active spec discussions ([Editor's Draft](https://drafts.csswg.org/css-link-params/)) | -| **Firefox** | βœ… Positive | Experimental implementation landed ([bug 2022783](https://bugzilla.mozilla.org/show_bug.cgi?id=2022783)) | -| **Safari/WebKit** | No signal | No known implementation or public position (TODO: file standards position request) | -| **Web developers** | βœ… Positive | Long-standing demand for parameterized external SVG; [Stack Overflow (3.5M views)](https://stackoverflow.com/questions/22252472/how-can-i-change-the-color-of-an-svg-element), [State of CSS 2025 survey](https://2025.stateofcss.com/en-US/features/), [Roma Komarov's workaround analysis](https://kizu.dev/svg-linked-parameters-workaround/) | +| **Firefox** | βœ… Positive | Firefox tracks the full specification in [meta bug 1812163](https://bugzilla.mozilla.org/show_bug.cgi?id=1812163). The `link-parameters` property is enabled for external SVG image rendering in Firefox Nightly starting with Firefox 153 ([implementation bug 2022783](https://bugzilla.mozilla.org/show_bug.cgi?id=2022783), [Nightly enablement bug 2046153](https://bugzilla.mozilla.org/show_bug.cgi?id=2046153)). Mozilla has [identified both URL-based mechanisms as follow-up implementation work](https://bugzilla.mozilla.org/show_bug.cgi?id=1812163#c2), with the `url()` modifier tracked in [bug 1812167](https://bugzilla.mozilla.org/show_bug.cgi?id=1812167). | +| **Safari/WebKit** | No signal | No public position | +| **Web developers** | βœ… Positive | External SVG styling and coloring are recurring developer pain points. See [State of CSS 2025 Shapes & Graphics pain points](https://2025.stateofcss.com/en-US/features/#shapes_graphics_pain_points). | --- ## References & Acknowledgements -**Specs:** [CSS Linked Parameters Module Level 1](https://drafts.csswg.org/css-link-params/) Β· [CSS Environment Variables Module Level 1](https://drafts.csswg.org/css-env/#environment) Β· [CSS Values and Units Level 4](https://www.w3.org/TR/css-values-4/) - -**Bugs:** [Chromium 41482962](https://issues.chromium.org/issues/41482962) +**Status:** [ChromeStatus entry](https://chromestatus.com/feature/5095153430822912) -**Discussions:** [w3c/csswg-drafts#13767](https://github.com/w3c/csswg-drafts/issues/13767) (comma requirement resolution) +**Specs:** [CSS Linked Parameters Module Level 1](https://drafts.csswg.org/css-link-params/) (Editor's Draft) Β· [CSS Environment Variables Module Level 1](https://drafts.csswg.org/css-env/#environment) Β· [CSS Values and Units Level 4](https://www.w3.org/TR/css-values-4/) -**Design doc:** [CSS Link Parameters β€” Chromium Design Document](https://docs.google.com/document/d/1Dn0v19ljsQD8EKSxsAj2JhoG7DbK_Y3kZc7z8Fu36jg) +**Design doc:** [Chromium design document](https://docs.google.com/document/d/1Dn0v19ljsQD8EKSxsAj2JhoG7DbK_Y3kZc7z8Fu36jg) **Acknowledgements:** Tab Atkins Jr. (spec author), Rune Lillesveen (Chromium CSS OWNERS, implementation review), Fredrik SΓΆderquist (Chromium SVG OWNERS, implementation review).