# Como animar border-image em CSS

> Como animar border-image com gradientes, custom properties registradas e border-image-slice para criar bordas que se desenham sozinhas no hover.

URL: https://dpw.dev/css/animar-border-image-css/  
Publicado em: 2026-08-24  
Categoria: css  
Tags: animacao-css, interface  
Autor: Tárcio Zemel

Bordas que se desenham sozinhas no hover, giram como um ponteiro de relógio ou se quebram em fatias repetidas. Todos esses efeitos saem de **border-image**, uma propriedade que existe há mais de uma década e quase ninguém usa, sem uma única linha de JavaScript.

> Artigo baseado em [Animating CSS border-image](https://css-tricks.com/animating-css-border-image/).

O resumo é que dá para usar uma imagem ou um gradiente como borda, em vez dos estilos padrão (e um tanto sem graça) como `solid` ou `dashed`. A ideia aqui é ir além disso e mostrar como animar imagens de borda para criar interfaces bem mais interessantes.

Assim:

[Exemplo no CodePen](https://codepen.io/anon/pen/ByQQJQj)

A `border-image` é uma daquelas propriedades que a gente toma como garantidas. E ela não é nova: Andy Clarke tem <a href="https://css-tricks.com/revisiting-css-border-image/" target="_blank" rel="noopener noreferrer">um artigo relativamente recente</a> que revisita a propriedade e mostra o quanto é possível ser criativo com ela. Vale a leitura.

## Por que usar imagens de borda?

Existe uma ressalva grande nas imagens de borda: **elas não acompanham a curvatura das bordas**. É uma limitação séria para uma animação que percorre o elemento inteiro, como a que será feita aqui. Mas há como contornar isso neste exemplo.

Só que isso levanta a pergunta: *"por que contornar a limitação se existem outras abordagens?"* Basta olhar a abordagem do Temani Afif, que usa uma máscara CSS (ele escreveu <a href="https://css-tip.com/speed-control/" target="_blank" rel="noopener noreferrer">um texto excelente</a> sobre isso):

[Exemplo no CodePen](https://codepen.io/anon/pen/RNoNJLW)

A `border-image` é interessante porque é bem eficiente, sobretudo quando o assunto é animar imagens de borda e gradientes. Isso acontece por dois motivos.

O primeiro é que replicar o desenho em todas as bordas é fácil (e automático). O segundo é que dá para "fatiar" as imagens com a propriedade `border-image-slice`.

Ela funciona de forma parecida com `background-size` e `background-position`, onde uma única fatia da imagem pode ser aproveitada. A diferença é que as fatias da imagem de borda podem percorrer as bordas inteiras, e animar isso cria efeitos bonitos.

## O HTML

Nada de mais por aqui: apenas uma `div` com um pouco de texto formatado dentro:

```markup
<div class=card><strong>Bruce Wayne</strong></div>
```

E a imagem? Ela entra como background em CSS, então vamos direto para lá.

## Estilos base

O `.card` recebe dimensões definidas e uma imagem de fundo:

```css
.card {
  width: 150px;
  aspect-ratio: 0.69;
  position: relative;
  background: center/90% no-repeat;
  background-image: url("batman.jpg");
}
```

Também vale um estilo no texto, para garantir que ele não fique exatamente sobre o fundo:

[Exemplo no CodePen](https://codepen.io/anon/pen/azBJOKg)

## A imagem de borda

Aqui será usado um gradiente CSS de uma cor só, por dois motivos: primeiro porque ele é um tipo de imagem de fundo, e segundo porque fica mais fácil demonstrar a animação.

Todos os valores de `border-image` também serão definidos em suas próprias propriedades longhand, para deixar claro qual valor afeta o gradiente de qual maneira.

Começando pelo efeito de um `linear-gradient` simples:

```css
.card {
  /* ... */

  /* Cria uma cor linear */
  border-image-source: linear-gradient(-45deg, red 0%, transparent 0%);

  /* Controla como o gradiente é fatiado */
  border-image-slice: 1;

  /* Define a espessura física da borda */
  border-image-width: 5px;
}
```

Talvez você tenha notado na demonstração que existe uma pequena folga entre a borda animada e a imagem. Dá para empurrar a borda para fora do `.card` com a propriedade `border-image-outset`:

```css
.card {
  /* ... */

  border-image-source: linear-gradient(-45deg, red 0%, transparent 0%);
  border-image-slice: 1;
  border-image-width: 5px;

  /* Empurra a borda para fora da div */
  border-image-outset: 5px;
}
```

São necessárias `border-image-source` e `border-image-width` para renderizar a borda. No início, a fonte da imagem (o gradiente) é totalmente transparente. Como `red` e `transparent` estão ambas posicionadas em `0%`, o navegador não tem espaço para misturar as cores.

E como `transparent` vem em segundo lugar no código, é ela que assume a posição inicial em `0%` e preenche o resto do gradiente. O `border-image-slice: 1` cria fatias de `1px` do gradiente, o que gera um preenchimento suave ao longo de toda a borda.

## Animando a imagem de borda

Há outro detalhe importante sobre gradientes, especialmente sobre animá-los: por padrão, não dá. <a href="https://css-tricks.com/interpolating-numeric-css-variables/" target="_blank" rel="noopener noreferrer">Fazer a transição (ou interpolação) de uma cor para outra</a> é difícil, porque na prática se está transicionando os pontos inicial e final de um gradiente, que são porcentagens.

É aí que entra o registro de uma custom property, já que <a href="/css/variaveis-css-guia-pratico/" target="_blank">variáveis CSS</a> podem, sim, ser animadas:

```css
@property --p {
  syntax: "<percentage>";
  initial-value: 0%;
  inherits: false;
}
```

E dá para usá-la no gradiente:

```css
.card {
  /* ... */
  border-image-source: linear-gradient(-45deg, red var(--p), transparent 0%);
}
```

Agora, digamos que `--p` deva transicionar do valor padrão de `0%` para `100%` quando o `.card` receber hover:

```css
.card {
  /* ... */
  border-image-source: linear-gradient(-45deg, red var(--p), transparent 0%);
  /* ... */

  &:hover {
    --p: 100%;
  }
}
```

Isso diz ao navegador que o vermelho deve terminar a transição na marca de 100% (o fim da linha). O gradiente cresce até virar um vermelho sólido, como se a borda estivesse se desenhando:

[Exemplo no CodePen](https://codepen.io/anon/pen/EaNZaWL)

## Variações

O exemplo anterior já seria um bom lugar para parar, mas há muito mais a fazer. Dá para mudar a direção, acelerar, desacelerar, parar em outras posições ou usar tipos diferentes de gradiente.

Vamos tentar um `conic-gradient` em vez de um linear. É possível animar o valor de `border-image-slice` e usar `border-image-repeat: round` para repetir as fatias dentro das bordas.

O empilhamento `round` tenta encaixar um número inteiro de repetições na borda e, quando não consegue, a imagem estica ou comprime um pouco até caber.

```css
.card {
  /* Cria uma roda de cores nítida e expansível usando a variável de ângulo */
  border-image-source: conic-gradient(from 0deg, red 0deg, transparent 0%);

  /* Repete as regiões fatiadas suavemente, sem cortar */
  border-image-repeat: round;

  border-image-width: 5px;
  border-image-slice: 1;
}
```

Ainda é preciso registrar custom properties para movimentar o gradiente, desta vez para transicionar o valor de `border-image-slice` (chamado aqui de `--n`) e o ângulo do `conic-gradient` (chamado de `--a`):

**Nota:** também é possível animar `border-image-slice` diretamente, sem passar por uma custom property registrada. O resultado varia um pouco conforme a forma como o navegador lida com essas mudanças.

```css
/* Registra uma custom property para o border-image-slice */
@property --n {
  syntax: "<number>";
  initial-value: 1;
  inherits: false;
}

/* Registra uma custom property para o ângulo do gradiente */
@property --a {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}
```

Agora, jogando essas variáveis no CSS original:

```css
.card {
  border-image-source: conic-gradient(from var(--a), red var(--a), transparent 0%);
  border-image-width: 5px;
  border-image-slice: var(--n);
  border-image-repeat: round;
}
```

…e dizendo ao CSS exatamente quais propriedades estão em transição, o que é bom para a performance:

```css
.card {
  border-image-source: conic-gradient(from var(--a), red var(--a), transparent 0%);
  border-image-width: 5px;
  border-image-slice: var(--n);
  border-image-repeat: round;
  transition-property: --n, --a;
  transition-duration: 0.6s;
}
```

…e fazendo as propriedades transicionarem no hover:

```css
.card {
  border-image-source: conic-gradient(from var(--a), red var(--a), transparent 0%);
  border-image-width: 5px;
  border-image-slice: var(--n);
  border-image-repeat: round;
  transition-property: --n,--a;
  transition-duration: 0.6s;

  &:hover {
    /* Aumenta a profundidade do fatiamento para repetir o padrão da borda */
    --n: 20;
    /* Gira o gradiente uma volta completa para desenhar a borda */
    --a: 360deg;
  }
}
```

O valor da fatia (`--n`) começa em `1` e sobe até `20` no hover. Isso significa que a fatia fica mais grossa (até `20px`), o que dá para perceber pelas quebras que aparecem nas bordas.

[Exemplo no CodePen](https://codepen.io/anon/pen/myOWbzR)

## Mais exemplos

Como dito antes, há muita coisa possível com imagens de borda animadas: animar várias cores, usar gradientes repetidos e por aí vai. Aqui estão alguns exemplos reunidos.

[Exemplo no CodePen](https://codepen.io/anon/pen/ByQQJQj)

A lição de casa fica sendo destrinchar cada um desses exemplos e criar novos efeitos a partir deles. Se a animação de borda for o próximo passo do seu repertório, vale conferir também <a href="/css/10-dicas-animacoes-transicoes-css/" target="_blank">10 dicas para melhores animações e transições CSS</a> e <a href="/css/css-border-shape/" target="_blank">a nova propriedade CSS border-shape</a>.

---

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
