Title: CSS Linked Parameters
Shortname: css-link-params
Level: 1
Status: ED
Group: CSSWG
Work Status: exploring
ED: https://drafts.csswg.org/css-link-params/
Editor: Tab Atkins-Bittner, Google, http://xanthir.com/contact/
Editor: Daniel Holbert, Mozilla
Editor: Jonathan Watt, Mozilla
Abstract: This spec introduces a way to pass CSS values into linked resources, such as SVG images, so that they can be used as CSS [=custom property=] values in the destination resource. This allows easy reuse of "templated" SVG images, which can be adapted to a site's theme color, etc. easily, without having to modify the source SVG.
Ignored Terms: css value definition syntax
Introduction {#intro} ===================== SVG is stylable with CSS, and when used inline in HTML, this capability can be very useful. For example, an SVG icon can take on a different color based on whether the user is hovering it or not, just by appling a '':hover'' rule to it that changes the 'fill' property. When the SVG is referenced in a way that doesn't allow selectors or CSS inheritance from the outer page to apply to it (such as embedding it via <{img}> or <{iframe}> in HTML), though, this functionality is lost. The only way to change the display of such "external" SVG images is to produce several of them, and change which image you're referencing. This incurs delay on the page as a new resource is downloaded, and disallows dynamic effects like CSS Transitions. CSS link parameters are a way to set CSS custom properties on an "external" resource, either by a CSS property or thru a special fragment scheme on the URL. This gives a limited, but powerful, subset of the customizability that "inline" SVG images have to "external" SVG images. Setting a Link Parameter {#setting} =================================== An external resource can be accompanied by a map of [=link parameters=], each entry composed of a [=custom property name=] as a key, and an <> as the value. There are three ways to specify a [=link parameter=]: * via the 'link-parameters' property, which applies to the resource itself (if the element represents an external resource), and to all external resources used in CSS properties on the element * via a special syntax in the fragment portion of the URL of an external resource * via a ''param()'' argument in the ''url()'' syntax If specified in multiple of these ways, all of the [=link parameters=] are combined. If the same key appears in multiple inputs, the latest source in the above list wins (that is, URL fragment beats 'link-parameters', and ''url("..." param())'' beats URL fragment). The influence of [=link parameters=] on the linked resource is defined in the next section. In CSS: the 'link-parameters' property {#link-param-prop} --------------------------------------
Name: link-parameters
Value: none | <>+
Initial: none
Inherited: no
Applies to: all elements and pseudo-elements
Computed value: as specified
Animation type: discrete
The 'link-parameters' property is one way to set [=link parameters=] on the element itself (if it is an element representing an external resource, such as an HTML <{img}> or <{iframe}>), and on all external CSS resources specified on the element (such as background images, etc). Its values are:
: none :: No [=link parameters=] specified. : <>+ :: A list of one or more [=link parameters=]. If two [=link parameters=] with the same name are specified with the same <>, the last one wins.
<link-param> = param( <> <>? )
A <> represents a [=link parameter=], with a key of the <>. If the <> is specified, that's the value of the [=link parameter=]. If omitted, the value of the [=custom property=] of the same name on the element is the value of the [=link parameter=]. In The URL {#url-frag} ---------- A special "fragment identifier" can be used in the fragment of a URL used to reference an external resource. Several examples of existing "fragment identifiers" for SVG documents can be found in the SVG 1.1 specification. The syntax of an SVG parameter fragment identifier is:
param( <> <> )
(using the CSS value definition syntax; TODO define an actual parser for it).
For example, to set the "--text-color" custom property of an SVG image to ''blue'', one can reference the image with a url like “http://example.com/image.svg#param(--text-color%20blue)”.
If passing multiple parameters to an image, additional param() functions must be appended to the URL. If multiple param() functions specify the same <>, the custom property is set to the value of the last one.
For example, if the image from the previous example also used a "--bg-color" custom property, it could be referenced with a url like “http://example.com/image.svg#param(--text-color%20blue)param(--bg-color%20white)”.
Note: Spaces, and some other characters that might be valid in CSS syntax, are not technically valid in URLs. In some contexts, you might need to escape those characters to form a valid URL. In most cases, though, such as HTML's <{a}> element or CSS's ''url()'' function, spaces are accepted and do not need to be escaped. Setting via the CSS ''url()'' Function {#setting-url} ----------------------------------------------------- When referencing an external resource via CSS, the param() function can be used in the ''url()'' function. But a common use-case is passing in values of the page's own custom properties; for example, a page might use a ''--primary-color'' custom property, and want to make an SVG image match. There's no way, however, to integrate the value of a custom property in CSS into the URL passed to the ''url()'' function. To accomodate this, a <> is a valid <>. As in the other methods of specifying [=link parameters=], if the same <> is specified in several <>s, the last one wins.
For example, if the site is using a ''--primary-color'' custom property to theme its elements with, and wanted an SVG background using a ''--color'' custom property to reflect it, it could write:
		.foo {
			background-image: url("http://example.com/image.svg" param(--color var(--primary-color)));
		}
	
Using Link Parameters {#using} ===================== When an external resource link has one or more [=link parameters=] specified, if the linked resource understands CSS (such as an SVG or HTML document), then the initial value of custom properties with names equal to the keys of the [=link parameters=] map is set to the corresponding values of the map. If an ''@property'' rule is specified for one of the custom property names in the [=link parameters=], the [=link parameter=] value is used for the initial value, rather than the ''@property''-specified initial value. If the linked resource does not understand CSS (such as PNG images), then [=link parameters=] have no effect. Issue: Define a way for the linked resource to specify what link parameters they allow. For cross-origin iframes/etc, this will default to nothing; for same-origin (or cross-origin "SVG as image"), it defaults to "everything". If not allowed, the link parameter is ignored.
For example, if an SVG image wanted to expose a ''--color'' parameter, it could use it like:
		<svg>
			<g style="fill: var(--color);">
				<path d="..." />
			</g>
		</svg>
	
It's usually a good idea to make your SVG image usable even if no parameters are given, by providing "default values" for each of the custom properties. There are several ways to do this. 1. On each ''var()'' function, provide a fallback value, like ''fill: var(--color, blue)''. 2. If the custom property is going to be used a lot, such that providing a fallback for each individual ''var()'' is troublesome, store the custom property in a different name while invoking the default, like:
			:root {
				--color2: var(--color, blue);
			}
		
In this example, if ''--color'' is provided via an SVG parameter, ''--color2'' will receive its value. If not, it will recieve the default ''blue'' value. In either case, ''--color2'' can be used in the SVG image's stylesheet unconditionally, secure in the knowledge that it will always have a value. 3. In a future level of the Custom Properties specification [[CSS-VARIABLES]], some "parent's value" functionality will be available to make the previous suggestion more usable:
			:root {
				--color: var(parent --color, blue);
			}
		
(This is an example syntax, and is not yet final.) By invoking the value of the --color property on the parent (which, on the root element, refers to the initial value), an author can avoid self-reference loops while retaining the same custom property name.