# Um SVG, nove pôsteres: CSS Linked Parameters

> CSS Linked Parameters passa cores do CSS para um SVG carregado como img ou background. Veja como funciona, o fallback grátis e o que falta no recurso.

URL: https://dpw.dev/css/css-linked-parameters-svg/  
Publicado em: 2026-10-22  
Categoria: css  
Tags: interface, web-design, design-system  
Autor: Tárcio Zemel

Um SVG usado como `<img>` ou imagem de fundo sempre ignorou o CSS da página. Com **CSS Linked Parameters**, a página passa valores para dentro do arquivo e um único SVG ganha quantas paletas forem necessárias, com fallback automático nos navegadores que ainda não conhecem o recurso.

> Artigo baseado em [One SVG, nine posters: CSS linked parameters](https://pepelsbey.dev/articles/svg-link-params/).

A seguir estão os dois lados da sintaxe (o SVG e o CSS), um pôster do Andy Warhol pintado de nove jeitos a partir do mesmo arquivo e o que ainda falta implementar. Por enquanto, é um recurso experimental para acompanhar e testar, não para usar em produção.

Alguns anos atrás, o autor, Vadim Makeev, mergulhou no assunto dos <a href="https://pepelsbey.dev/articles/svg-sprites/" target="_blank" rel="noopener noreferrer">sprites SVG</a> e voltou com uma lista de métodos, cada um quebrado do seu jeito. A linha divisória acabou ficando num lugar diferente do esperado.

<a href="/html/inline-svg-cache/" target="_blank">Cache é um problema resolvido</a>: um sprite cheio de `<symbol>`s vive num arquivo externo, entra no cache como qualquer outro e ainda respeita o `currentcolor`. Só que isso funciona apenas por meio de um `<svg>` inline como marcador no HTML.

Peça o mesmo gráfico como `<img>` ou imagem de fundo e a estilização sai de cena. Nada de cores.

Isso finalmente começa a mudar. Existe uma especificação nova chamada <a href="https://drafts.csswg.org/css-link-params-1/" target="_blank" rel="noopener noreferrer">CSS Linked Parameters</a>, que permite passar valores CSS para um recurso vinculado, e o recurso decide o que fazer com eles.

O Firefox Nightly <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/153#:~:text=Updating%20attributes%20of%20external%20resources" target="_blank" rel="noopener noreferrer">traz uma implementação experimental</a> desde a versão 153, com a preferência `layout.css.link-parameters.enabled` ativada por padrão, e nenhum outro navegador tem nada. Ou seja, está longe de produção.

Mas já dá para brincar com ele hoje, e havia a desculpa perfeita para isso: imprimir um Andy Warhol.

> **Atualização:** **Atualização:** agora são dois motores. <a href="https://indieweb.social/@bigandy/117325881565720106" target="_blank" rel="noopener noreferrer">Bigandy</a> testou as demonstrações no Safari Technology Preview 253, onde existe uma flag para o recurso: Settings → Feature Flags → CSS → "CSS Linked Parameters". É experimental e vem desligado por padrão, então o "longe de produção" continua valendo.

## O beco sem saída da estilização

Uma recapitulação rápida do problema. Aqui está o mesmo logo, colocado de quatro formas diferentes:

```html
<svg viewBox="0 0 160 160" width="160" height="160">
	<path d="M123.13 36.87a61.02 61.02 0 0 0-86.26 0…"/>
</svg>
<svg width="160" height="160">
	<use href="logo.svg#logo"/>
</svg>
<img src="logo.svg" width="160" height="160" alt="">
<div style="background-image: url('logo.svg')"></div>
```

As duas primeiras podem ser estilizadas pelo CSS da página: o `currentcolor` e propriedades herdadas como `fill` atravessam a fronteira do SVG inline e, com algumas restrições, chegam ao símbolo que ele puxa de um arquivo externo.

As duas últimas, não. Um `<img>` ou uma imagem de fundo é um documento separado, com seus próprios estilos, e nada do que se escreve no CSS da página alcança o lado de dentro.

O Firefox tem há anos uma solução não padronizada: `-moz-context-properties` permite que um SVG externo aceite o `fill` e o `stroke` do elemento que o referencia. Ela é usada na própria interface do Firefox desde sempre, mas nunca virou padrão e nunca funcionou em outro lugar.

Os linked parameters são o substituto padronizado dela, e bem mais flexível: em vez de duas propriedades fixas, dá para ter quantos valores nomeados forem necessários.

## Passando uma cor

São dois lados: o SVG declara o que aceita, e o CSS fornece os valores.

### O lado do SVG

Dentro do arquivo SVG, onde normalmente iria uma cor, entra uma função `env()` com um nome e um fallback:

```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160">
	<rect fill="env(--color, #c1f07c)" width="160" height="160" rx="80"/>
	<path fill="black" d="M123.13 36.87a61.02 61.02 0 0 0-86.26 0…"/>
</svg>
```

Talvez você conheça o `env()` do `safe-area-inset-bottom` e companhia, em que o navegador fornece os valores. Aqui é o contrário: o nome é seu, e a página que vincula este arquivo fornece o valor.

O segundo argumento é o fallback. Enquanto ele estiver lá, o arquivo continua sendo um SVG perfeitamente normal, que é renderizado sozinho, em qualquer navegador, sem parâmetro nenhum.

Também funciona num elemento `<style>` dentro do SVG, e não só em atributos de apresentação:

```xml
<style>
	.logo {
		fill: env(--color, #c1f07c);
	}
</style>
```

### O lado do CSS

Na página, os valores são definidos com a propriedade `link-parameters` e a função `param()`:

```css
img {
	link-parameters: param(--color, #ff8052);
}
```

Só isso. O elemento `<img>` é o recurso vinculado, a propriedade se aplica a ele, e o SVG lá dentro é repintado.

Esse logo é verde em todo perfil do autor nas redes sociais, mas agora o verde é um parâmetro, então aqui ele sai coral. Se o logo continuar verde na demonstração, o navegador ainda não tem o recurso.

<a href="https://pepelsbey.dev/articles/svg-link-params/demo/logo.html" target="_blank" rel="noopener noreferrer">Abrir a demonstração do logo em nova aba</a>

A nomenclatura confunde um pouco no começo. Em `param(--color, #ff8052)`, o primeiro argumento é o nome do parâmetro e o segundo é o valor enviado. Em `env(--color, #c1f07c)`, o primeiro argumento é o mesmo nome e o segundo é o fallback.

Mesmo formato, funções diferentes: `param()` manda um valor para dentro, e `env()` decide o que usar quando nada chega.

> **Nota:** A propriedade não é herdada. O valor inicial dela é `none` e ela se aplica a todos os elementos e pseudo-elementos, mas precisa ser definida no próprio elemento que carrega a imagem. Colocá-la num wrapper não faz nada.

## Quatro matrizes, um pôster

Uma cor é legal, mas um logo não é lá uma grande tela. Hora de apresentar uma de verdade: a gravura Marilyn, de Andy Warhol, de 1967, vetorizada em SVG.

Warhol fazia essas obras em serigrafia, o que significa que a imagem é uma pilha de matrizes de cor chapada, uma passada de tinta cada. A vetorização funciona exatamente do mesmo jeito: quatro elementos `<path>`, quatro cores chapadas, cada uma pintada por cima da anterior.

Nada de gradientes, nada de opacidade, nenhum truque esperto. É a imagem mais parametrizável que se poderia imaginar.

```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1026 1022">
	<path fill="env(--dark, #37312d)" d="M294 1020h-2…"/>
	<path fill="env(--face, #ebb4ad)" d="M0 511V0h1026…"/>
	<path fill="env(--hair, #e6e780)" d="M801 982c0-3…"/>
	<path fill="env(--back, #f25a80)" d="M6 1019A118549…"/>
</svg>
```

Os paths vão de baixo para cima, na ordem em que as telas desceriam. A matriz escura vai primeiro.

Depois, o tom de pele cobre a tela inteira e abre buracos em si mesmo onde o escuro deve aparecer: o atributo `d` dele começa traçando os quatro cantos e depois gasta algumas centenas de subpaths recortando buracos nesse retângulo. Em seguida vêm o cabelo e o fundo, cada um pintado por cima do que veio antes.

Agora, quatro parâmetros em vez de um:

```css
img {
	link-parameters:
		param(--back, #cfa9bf),
		param(--hair, #faa601),
		param(--face, #99d2d7),
		param(--dark, #73901a);
}
```

<a href="https://pepelsbey.dev/articles/svg-link-params/demo/poster.html" target="_blank" rel="noopener noreferrer">Abrir a demonstração do pôster em nova aba</a>

> **Nota:** Repare que a sombra dos olhos e os lábios mudam junto com o fundo. Na gravura, eles estão na mesma matriz, então estão no mesmo path da vetorização, e um parâmetro pinta os três.

## Nove pôsteres, um arquivo

E aqui está a parte que faz desse recurso mais do que um substituto do `currentcolor`. O mesmo arquivo, referenciado nove vezes, pintado de nove jeitos diferentes:

```html
<div class="poster">
	<img
		class="poster__panel poster__panel--pink"
		src="poster.svg"
		width="1026" height="1022"
		alt="Marilyn Monroe portrait in pink and yellow"
	>
	<!-- …e mais oito -->
</div>
```

```css
.poster__panel--pink {
	link-parameters:
		param(--back, #f85983),
		param(--hair, #ecef81),
		param(--face, #edb3ac),
		param(--dark, #322e2e);
}

.poster__panel--turquoise {
	link-parameters:
		param(--back, #4a9fac),
		param(--hair, #d87205),
		param(--face, #cba6bd),
		param(--dark, #a09797);
}

/* …e mais sete */
```

<a href="https://pepelsbey.dev/articles/svg-link-params/demo/warhol.html" target="_blank" rel="noopener noreferrer">Abrir a demonstração dos nove pôsteres em nova aba</a>

Demonstrações ao vivo são complicadas para um recurso que só existe no Firefox: a menos que você esteja lendo isto no Nightly, a demonstração não vai mostrar o que está descrito aqui. Esta é uma captura de tela de um navegador que tem o recurso:

![Nove retratos de Marilyn Monroe numa grade de três por três, cada um com um conjunto diferente de cores: rosa e amarelo, turquesa e laranja, ameixa e azul-marinho, lilás e azul-celeste, magenta e laranja, verde-menta e âmbar, cinza e azul-ardósia, verde e vermelho-tijolo, verde-azulado e magenta.](/images/blog/css-linked-parameters-svg/nove-posteres-firefox-nightly.webp)

Nove pinturas, um arquivo de 50 KB, uma requisição de rede. A especificação é explícita: quando a mesma URL aparece várias vezes com parâmetros diferentes, os navegadores precisam pintar cada uma corretamente, mas podem compartilhar o documento por trás delas.

Essa é a parte que nenhuma técnica existente oferece. Símbolos SVG podem mudar de cor, mas só por meio de um marcador inline. Fragmentos e stacks funcionam em `<img>`, mas cada variação de cor precisa estar gravada no arquivo de antemão. Aqui, o arquivo continua sendo um modelo, e a página decide.

## O fallback

Agora, a mesma página num navegador sem suporte a nada disso:

![A mesma grade de três por três, mas os nove retratos são idênticos: fundo rosa, cabelo amarelo, rosto cor de pele e uma matriz de tinta quase preta.](/images/blog/css-linked-parameters-svg/nove-posteres-fallback.webp)

Nove pôsteres idênticos, nas cores originais da gravura. Warhol não ficaria impressionado, mas a página não quebra. Todo `env()` do arquivo tem um fallback, então um navegador sem suporte simplesmente renderiza o SVG do jeito que ele foi desenhado.

Isso faz deste um tipo raro de recurso novo do CSS: o progressive enhancement sai de graça. Não é preciso `@supports` nem uma folha de estilo de fallback, basta escolher cores padrão sensatas ao exportar o arquivo. O que já ia acontecer de qualquer jeito.

Se isso parece familiar, é o mesmo contrato que as <a href="/css/variaveis-css-guia-pratico/" target="_blank">custom properties</a> sempre tiveram. `var(--brand, black)` cai no preto quando `--brand` nunca foi definida, e `env(--brand, black)` cai no preto quando nada foi passado.

> **Nota:** Por falar nisso: `@supports (link-parameters: param(--a, red))` funciona no Nightly, para quem quiser servir um layout diferente aos navegadores que conseguem de fato distinguir os nove painéis.

## Ainda não chegou lá

Mesmo no Nightly, só uma parte da especificação está implementada, e o resto é acompanhado no <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1812163" target="_blank" rel="noopener noreferrer">bug 1812163</a>. A propriedade em si funciona, inclusive em imagens de fundo:

```css
div {
	background-image: url('poster.svg');
	link-parameters: param(--back, tomato);
}
```

Mas as outras duas formas que a especificação define para passar parâmetros ainda não funcionam. Nem o modificador de `url()`:

```css
div {
	/* Não, ainda não */
	background-image: url('poster.svg' param(--back, tomato));
}
```

Nem o fragmento da URL, que é o mais aguardado pelo autor, porque funcionaria direto do HTML, sem CSS nenhum:

```html
<!-- Também não, ainda -->
<img src="poster.svg#:~:param(--back,tomato)" alt="">
```

Os atalhos `param(color, …)` e `param(accent-color, …)` também estão faltando, e essa é a perda maior: são eles que levariam o `currentcolor` para um `<img>`.

Passar `param(--color, currentcolor)` no lugar não resolve, porque a palavra-chave é resolvida dentro da imagem, onde a cor ainda é preta.

Algumas faltas menores:

- A anotação de tipo opcional, `param(--back <color>, tomato)`, não existe ainda. Sem ela, funciona normalmente.
- Um `<svg>` inline com `<use href="sprite.svg#icon"/>` não recebe parâmetros. O `currentcolor` atravessa essa fronteira, os linked parameters não.
- O `<object>` também não recebe nada. Por enquanto, só `<img>` e imagens do CSS.

Aliás, os valores não se limitam a cores. Qualquer coisa que caiba numa declaração CSS funciona, inclusive `var()` da página:

```css
img {
	link-parameters: param(--color, var(--brand));
}
```

E, do lado do SVG, o `env()` também não se limita ao `fill`. Larguras de traço, opacidades, transformações, o que a imagem precisar:

```xml
<path
	stroke="env(--stroke, gray)"
	stroke-width="env(--width, 2)"
	d="…"
/>
```

## Vale a espera

Então, dá para usar CSS Linked Parameters hoje? Não, e não vai dar por um bom tempo. Um motor, um canal, meia especificação.

Mesmo assim, vale acompanhar, pelo que isso mudaria quando estiver em todo lugar. Um arquivo de ícone em vez de um por tema. Uma ilustração que segue a cor da marca sem ser colocada inline em cada página. Qualquer caso em que a forma é fixa e a paleta não, servido como uma imagem comum em cache.

> **Dica:** Chris Coyier detalha o que isso pode mudar em sistemas de ícones no artigo <a href="https://blog.master.dev/svg-linked-parameters-will-change-how-we-do-icon-systems/" target="_blank" rel="noopener noreferrer">SVG Linked Parameters Will Change How We Do Icon Systems</a>.

Até lá, a única coisa a fazer com ele é brincar. Abra os <a href="https://pepelsbey.dev/articles/svg-link-params/demo/warhol.html" target="_blank" rel="noopener noreferrer">nove pôsteres</a> no Nightly, escolha as próprias cores e veja até onde quatro parâmetros chegam.

Warhol provavelmente teria gostado deste. Mesma tela, tinta diferente, roda de novo 🎨

## Perguntas frequentes

### Um site de terceiros consegue estilizar à vontade um SVG meu com `link-parameters`?

Não. O valor só chega às propriedades que o próprio SVG abre com `env()`. A [seção de segurança da especificação](https://drafts.csswg.org/css-link-params-1/) reconhece que o mecanismo cria um jeito novo de passar informação a um recurso vinculado, possivelmente vindo de uma fonte hostil, e por isso não exige nenhum acordo prévio: um valor hostil só afeta as propriedades CSS que o recurso escolheu expor. Um parâmetro que o arquivo não lê com `env()` simplesmente não tem efeito.

### Preciso repetir o fallback em cada `env()` do arquivo SVG?

Não precisa. A [especificação sugere](https://drafts.csswg.org/css-link-params-1/) ler o parâmetro uma vez numa custom property na raiz do SVG, com o valor padrão ali, e usar `var()` no resto do arquivo. Se a página mandar `--color`, a variável recebe esse valor; se não mandar, fica com o padrão. É o mesmo contrato da [seção sobre o fallback](#o-fallback), só que concentrado num lugar.

```css
:root {
  --color: env(--color, blue);
}
.logo {
  fill: var(--color);
}
```

### O que acontece se o mesmo parâmetro vier da propriedade e do `url()`?

Vale o do `url()`. A [especificação](https://drafts.csswg.org/css-link-params-1/) junta todos os parâmetros numa lista só, nesta ordem: a propriedade `link-parameters`, depois as diretivas do fragmento da URL e por fim os `param()` dentro de `url()`. Quando um nome se repete, o último da lista ganha. Na prática ainda não dá para testar isso: como mostra a [seção sobre o que falta](#ainda-não-chegou-lá), o Nightly só implementa a propriedade.

### Dá para animar a troca de cor de um ícone com `transition` no `:hover`?

Não de forma suave. A [página do MDN sobre `link-parameters`](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/link-parameters) define o tipo de animação da propriedade como discreto, ou seja, o navegador passa de um conjunto de parâmetros para o outro de uma vez, sem cores intermediárias. A troca no hover funciona, mas sem a transição gradual entre os dois tons que uma propriedade como `fill` teria num SVG inline.

## Teste seus conhecimentos

**Pergunta 1.** O `<img src="logo.svg">` está dentro de `.logo-wrapper`, e o SVG pinta o fundo com `env(--color, #c1f07c)`. Num navegador com suporte, de que cor o fundo do logo sai?

```css
.logo-wrapper {
  link-parameters: param(--color, #ff8052);
}
```

- Coral (`#ff8052`), herdado do wrapper
  Seria assim se a propriedade fosse herdada, como `color`. Ela não é: o `<img>` dentro do wrapper continua com `link-parameters: none`.
- Verde (`#c1f07c`), o fallback do `env()` **(correta)**
  A propriedade não é herdada e só vale no elemento que carrega a imagem. Como nada chega ao `<img>`, o SVG usa o fallback.
- Sem cor nenhuma, porque o `env()` fica inválido
  O fallback existe justamente para isso: sem parâmetro, o `env()` usa o segundo argumento e o SVG é renderizado como foi desenhado.

Verde, o fallback. `link-parameters` não é herdada, então precisa estar no próprio `<img>` (ou no elemento com a imagem de fundo). No wrapper, ela não faz nada.

**Pergunta 2.** O `poster.svg` tem `<path fill="env(--back, #f25a80)" …/>`. Que cor o fundo do pôster recebe com este CSS?

```css
img {
  link-parameters: param(--fundo, #4a9fac);
}
```

- Rosa (`#f25a80`), o fallback do SVG **(correta)**
  O SVG pede `--back` e a página manda `--fundo`. Os nomes não batem, então o `env()` não recebe nada e usa o fallback.
- Turquesa (`#4a9fac`), o valor enviado pela página
  O valor só chega quando o nome em `param()` é o mesmo do `env()`. O primeiro argumento das duas funções é o nome, e ele precisa ser idêntico.
- Nenhuma, o path fica transparente
  Um parâmetro que o SVG não usa é só ignorado. O `env(--back, …)` continua com o fallback e o path é pintado normalmente.

Rosa, o fallback. Em `param()` e em `env()`, o primeiro argumento é o nome do parâmetro, e é por ele que os dois lados se encontram. Com nomes diferentes, o valor enviado não tem para onde ir.

**Pergunta 3.** O SVG usa `fill="env(--color, #c1f07c)"`. Com este CSS, num Firefox Nightly com o recurso, de que cor sai o preenchimento?

```css
img {
  color: red;
  link-parameters: param(--color, currentcolor);
}
```

- Vermelho, a cor do `<img>`
  É o que se espera, mas `currentcolor` não é resolvido no `<img>`. Ele chega como palavra-chave e é resolvido dentro do documento da imagem.
- Verde (`#c1f07c`), o fallback
  O parâmetro chega, então o fallback não entra. O problema é o valor que ele carrega, e não a ausência de valor.
- Preto, a cor padrão dentro do SVG **(correta)**
  A palavra-chave é resolvida dentro da imagem, onde `color` continua preto. Levar a cor do texto para o `<img>` seria o papel do atalho `param(color, …)`, que ainda não existe no Nightly.

Preto. `currentcolor` vira a cor do documento da imagem, e não a do `<img>` na página. O caminho para isso seriam os atalhos `param(color, …)` e `param(accent-color, …)`, que ainda faltam na implementação.

**Pergunta 4.** Um site usa o `poster.svg` com `link-parameters` para pintar nove painéis. O que ele precisa fazer para que a página não quebre nos navegadores sem suporte?

- Envolver as regras num `@supports` e criar uma folha de estilo alternativa
  O `@supports` funciona no Nightly, mas só é útil para servir outro layout. Para a página não quebrar, ele não é necessário.
- Gerar uma versão do SVG para cada combinação de cores
  É exatamente o trabalho que o recurso evita. Os navegadores sem suporte mostram as cores padrão, sem nenhum arquivo extra.
- Nada além de dar um fallback a cada `env()` do arquivo **(correta)**
  Com um fallback em cada `env()`, o navegador que não entende `link-parameters` renderiza o SVG como ele foi desenhado. Os nove painéis ficam iguais, mas a página funciona.

Basta o fallback em cada `env()`. O navegador sem suporte ignora `link-parameters` e pinta o SVG com as cores padrão, como acontece com `var(--brand, black)` quando a custom property nunca foi definida.

---

Fonte: [dpw - desenvolvimento para web](https://dpw.dev/) (pt-BR).
Guia para agentes: https://dpw.dev/llms.txt
Índice completo: https://dpw.dev/sitemap-index.xml
Feed: https://dpw.dev/rss.xml
