Curso de CSS / Bordas, cantos arredondados e sombras

As bordas em CSS definem a borda visível de uma caixa, border-radius arredonda seus cantos, e box-shadow adiciona uma sombra sem aumentar o tamanho do layout. Sombras ainda podem ser cortadas pelas configurações de overflow de um ancestral, e uma borda arredondada não recorta automaticamente todos os filhos.

Defina a largura, estilo e cor da borda

.card { border: 2px solid #3d6b89; }

A abreviação border combina largura, estilo e cor. solid desenha uma linha contínua, dashed desenha traços e dotted desenha pontos. Um estilo none suprime a borda esperada mesmo que uma largura e cor estejam presentes. Use border-bottom ou border-block-end quando apenas uma borda de um lado for necessária. Para mais detalhes, veja O Modelo de Caixa CSS: Conteúdo, Padding, Borda e Margem.

Propriedade Efeito no tamanho da caixa Principais usos
border Em content-box, é adicionada externamente, e em border-box, está incluída dentro do tamanho especificado. borda do elemento
outline Não aumenta o espaço do layout Mostra contornos ao redor dos elementos focados
box-shadow Não aumenta o espaço do layout Sombras e Profundidade Visual

Com uma largura fixa de border-box, aumentar a espessura da borda reduz o espaço interno enquanto mantém a largura externa. Uma borda ou sombra decorativa tem um papel diferente do contorno de foco que identifica o alvo atual do teclado. Mantenha esse indicador visível. Veja MDN: border.

Compare comprimentos e percentagens dos cantos

.round { border-radius: 12px; }

.circle { width: 80px; height: 80px; border-radius: 50%; }

.oval { width: 160px; height: 80px; border-radius: 50%; }

Um valor de comprimento como 12px especifica o raio do canto. Você pode dar valores diferentes para os quatro cantos, mas compare-os primeiro com um valor. Se você aplicar 50% a uma caixa com a mesma largura e altura, ela parecerá um círculo, e se os tamanhos horizontal e vertical forem diferentes, ela parecerá uma elipse. O raio horizontal da porcentagem é baseado na largura, e o raio vertical é baseado na altura.

Os cantos arredondados do elemento pai não recortam automaticamente a imagem filha. Escolha entre aplicar o border-radius na própria imagem ou cortar o overflow do elemento pai, dependendo do seu objetivo. Se você definir overflow: hidden no pai, a sombra/foco do filho também pode ser cortada na borda. A comparação a seguir distingue qual caixa está sendo cortada. Você pode verificar o cálculo do raio na descrição do border-radius do MDN.

Leia os valores da sombra

.shadow { box-shadow: 0 8px 24px 4px rgb(0 0 0 / 16%); }
valor significado Resultados a alterar
primeiro 0 mover horizontalmente Números positivos movem-se para a direita, números negativos movem-se para a esquerda
segundo 8px movimento vertical Números positivos movem-se para baixo, números negativos movem-se para cima.
terceiro 24px raio de desfoque Perto de 0, a borda fica mais nítida; valores maiores tornam o desfoque mais suave.
quarto 4px raio de dispersão Números positivos aumentam o tamanho da sombra, números negativos diminuem.
rgb(0 0 0 / 16%) Cor e Opacidade O grau em que ele se distingue do fundo varia.

Os dois primeiros comprimentos são obrigatórios e o desfoque e a propagação podem ser omitidos. O raio de desfoque não pode ser negativo. Adicionar inset é a sombra interna, o padrão é a sombra externa. Também existe uma maneira de adicionar múltiplas sombras, mas primeiro verifique alterando o movimento e o tamanho de uma sombra separadamente.

Uma sombra não reserva espaço de layout. Ela não afastará um cartão seguinte pela quantidade de seu desfoque ou propagação. Sombras grandes podem obscurecer conteúdos próximos, então forneça espaçamento real com margens ou lacunas de layout quando necessário. Veja MDN: box shadow.

Encontre o ancestral que recorta uma sombra

.frame { padding: 12px; overflow: visible; }

.frame.clip { overflow: hidden; }

.frame .card { box-shadow: 0 18px 20px 8px rgb(0 0 0 / 25%); }

Os dois últimos cartões têm pais .frame separados. As sombras dos filhos são idênticas, mas um pai permite overflow visível e o outro o corta. A sombra se estende além do padding de 12px do pai, então a versão com overflow oculto a corta na borda do pai. Inspecione esse ancestral ao diagnosticar uma sombra cortada. Veja CSS Overflow, Quebra de Texto Longo e Reticências.

Aplicar overflow: hidden no próprio cartão é diferente de um ancestral recortar a sombra externa desse cartão. Este exercício é uma situação em que um pai corta a sombra externa de um cartão filho. Se a sombra não estiver visível na página real, você deve verificar não apenas o valor do próprio cartão, mas também o overflow e a borda do elemento pai.

Execute o exemplo e compare as alterações

Salve o código abaixo como UTF-8 em borders.html. Comparações de bordas, cantos arredondados, sombras externas, sombras internas, círculos e elipses, e truncamento estão todas incluídas.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Comparing borders, corners, and shadows</title>
  <style>
    * { box-sizing: border-box; }
    body { margin: 24px; color: #333; font: 16px/1.6 sans-serif; background: #f6f8fa; }
    .card { width: 100%; max-width: 320px; margin-block: 24px; padding: 20px; background: white; }
    .border { border: 2px solid #3d6b89; }
    .round { border: 2px solid #3d6b89; border-radius: 12px; }
    .shadow { border-radius: 12px; box-shadow: 0 8px 24px 4px rgb(0 0 0 / 16%); }
    .inset { box-shadow: inset 0 0 12px 2px rgb(0 0 0 / 20%); }
    .shape { width: 80px; height: 80px; margin-block: 16px; border-radius: 50%; background: #6eb898; }
    .oval { width: 160px; }
    .frame { width: 100%; max-width: 320px; padding: 12px; margin-block: 24px; background: #dce8f1; overflow: visible; }
    .frame .card { margin: 0; max-width: none; height: 100px; box-shadow: 0 18px 20px 8px rgb(0 0 0 / 25%); }
    .clip { overflow: hidden; }
  </style>
</head>
<body>
  <h1>Card boundaries and shadows</h1>
  <div class="card border">Card with a border only</div>
  <div class="card round">Border and rounded corners</div>
  <div class="card shadow">Outer shadow</div>
  <div class="card inset">Inset shadow</div>
  <h2>50% Edges: Circles and Ovals</h2><div class="shape" role="img" aria-label="80×80 circle"></div><div class="shape oval" role="img" aria-label="160×80 ellipse"></div>
  <h2>Parent: overflow: visible</h2><div class="frame"><div class="card">Child shadow visible outside the parent</div></div>
  <h2>Parent: overflow: hidden</h2><div class="frame clip"><div class="card">Child shadow clipped at the parent boundary</div></div>
</body>
</html>
  1. Altere a espessura da .border de 2px para 8px. Em janelas largas, certifique-se de que a largura externa seja mantida e o espaço interno seja reduzido, e depois retorne para 2px.
  2. Altere a largura do .shape de 80px para 160px. Certifique-se de que o círculo se transforme em elipse se você mantiver a altura em 80px. Restaure para a largura original.
  3. Altere o deslocamento horizontal da .shadow para 20px e o deslocamento vertical para -8px. Mantenha o desfoque em 24px e compare apenas a direção do movimento. Em seguida, altere o desfoque para 0, compare com a borda nítida e depois retorne ao valor original.
  4. Altere o spread de 4px para -4px. Observe se o tamanho da sombra diminui. No segundo .frame, altere overflow de hidden para visible, confira se a sombra do filho reaparece fora do pai e depois restaure hidden.

Se a sombra estiver borrada, verifique a opacidade da cor e o contraste do fundo, e se apenas um lado estiver cortado, verifique a borda e o transbordamento (overflow) do elemento pai. Se o conteúdo filho dentro do canto se sobressair, também comparamos o método de dar cantos arredondados ao próprio filho. Ao escolher os efeitos decorativos, baseie seu julgamento em manter o conteúdo claro e fácil de manipular.