Pular para o conteúdo
murad.guide

A Web Aberta

Capítulo 40

Melhoria progressiva

7 min de leitura 1.310 palavras 2 gravuras

Este capítulo ensina a construir a Oficina Costeira de dentro para fora: primeiro o HTML, depois o CSS, depois o JavaScript. A Oficina Costeira é um coletivo fictício de design em João Pessoa. Este volume tem 52 capítulos. Esta é a 40.

O exemplo está em exemplos/40-melhoria-progressiva/. Abra index.html no navegador. O ciclo é o de sempre: ler, copiar, mudar uma coisa, prever, recarregar, conferir.

O que você vai aprender

A página precisa funcionar sem enfeite

Melhoria progressiva é uma ordem de trabalho. Você entrega o conteúdo primeiro. Depois acrescenta aparência. Por último, comportamento.

A visitante não é você. Ela pode estar no ônibus, com a fonte enorme, só com teclado, ou com o JavaScript bloqueado. O que você controla é o arquivo. O que você não controla é o aparelho.

Três camadas, na ordem:

  1. HTML — títulos, parágrafos, listas, links, formulário com rótulo.
  2. CSS — cor, tipo, grade, espaço.
  3. JavaScript — gráfico extra, menu extra, validação extra.

Se a camada de cima falhar, a de baixo continua. A home da Oficina Costeira já conta quem é o coletivo só com tags. O infográfico, quando existir, vai repetir números que a lista HTML já mostra.

Copie e salve como pe.html. Abra no navegador.

<!DOCTYPE html>
<html lang="pt-BR">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Início — Oficina Costeira</title>
  </head>
  <body>
    <a href="#conteudo">Pular para o conteúdo</a>
    <header>
      <p><a href="index.html">Oficina Costeira</a></p>
      <nav aria-label="Principal">
        <ul>
          <li><a href="index.html" aria-current="page">Início</a></li>
          <li><a href="projetos.html">Projetos</a></li>
        </ul>
      </nav>
    </header>
    <main id="conteudo">
      <h1>Oficina Costeira</h1>
      <p>Coletivo fictício de design em João Pessoa.</p>
      <ul>
        <li>Identidade: 8 trabalhos fictícios</li>
        <li>Publicação: 12 trabalhos fictícios</li>
      </ul>
    </main>
  </body>
</html>

Mude só o segundo item da lista para Oficina: 5. Preveja o texto na janela. Recarregue. Confira. Ainda não há CSS nem script. A página já é um documento.

Erro comum: começar pelo efeito visual e só depois “preencher” o HTML. Sem conteúdo, não há o que melhorar.

CSS chega depois, e pode faltar

Ligue uma folha no head. Se o arquivo CSS não baixar, o HTML continua. O navegador usa o visual padrão. Isso não é falha grave. É o combinado da Web.

<link rel="stylesheet" href="assets/stylesheets/main.css">

No CSS, escreva o básico primeiro: cor do texto, tamanho do tipo, foco visível. Recursos novos entram atrás de uma pergunta: o navegador entende isto?

body {
  font-family: "Segoe UI", Tahoma, sans-serif;
  line-height: 1.5;
  color: #14222b;
  background: #f7f4ee;
}

a:focus-visible {
  outline: 3px solid #c45c26;
  outline-offset: 3px;
}

@supports (display: grid) {
  .cards {
    display: grid;
    gap: 1rem;
    grid-template-columns: 1fr;
  }
}

@supports pergunta ao navegador. Se display: grid existir, as regras de dentro valem. Se não existir, os cartões empilham como blocos. A leitura segue.

Mude só o valor de color no body. Preveja o tom do texto. Recarregue. Confira. Depois desligue a folha no HTML (comente o link) e recarregue de novo. O texto ainda precisa estar lá.

Erro comum: colocar o conteúdo só como fundo de uma imagem CSS. Se a imagem não carregar, a página fica muda.

Resumo dos conceitos: HTML, CSS, JS

JavaScript é extra, não o miolo

O script só entra quando a página já conta a história. Na Oficina Costeira o arquivo assets/javascript/infografico.js procura um elemento. Se o elemento não existir, o script não quebra a página.

<script src="assets/javascript/infografico.js" defer></script>

defer espera o HTML terminar de ser lido. Assim o script encontra as tags. Mesmo assim, o conteúdo visível não pode nascer só no JavaScript.

const raiz = document.querySelector("[data-grafico]");
if (!raiz) {
  // A lista HTML abaixo já conta a história.
} else {
  const barras = [
    { nome: "Identidade", valor: 8 },
    { nome: "Publicação", valor: 12 },
    { nome: "Oficina", valor: 5 }
  ];
  raiz.innerHTML = "";
  for (const item of barras) {
    const p = document.createElement("p");
    p.textContent = item.nome + ": " + item.valor + " trabalhos fictícios";
    raiz.append(p);
  }
}

A lista <ul> fica no HTML. O div data-grafico é o enfeite. Sem script, a visitante lê a lista. Com script, ela lê os mesmos números de outro jeito.

Mude só o valor 8 para 9 no HTML da lista, não no script. Preveja: a lista muda, o gráfico extra pode ficar desatualizado. Recarregue. Confira. Depois alinhe o script. Os dois precisam dizer a mesma coisa.

Erro comum: esconder o conteúdo no HTML e só revelar com JavaScript. Se o script falhar, a página parece vazia.

Checar o que o navegador sabe fazer

Nem todo navegador entende o mesmo CSS. Antes de um recurso frágil, pergunte.

@supports (display: flex) and (not (display: grid)) {
  .cards {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
  }
}

A regra acima só vale se houver flex e não houver grid. É um plano B. Não copie dez planos B “por garantia”. Um caminho sólido e um reforço bastam.

No JavaScript, a mesma ideia: só use o que existir.

const aguenta = "querySelector" in document && "addEventListener" in window;
if (aguenta) {
  const script = document.createElement("script");
  script.src = "assets/javascript/infografico.js";
  script.defer = true;
  document.head.append(script);
}

Se o navegador antigo não tiver querySelector, o HTML continua. Este volume não empacota bibliotecas de detecção. @supports e um if curto resolvem o estudo.

Mude a condição para false de propósito (if (false)). Preveja: o gráfico extra some, a lista fica. Recarregue. Confira. Depois devolva a condição verdadeira.

Erro comum: testar só o navegador da sua máquina com todas as extensões desligadas. Bloqueie o JavaScript uma vez nas ferramentas do navegador e recarregue a home.

Falha, fonte grande, teclado e impressão

Faça uma lista mental de “e se”. Não precisa marcar tudo de uma vez. Precisa provar os itens que o seu site usa.

O formulário de contato.html usa action="#" e method="get". O apoio pronto cancela o envio depois da validação. O botão permanece desativado quando esse apoio não carrega; action="#" sozinho não impediria um pedido GET. Validação do navegador (required, type="email") já é uma camada. Script de “sucesso” seria outra, opcional.

Impressão é CSS também:

@media print {
  .menu,
  .skip,
  video {
    display: none;
  }
  a[href]::after {
    content: none;
  }
}

Mude só o h1 da home para um título longo. Dê zoom até 200%. Preveja se o menu ainda quebra linha. Recarregue. Confira. Estreite a janela. O conteúdo não pode sumir atrás do cabeçalho.

Erro comum: achar que “todo mundo tem JavaScript”. Extensão, falha de rede e erro no seu próprio arquivo desligam o script.

Resumo dos conceitos: JS, CSS, HTML

Disco, 127.0.0.1 e publicação

Abrir o arquivo pelo Explorador usa file://. Serve para ler. Alguns testes (fonte, teclado, CSS desligado) já funcionam assim.

Servir a pasta curso só nesta máquina:

python -m http.server 8769 --bind 127.0.0.1 --directory curso

Visite http://127.0.0.1:8769/exemplos/40-melhoria-progressiva/. Encerre com Ctrl+C. Isso não é publicação. Não use 0.0.0.0.

Publicação pública é colocar os arquivos num servidor que qualquer pessoa na Internet alcança. Não publique este exercício. Os nomes da equipe são personagens. O formulário não deve pedir dado real.

A melhoria progressiva não termina neste capítulo. Ela vira hábito: HTML primeiro, CSS depois, JavaScript por último, e sempre um jeito de conferir com a camada de cima desligada.

Atividades

  1. Se o arquivo main.css não carregar, a home da Oficina Costeira ainda informa o que o coletivo faz? Onde?
  2. Para que serve @supports (display: grid) neste volume?
  3. O script do infográfico pode ser a única fonte dos números 8, 12 e 5? Por quê?
  4. Qual a diferença entre abrir index.html pelo disco e visitá-lo em 127.0.0.1?
  5. O formulário de contato deve enviar a mensagem para um servidor do capítulo? Por quê?

Respostas comentadas

  1. Sim. O h1, o parágrafo e os cartões estão no HTML. Sem CSS eles aparecem com o visual padrão do navegador.
  2. Só aplica a grade se o navegador entender grid. Caso contrário os cartões empilham e o conteúdo continua.
  3. Não. A lista HTML já mostra os números. O script só repete. Se ele for a única fonte, a página some quando o JS falha.
  4. Disco é file://, arquivo local. 127.0.0.1 é um servidor de teste nesta máquina. Nenhum dos dois é site público.
  5. Não. O formulário só demonstra marcação e validação. Nada é enviado. Não use dado pessoal.

Referências

O arquivo completo

Referência do exemplo 40-melhoria-progressiva, reproduzida aqui para que você possa conferir sem sair da página.

assets/javascript/simulacao.js

const form=document.querySelector("#simulacao");if(form){form.querySelector("button[type=submit]").disabled=false;form.addEventListener("submit",event=>{event.preventDefault();document.querySelector("#retorno").textContent="Simulação concluída. Nada foi enviado ou guardado.";});}