Vídeos de fundo, autoplay e Core Web Vitals

Vídeos de fundo, autoplay e Core Web Vitals

Última verificação: 14 de outubro de 2026
16 min de leitura
Guia
Core Web Vitals

#O que um vídeo de fundo realmente custa em 2026

Um hero com movimento vende atmosfera. Também compete pelo mesmo orçamento de rede, CPU e paint que o título, o CTA e a imagem que o Lighthouse trata como Largest Contentful Paint. Em sites WordPress geridos a partir de Portugal e servidos a clientes em PT, ES e DE, o padrão que mais aparece nas auditorias é o mesmo: o vídeo entra no HTML inicial, o poster é irrelevante ou inexistente, e o autoplay falha em Safari porque faltou muted ou playsinline.

Este tutorial trata o vídeo de fundo como um recurso de performance, não como um embelezamento. A pergunta útil não é “como faço o ficheiro tocar”, e sim “em que condições o movimento merece bytes no caminho crítico”.

Nos browsers modernos, autoplay sem gesto do utilizador só é fiável quando o áudio está silenciado. A documentação da MDN sobre autoplay e o elemento video descrevem exatamente esse contrato. O guia da web.dev sobre otimizar LCP mostra porque um vídeo mal colocado empurra o maior elemento da viewport para fora do orçamento de 2,5 s.

#Como fazer autoplay de vídeo com muted e playsinline

Chrome, Firefox, Edge e Safari permitem autoplay de media quando o elemento está muted (ou o volume efetivo é zero) e, no iOS Safari, quando playsinline está presente. Sem estes atributos, o play() devolve uma Promise rejeitada. O hero fica com um frame preto ou com o poster congelado, e o visitante assume que a página está partida.

Atributos mínimos para um fundo decorativo:

<video
  class="hero-video"
  autoplay
  muted
  loop
  playsinline
  preload="none"
  poster="/media/hero-poster.avif"
>
  <source src="/media/hero.webm" type="video/webm" />
  <source src="/media/hero.mp4" type="video/mp4" />
</video>

Notas práticas que evitam tickets de suporte:

  • muted tem de estar no markup. Definir video.muted = true só em JavaScript chega tarde para a primeira tentativa de autoplay em alguns WebViews.
  • playsinline é obrigatório no iOS; sem ele o Safari tenta ecrã completo e aborta o autoplay de fundo.
  • loop sem faixa de áudio reduz surpresas quando o utilizador reativa o som por engano noutro separador.
  • Não dependa de autoplay sozinho: chame video.play().catch(() => {}) depois de anexar o src, e trate a rejeição como estado normal em redes lentas ou com poupança de dados ativa.

Em Portugal, muitos formulários de contacto abrem em telemóveis com poupança de dados da operadora. Nesse cenário o browser pode adiar media mesmo com atributos corretos. O poster deixa de ser “nice to have” e passa a ser o único conteúdo estável do hero.

#Política de autoplay do Chrome e Media Engagement Index

As regras do Chrome estão publicadas na página do Chrome for Developers sobre autoplay. A política chegou no Chrome 66 para elementos de áudio e vídeo, e a primeira regra resolve a questão do vídeo de fundo: o autoplay silenciado é sempre permitido. O autoplay com som só é permitido quando se verifica uma destas condições:

  • o utilizador interagiu com o domínio (clique, toque ou semelhante),
  • no desktop, o utilizador ultrapassou o limiar do Media Engagement Index,
  • no telemóvel, o utilizador adicionou o site ao ecrã principal, ou no desktop instalou-o como PWA.

O Media Engagement Index (MEI) mede a propensão de uma pessoa para consumir media num determinado site. Uma reprodução só conta se durar mais de sete segundos, tiver áudio presente e não silenciado, o separador estiver ativo e o vídeo for maior do que 200x140 px. Um loop silencioso no hero nunca constrói MEI, nem precisa. Pode consultar os seus próprios valores em about://media-engagement.

Os iframes seguem a mesma lógica. Um iframe da mesma origem pode fazer autoplay por omissão; um iframe de outra origem (um player do YouTube ou do Vimeo) precisa que a permissão lhe seja delegada com allow="autoplay". Sem ela, play() é rejeitado com NotAllowedError e o atributo autoplay é ignorado.

#Como verificar se o autoplay é permitido antes de chamar play

HTMLMediaElement.play() devolve uma Promise. O guia de autoplay da MDN mostra o padrão: se a Promise for rejeitada e o nome do erro for NotAllowedError, o browser recusou a reprodução por questões de permissão, por isso mostre um controlo de reprodução ou mantenha o poster. Qualquer outro erro aponta para um problema de carregamento ou descodificação que vale a pena registar.

const video = document.querySelector('.hero-video');
video.play().catch((error) => {
  if (error.name === 'NotAllowedError') {
    video.closest('.hero')?.classList.add('is-static'); // manter o poster
  }
});

Existe também navigator.getAutoplayPolicy('mediaelement'), que responde "allowed", "allowed-muted" ou "disallowed" antes de tentar seja o que for. Segundo os dados de compatibilidade de browsers da MDN, só está disponível no Firefox (a partir da versão 112), por isso trate-o como um atalho opcional atrás de uma verificação de suporte, nunca como o único caminho.

Do lado do servidor, o cabeçalho Permissions-Policy controla que origens podem fazer autoplay. O valor por omissão é self. Permissions-Policy: autoplay=() desativa o autoplay em todo o documento, um interruptor pouco subtil mas eficaz em páginas onde o movimento nunca deve arrancar sozinho.

#O que o Safari no iOS faz com um vídeo em autoplay

A WebKit descreveu as regras do iOS em New video policies for iOS (julho de 2016, iOS 10), e continuam a explicar a maioria dos casos de “no desktop funciona, no iPhone fica parado”:

  • <video muted> pode fazer autoplay sem gesto do utilizador, tal como um vídeo cujo ficheiro não tem nenhuma faixa de áudio.
  • <video playsinline> reproduz dentro da página no iPhone em vez de passar para ecrã inteiro.
  • Um vídeo com autoplay pausa quando deixa de estar visível, por exemplo quando é deslocado para fora da viewport.
  • Se um vídeo ganhar uma faixa de áudio ou deixar de estar silenciado sem gesto do utilizador, a reprodução pausa.

Daqui saem duas consequências práticas. Remova a faixa de áudio ao codificar (-an no FFmpeg), porque um ficheiro sem áudio continua elegível mesmo que algum script altere muted mais tarde. E não escreva lógica que assuma que o loop continua a correr fora do ecrã no iOS: o browser já o pausa aí.

#Imagem poster do vídeo como elemento LCP

Se o maior elemento da viewport inicial for o <video>, o LCP espera por frames descodificados. Em ligações 4G instáveis isso empurra o LCP para 4-6 s com facilidade. A correção padrão é tratar o poster como o candidato a LCP e só depois substituir por movimento.

Regras que funcionam em produção:

  1. Exporte o poster no mesmo enquadramento do primeiro frame do vídeo (evita CLS quando o vídeo arranca).
  2. Sirva o poster em AVIF ou WebP com dimensões explícitas no CSS ou nos atributos width/height.
  3. Faça preload do poster (<link rel="preload" as="image" href="...">) se ele for o LCP declarado, não do ficheiro de vídeo.
  4. Não coloque preload="auto" no <video> do hero. Isso compete com CSS e fontes no caminho crítico.

A web.dev resume o princípio: otimize o recurso que realmente pinta o LCP. Num hero com vídeo, esse recurso é quase sempre a imagem estática, não o stream.

Numa landing de serviços WordPress dirigida ao mercado lusófono europeu, medimos o mesmo template duas vezes: com src no HTML inicial o LCP mediava acima de 3,8 s em lab mobile; com poster AVIF no HTML e src injetado após window.load o LCP caiu para a faixa do poster (~1,6-2,1 s), e o vídeo arrancava 1-2 s depois sem bloquear o CTA.

A definição de LCP da web.dev inclui <video> entre os elementos que podem ser o Largest Contentful Paint e indica que marca temporal é usada: o tempo de carregamento da imagem poster ou o tempo de apresentação do primeiro frame, o que acontecer primeiro. Um poster rápido é, portanto, a alavanca que controla: fixa o tempo de LCP mesmo quando o vídeo chega depois. Sem poster, a métrica espera pelo primeiro frame descodificado, que depende do download do vídeo.

O objetivo não muda num hero com vídeo: LCP de 2,5 segundos ou menos, medido no percentil 75 dos carregamentos de página e separado entre telemóvel e desktop. Um hero que passa no Wi-Fi do escritório mas falha no percentil 75 em telemóvel, falha.

#Que valor de preload usar num vídeo de fundo

O atributo preload controla quanto o browser descarrega antes de um gesto explícito:

ValorComportamento típicoQuando usar num fundo
noneQuase nada até haver src ativo e pedido de playHero decorativo, mobile first
metadataCabeçalhos e talvez um frameQuando precisa da duração ou dimensões sem stream completo
autoO browser pode descarregar agressivamenteQuase nunca em fundos; reserva para players com intenção clara de ver

Para fundos, o default sensato é preload="none" mais um src diferido. Se o markup já inclui <source>, alguns browsers ignoram parcialmente a intenção de none. A abordagem mais previsível é omitir src/source no HTML inicial e atribuir o URL só quando as condições de motion e viewport forem cumpridas.

<video class="hero-video" muted loop playsinline preload="none"
       poster="/images/hero-poster.avif" data-src="/videos/hero.webm"></video>
<script>
  const video = document.querySelector('.hero-video');
  const allowMotion = !matchMedia('(prefers-reduced-motion: reduce)').matches;
  if (video && allowMotion && matchMedia('(min-width: 768px)').matches) {
    addEventListener('load', () => {
      video.src = video.dataset.src;
      video.play().catch(() => {});
    }, { once: true });
  }
</script>

Este padrão mantém o HTML inicial leve, respeita motion reduzido e evita gastar dados móveis em movimento decorativo abaixo de 768 px.

#Desativar vídeo de fundo com prefers-reduced-motion

A media query prefers-reduced-motion: reduce não é um detalhe de acessibilidade opcional. Visitantes com vestibulopatia, migrânea ou simplesmente com a opção ativada no sistema operativo pedem menos movimento. Um loop infinito atrás do texto falha esse pedido.

Implementação mínima e honesta:

@media (prefers-reduced-motion: reduce) {
  .hero-video {
    display: none;
  }
  .hero {
    background-image: url("/images/hero-poster.avif");
    background-size: cover;
  }
}

No JavaScript, a mesma condição deve impedir a atribuição de src. Esconder o elemento com CSS depois de o ficheiro já ter sido descarregado não recupera a largura de banda gasta.

Se o vídeo transporta informação (demonstração de produto, tutorial), não o use como fundo silencioso. Coloque-o num player com controlos, legendas e botão de play explícito. Fundo decorativo e conteúdo informativo são contratos diferentes com o utilizador.

#WCAG 2.2.2 pausar, parar e ocultar o vídeo de fundo

Um vídeo de fundo em loop é conteúdo em movimento, e as WCAG cobrem-no no nível A. O critério de sucesso 2.2.2 diz que, para qualquer informação em movimento, intermitente ou em deslocamento que (1) começa automaticamente, (2) dura mais de cinco segundos e (3) é apresentada em paralelo com outro conteúdo, tem de existir um mecanismo para o utilizador a pausar, parar ou ocultar, a não ser que o movimento seja essencial. A página Understanding 2.2.2 explica que se escolheram cinco segundos porque é tempo suficiente para captar a atenção do utilizador, mas curto o bastante para que ele possa esperar que a distração passe.

Um loop no hero cumpre as três condições: arranca sozinho, repete-se para lá de cinco segundos e está por trás do título e do CTA. Por isso, é obrigatório um controlo de pausa real, e respeitar prefers-reduced-motion não o substitui, porque muitas pessoas que se distraem com movimento nunca alteram essa definição do sistema.

O que o controlo precisa na prática:

  • um <button> nativo acessível por teclado, colocado junto ao vídeo e visível tanto sobre o poster como sobre os frames em movimento,
  • um nome acessível que descreva a ação (“Pausar vídeo de fundo”), atualizado quando o estado muda,
  • um estado de pausa que se mantenha pelo menos durante a visualização atual da página, para que o loop não recomece no scroll seguinte.

O áudio é outro critério. Se um clip alguma vez reproduzir som automaticamente, as WCAG remetem para o 1.4.2 Audio Control, mais uma razão para manter os loops de fundo silenciosos.

#Vídeos de fundo na biblioteca de media do WordPress

O media library do WordPress foi desenhado para imagens e PDFs. Vídeos de hero expõem vários atalhos perigosos:

  • Upload direto para uploads/ sem reencode. Um .mov de 80 MB filmado no iPhone passa a URL pública. O tema faz <video src="...mov"> e o primeiro visitante em 4G paga a fatura.
  • Plugins de “background video” que injetam YouTube no above-the-fold. O iframe puxa o player completo, cookies e scripts de recomendação antes do primeiro paint útil. O LCP e o INP sofrem mesmo com fachada mal configurada.
  • Dependência de oEmbed no conteúdo do hero. O bloco Embed resolve o provider no servidor, mas o HTML final ainda é um iframe pesado. Para fundo, prefira ficheiro self-hosted curto ou um shortcode que só imprime <video> com poster.
  • Falta de loading strategy no tema. Muitos temas filhos copiam o markup do customizer sem preload="none" e sem teste em staging com throttling 4G.
  • CDN que cacheia o HTML com src absoluto de staging. Depois do go-live o vídeo 404 e o poster fica sozinho - o que, ironicamente, é melhor para performance, mas parte a narrativa visual.
  • Áudio residual no ficheiro. Designers exportam “sem som” mas deixam uma faixa silenciosa. Alguns browsers tratam isso de forma inconsistente face a autoplay. Remova a faixa com FFmpeg (-an) e volte a gerar WebM/MP4.

Fluxo de trabalho que reduz regressões:

  1. Reencode local (WebM + H.264 MP4), alvo tipicamente abaixo de alguns megabytes para loops de 6-12 s em 720p ou 1080p cropado.
  2. Carregue o poster otimizado e o vídeo via SFTP ou media library, mas referencie-os no tema com caminhos estáveis.
  3. Teste em Safari iOS real, Chrome Android e Firefox desktop com prefers-reduced-motion ligado.
  4. Meça LCP no PageSpeed Insights e no campo (CrUX) depois de uma semana, não só no Lighthouse local.

Veja também os nossos serviços de otimização de velocidade WordPress quando o gargalo já não é só o markup do hero.

#Alojar vídeo no próprio site ou usar YouTube e Vimeo

YouTube e Vimeo resolvem transcoding e CDN. Para um fundo full-bleed no primeiro ecrã, o custo de JavaScript do player raramente compensa.

  • YouTube: precisa de mute=1, controls=0, e o truque da playlist com o mesmo ID para loop. Continua a descarregar o player.
  • Vimeo: background=1 simplifica a UI, mas o iframe e a API continuam no caminho crítico se o embed estiver no HTML inicial.
  • Self-host: controlo total de preload, poster e codecs. Exige disciplina de compressão e um fallback MP4 para Safari quando o primário é AV1/WebM.

A fachada (lite embed) faz sentido quando o vídeo é conteúdo a pedido. Para atmosfera de fundo, a fachada correta é o poster estático - sem player por baixo até haver condições de motion.

#Verificar a descodificação de AV1 com Media Capabilities

Colocar AV1 como primeiro <source> só indica se o browser consegue reproduzir o codec, não se o dispositivo o descodifica em hardware. A descodificação de AV1 por software num telemóvel mais antigo pode engasgar e gastar bateria, o oposto do que um loop decorativo deve fazer.

A Media Capabilities API responde a essa pergunta. navigator.mediaCapabilities.decodingInfo() devolve três booleanos: supported (o conteúdo pode ser descodificado), smooth (reproduz à taxa de frames configurada sem perder frames) e powerEfficient. Para type: "file" a configuração precisa de contentType, width, height, bitrate e framerate; omitir um valor lança um TypeError. Os dados de compatibilidade da MDN indicam Chrome 66, Firefox 63 e Safari 13.

const av1 = {
  type: 'file',
  video: {
    contentType: 'video/mp4; codecs="av01.0.05M.08"',
    width: 1280,
    height: 720,
    bitrate: 1500000,
    framerate: 30,
  },
};

const pickSource = async () => {
  if (!('mediaCapabilities' in navigator)) return '/media/hero.mp4';
  const r = await navigator.mediaCapabilities.decodingInfo(av1);
  return r.supported && r.smooth && r.powerEfficient
    ? '/media/hero.av1.mp4'
    : '/media/hero.mp4';
};

Use as mesmas dimensões e o mesmo bitrate com que codificou o ficheiro; caso contrário, a resposta descreve outro ficheiro.

#Vídeo silenciado em vez de um GIF animado

Se o “fundo” for na verdade uma animação curta, um GIF é a forma mais pesada de a servir. O guia da web.dev para substituir GIFs por vídeo converte um GIF de 3,7 MB num MP4 de 551 KB e num WebM de 341 KB com estes comandos:

ffmpeg -i my-animation.gif -b:v 0 -crf 25 -f mp4 -vcodec libx264 -pix_fmt yuv420p my-animation.mp4
ffmpeg -i my-animation.gif -c vp9 -b:v 0 -crf 41 my-animation.webm

O elemento de substituição usa os mesmos atributos que um loop de fundo: <video autoplay loop muted playsinline>. Tudo o resto deste guia (poster, carregamento diferido, controlo de pausa) aplica-se sem alterações.

#Quando não usar vídeo de fundo

Salte o vídeo e fique no poster (ou num still bem composto) quando qualquer uma destas condições for verdadeira:

  • A página depende de um LCP agressivo para campanhas pagas ou SEO local (ex.: landings de cidade com orçamento de anúncios limitado).
  • Mais de metade do tráfego chega em redes móveis lentas ou com poupança de dados.
  • O texto do hero já compete visualmente com o movimento (contraste fraco, CTA pequeno).
  • O “vídeo” é um slideshow disfarçado: três fades lentos não precisam de um contentor <video>.
  • Há obrigação legal ou de marca de legendas/áudio - isso pede player com controlos, não um loop muted.
  • A equipa não tem processo para reencode e para testar prefers-reduced-motion em cada release.

Um still AVIF de 80-120 KB, bem enquadrado, supera um WebM de 3 MB que falha o autoplay em iOS. Movimento só vale a pena quando sobrevive a throttling, a políticas de autoplay e a preferências de acessibilidade sem empurrar o LCP para fora do verde.

#Como medir o impacto do vídeo de fundo no LCP

Checklist curto após cada alteração de hero:

  1. Lighthouse mobile e desktop: LCP, CLS, pedidos de vídeo no caminho crítico.
  2. Filmstrip: o CTA é legível antes do primeiro frame em movimento?
  3. Safari iOS com Low Power Mode: o autoplay falha com elegância para o poster?
  4. prefers-reduced-motion: reduce simulado nas DevTools: zero downloads de vídeo?
  5. WordPress staging com um editor sem perfil técnico a trocar o media: o markup ainda sai com muted e playsinline?

Se o vídeo só “funciona” no MacBook do designer em Wi-Fi da empresa, ainda não está pronto para produção.

#Resumo

Trate autoplay como um privilégio com regras: muted + playsinline + falha segura para poster. Proteja o LCP com uma imagem estática pré-carregada. Use preload="none" e atrase o src. Honre prefers-reduced-motion. No WordPress, não deixe o media library servir ficheiros de telemóvel sem reencode. E quando o movimento não sobrevive a estas restrições, publique o poster e siga em frente - a conversão raramente pede um loop de 8 segundos atrás do H1.

Fontes de referência usadas neste guia: optimize LCP (web.dev), LCP (web.dev), política de autoplay do Chrome, políticas de vídeo do iOS (WebKit), Understanding 2.2.2 (W3C), decodingInfo (MDN), substituir GIFs por vídeo (web.dev), elemento video (MDN), guia de autoplay (MDN).

Próximo passo

Transforme o artigo numa implementação real

Este bloco reforça a ligação interna e conduz o leitor para o passo seguinte mais útil dentro da arquitetura do site.

Quer implementar isto no seu site?

Se o problema está nos Core Web Vitals, no rendering lento ou no peso do WordPress, posso mapear e implementar a otimização.

Cluster relacionado

Explorar outros serviços WordPress e base de conhecimento

Reforce o seu negócio com suporte técnico profissional em áreas-chave do ecossistema WordPress.

FAQ do artigo

Perguntas frequentes

Respostas práticas para aplicar o tema na execução real.

SEO-readyGEO-readyAEO-ready4 Q&A
Estas otimizações vão quebrar a funcionalidade do meu site?#
Alteram o markup e a ordem de carregamento, por isso teste primeiro em staging e compare o hero com vídeo e só com o poster. Todas as técnicas deste guia recorrem ao poster quando a reprodução é recusada.
Quanta melhoria de velocidade posso esperar?#
Não há um número universal. Meça LCP, INP e CLS antes e depois no mesmo URL, em laboratório e com dados de campo no percentil 75, que é como a web.dev define o objetivo de LCP de 2,5 segundos.
Preciso de hosting caro para estas otimizações funcionarem?#
Não, estas técnicas funcionam em qualquer hosting. No entanto, hosting melhor (VPS/cloud) permite otimizações mais avançadas e melhor performance de base.
Os visitantes vão notar as melhorias de performance?#
Sobretudo em telemóvel, onde um vídeo diferido ou omitido poupa o download e o hero aparece primeiro com o poster. Confirme-o com dados de campo em vez de o assumir.

Precisa de FAQ adaptado ao setor e mercado? Criamos uma versão alinhada com os seus objetivos de negócio.

Fale connosco

Artigos Relacionados

Demasiados plugins WordPress

Um site de comparação de seguros chegou com mais de 30 plugins, uma base de dados de 705 MB e um LCP de 7.7s. O pior culpado era um contador de visualizações a escrever em wp_postmeta a cada carregamento. Um teardown real do padrão de excesso de plugins que os projetos rápidos e assistidos por IA continuam a produzir.