Pular para o conteúdo
murad.guide

Introdução Completa à Web

Capítulo 13

Projeto: checkout do café

5 min de leitura 869 palavras 2 gravuras

A Casa da Restinga precisa de uma tela de pedido: itens à esquerda, nome e pagamento à direita, total embaixo. Você escreve o HTML e o CSS. Nada é cobrado. Nada sai do computador.

O exemplo está em exemplos/13-checkout/. Natal, cafeteria fictícia. Este volume tem 23 capítulos.

Não digite nome real, nem número de cartão verdadeiro. Use Iara Costa e 0000 0000 0000 0000.

Trabalhe na cópia inicio da etapa. Leia e digite o código; mude uma coisa. Antes de recarregar, anote sua previsão. Depois confira com a referência completa. Se nada mudar, confira o arquivo salvo e o caminho aberto. Blocos adicionais do capítulo podem ser digitados no console; o exemplo completo mostra a aplicação daquela etapa.

O que você vai aprender

O que vamos montar

Três faixas: pedido, dados, total. A marca no topo é Casa da Restinga, não outra cafeteria.

Itens fictícios:

Subtotal R$ 27,00. “Taxa” de demonstração R$ 1,35. Total R$ 28,35. Os números são texto. Não há caixa registradora.

Há muitos jeitos certos. Grid + Flex cabem. Não force a página inteira num Grid de vinte células.

Mude uma coisa. Troque o cappuccino por Café gelado da duna no HTML. Preveja só o nome mudar. Recarregue e confira.

Erro comum: copiar preços em dólar e o nome de outra marca. Este pedido é da Restinga, em real.

HTML do pedido

<!DOCTYPE html>
<html lang="pt-BR">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Checkout — Casa da Restinga</title>
    <link rel="stylesheet" href="estilos.css">
  </head>
  <body>
    <header>
      <p class="marca">Casa da Restinga</p>
    </header>
    <main class="pagina">
      <section class="pedido" aria-labelledby="tit-pedido">
        <h1 id="tit-pedido">Itens</h1>
        <ul class="itens">
          <li class="item">
            <span>1×</span>
            <span>Café coado da Restinga</span>
            <span>R$ 8,00</span>
          </li>
        </ul>
      </section>
    </main>
  </body>
</html>

Complete os três itens no exemplo. Lista: ul / li. Preço visível no texto, não só na cor.

Mude uma coisa. Troque o h1 para Seu pedido na Restinga. Preveja o título da seção mudar, a aba continuar Checkout — Casa da Restinga. Recarregue e confira.

Erro comum: div no lugar de section sem título. A região some para o leitor de tela.

Formulário que não envia

Cada campo tem label com for igual ao id. O botão é type="button": clicar não navega, não abre e-mail, não chama PHP.

<section class="dados" aria-labelledby="tit-dados">
  <h2 id="tit-dados">Nome e pagamento</h2>
  <form>
    <p class="campo">
      <label for="nome">Nome no pedido</label>
      <input id="nome" name="nome" type="text" autocomplete="off">
    </p>
    <p class="campo">
      <label for="cartao">Número fictício do cartão</label>
      <input id="cartao" name="cartao" type="text" inputmode="numeric" autocomplete="off">
    </p>
    <p class="campo">
      <label for="cvv">CVV fictício</label>
      <input id="cvv" name="cvv" type="text" inputmode="numeric" autocomplete="off">
    </p>
    <button type="button">Confirmar pedido fictício</button>
  </form>
</section>

Clique no texto “Nome no pedido”: o cursor vai ao campo. Isso só funciona se for e id forem iguais, inclusive minúsculas.

O rótulo pode sentar na borda do campo com position: relative no grupo e position: absolute no label. O for continua obrigatório. placeholder não substitui o nome.

Mude uma coisa. Troque type="button" por type="submit". Clique. Preveja a página recarregar com lixo na URL. Recarregue. Volte para button.

Erro comum: action apontando para um site ou para mailto:. O exercício deixa de ser local.

Pedido, formulário com rótulos e total da Casa da Restinga

Grid na página, linha do item

.pagina {
  display: grid;
  gap: 1.5rem;
  padding: 1.5rem;
  grid-template-areas:
    "pedido dados"
    "total  total";
  grid-template-columns: 1fr 1fr;
}

.pedido { grid-area: pedido; }
.dados { grid-area: dados; }
.total { grid-area: total; }

.item {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
}

.marca {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 0;
  padding: 0.75rem;
  background: #0d5c63;
  color: #f4efe6;
}

@media (max-width: 40rem) {
  .pagina {
    grid-template-areas:
      "pedido"
      "dados"
      "total";
    grid-template-columns: 1fr;
  }
}

Cabeçalho em Flex (componente). Página em Grid. Item em Flex.

Mude uma coisa. Encolha a janela abaixo de 40rem. Preveja uma coluna: pedido, dados, total. Recarregue se precisar e confira.

Erro comum: grid-template-columns: 1fr 1fr sem media query. No telefone as duas colunas esmagam os campos.

border-radius e box-shadow

Ainda não tínhamos falado disso. border-radius arredonda. box-shadow desenha uma sombra.

.caixa {
  background: #eee1d5;
  border-radius: 8px;
  box-shadow: 0 1px 3px rgb(0 0 0 / 0.2);
  padding: 1rem;
}

input {
  border: 1px solid #0d5c63;
  border-radius: 4px;
  padding: 0.5rem;
}

input:focus-visible,
button:focus-visible {
  outline: 3px solid #0d5c63;
  outline-offset: 2px;
}

Quatro valores em border-radius arredondam cada canto. Um valor só arredonda todos. A sombra é deslocamento-x deslocamento-y desfoque cor.

Não precisa copiar o desenho ao milímetro. Chegue perto da cara da casa.

Mude uma coisa. Suba border-radius da caixa para 24px. Preveja um cartão bem redondo. Recarregue e confira.

Erro comum: box-shadow tão escura que parece um segundo fundo. Sombra é dica de elevação, não um muro.

Fonte local e conferência

Prefira fonte do sistema. Google Fonts é opcional e pede rede.

body {
  margin: 0;
  font-family: system-ui, "Segoe UI", sans-serif;
  background: #efefef;
}

system-ui usa a fonte da máquina. Sem link para fonts.google.com.

Confira: Tab em todos os campos; rótulo clicável; botão não envia; zoom 200%; tela estreita em uma coluna. Servidor só em 127.0.0.1. Publicação não é pedida.

Mude uma coisa. Não acrescente Google Fonts. Preveja o texto na fonte do sistema. Recarregue e confira.

Erro comum: font-family só com uma fonte da web, sem genérica. Sem internet, o checkout cai no Times padrão sem plano B.

Início da referência desta etapa no navegador local

Atividades

  1. Por que o botão é type="button" e não type="submit"?
  2. O que acontece se for="nome" e id="Nome" não baterem?
  3. Grid ou Flex: a página inteira do checkout? A linha “1× Café coado”?
  4. border-radius e box-shadow mudam o HTML ou só o CSS?

Respostas comentadas

  1. submit envia o formulário (recarrega ou vai para um action). button só existe na tela. Nada é transmitido.
  2. Clicar no rótulo não foca o campo. Maiúscula conta. Leitor de tela também perde a ligação.
  3. Página: Grid (pedido, dados, total). Linha do item: Flex (quantidade, nome, preço).
  4. Só o CSS. O HTML dos itens e dos campos permanece o mesmo.

Referências

O arquivo completo

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

checkout.js

document.querySelector("form").addEventListener("submit", (evento) => {
  evento.preventDefault();
  document.getElementById("ok").textContent = "Pedido simulado. Nada foi enviado.";
});