5 Estilos e Imagens
Nos capítulos anteriores, criamos a estrutura do site da TED System: as páginas com HTML semântico, os componentes de cabeçalho e rodapé, o layout base e o arquivo de dados da empresa. O resultado é funcional, mas ainda não tem estilo visual: as páginas aparecem apenas com a formatação padrão do navegador.
Neste capítulo, vamos aplicar o design do site usando CSS. Você vai aprender a criar um arquivo de estilos globais com variáveis CSS, a estilizar cada componente com estilos isolados (com escopo) e a destacar no menu a página que o visitante está acessando. Também vamos incluir as imagens do projeto e criar um componente de cartão para organizar o conteúdo das páginas.
5.1 Nivelamento de CSS
Antes de aplicarmos os estilos, é importante revisar alguns conceitos que usaremos no projeto:
Seletores e Variáveis Usaremos seletores CSS fundamentais para estruturar o layout. O seletor universal (*) permite aplicar regras a todos os elementos, como a remoção de margens padrão. Os seletores de classe (como .nome-da-classe) serão essenciais para estilizar componentes específicos de forma modular. Além disso, utilizaremos variáveis CSS (custom properties) para armazenar valores reutilizáveis. Definidas com dois traços (como --cor-primaria), elas garantem que, se precisarmos mudar a cor principal do site, a alteração em um único lugar refletirá globalmente. Saiba mais sobre Seletores CSS no MDN.
Unidades No dimensionamento de textos e espaçamentos, utilizaremos a unidade rem, que é relativa ao tamanho da fonte raiz do documento, garantindo maior acessibilidade ao respeitar as preferências do navegador. Para alturas baseadas na tela, utilizaremos vh, onde 1vh equivale a 1% da altura da janela de visualização (viewport). Mais detalhes em Valores e unidades CSS no MDN.
Flexbox O Flexbox nos ajudará a alinhar e distribuir elementos em uma dimensão. Com a propriedade display: flex, transformamos um elemento em um contêiner flexível. A propriedade flex-direction define a direção dos itens (linha ou coluna), e a propriedade flex-wrap: wrap permite a quebra de linha automática quando não há espaço horizontal suficiente. Confira mais sobre Flexbox no MDN. A estrutura CSS equivalente utiliza display: flex;, flex-direction: row; e flex-wrap: wrap;.
CSS Grid O CSS Grid será utilizado para alinhar elementos em duas dimensões (linhas e colunas). Com display: grid, habilitamos o sistema de grade em um contêiner. Usando a propriedade grid-template-columns, definimos como as colunas serão distribuídas. Aproveitaremos a unidade fracionária fr, que representa uma fração do espaço disponível no grid, para distribuir o espaço proporcionalmente sem necessidade de porcentagens precisas. Detalhes em CSS Grid Layout no MDN. A estrutura CSS equivalente utiliza display: grid; e grid-template-columns: 1fr 1fr; (duas colunas com larguras iguais).
5.2 Estilos Globais
O primeiro passo é criar um arquivo CSS centralizado com as cores, os degradês e os estilos que valem para o site inteiro. No Astro, esse arquivo fica em src/styles/ e é importado no layout base.
- No Explorador de Arquivos, passe o mouse sobre a pasta
src/e clique no ícone de Nova Pasta (New Folder). - Escreva o nome
stylese pressioneEnter. - Passe o mouse sobre a nova pasta
src/styles/e clique no ícone de Novo Arquivo (New File). - Escreva
global.css, pressioneEntere adicione o seguinte código:
src/styles/global.css
/* src/styles/global.css */
:root {
/* Paleta de Cores baseada no Logo */
--cor-primaria: #0d1520; /* Quase preto */
--cor-secundaria: #0058ec; /* Azul escuro do degradê (links e botões) */
--cor-destaque: #008ff7; /* Azul claro do degradê (decorativo) */
--cor-fundo: #ffffff;
--cor-fundo-alt: #f8fafc;
--cor-texto: #334155;
--cor-texto-secundario: #64748b;
--cor-texto-invertido: #ffffff;
--cor-texto-invertido-suave: #cbd5e1;
--cor-borda: #e2e8f0;
/* Variável para o Hero */
--cor-hero-fim: #00224d;
/* Degradês Globais */
--degrade-marca: linear-gradient(
90deg,
var(--cor-secundaria),
var(--cor-destaque)
);
--degrade-hero: linear-gradient(
135deg,
var(--cor-primaria),
var(--cor-hero-fim)
);
/* Variáveis Estruturais */
--borda-raio: 8px;
--sombra-cartao: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
--sombra-cartao-hover: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
--espacamento-secao: 4rem;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Oxygen, Ubuntu, Cantarell, sans-serif;
background-color: var(--cor-fundo);
color: var(--cor-texto);
line-height: 1.6;
display: flex;
flex-direction: column;
min-height: 100vh;
}
main {
flex: 1;
}
h1, h2, h3 {
color: var(--cor-primaria);
line-height: 1.2;
margin-bottom: 1rem;
}
p {
margin-bottom: 1rem;
}
a {
color: var(--cor-secundaria);
text-decoration: none;
transition: color 0.2s ease;
}
a:hover {
text-decoration: underline;
}
.container {
width: 100%;
max-width: 960px;
margin: 0 auto;
padding: 0 1.5rem;
}
.secao {
padding: var(--espacamento-secao) 0;
}
.secao-alt {
background-color: var(--cor-fundo-alt);
}
.btn {
display: inline-block;
background-color: var(--cor-secundaria);
color: var(--cor-texto-invertido);
padding: 0.75rem 1.5rem;
border-radius: var(--borda-raio);
font-weight: 600;
text-align: center;
transition: background-color 0.2s ease;
}
.btn:hover {
background-color: var(--cor-primaria);
text-decoration: none;
}Esse arquivo é extenso, mas cada parte tem uma função clara. Vamos entender por partes.
Variáveis CSS em :root — O bloco :root define variáveis CSS (também chamadas de custom properties) que ficam disponíveis em qualquer lugar do site. O nome de cada variável começa com -- e descreve a sua função: --cor-primaria é a cor principal (quase preta), --cor-secundaria é o azul dos links e botões, --cor-destaque é o azul claro usado apenas nos degradês decorativos. As variáveis de texto invertido (--cor-texto-invertido e --cor-texto-invertido-suave) são usadas em áreas com fundo escuro, como o cabeçalho hero e o rodapé. Para usar uma variável, escrevemos var(--nome-da-variavel). A vantagem é que, se você quiser trocar uma cor, basta alterar o valor aqui e a mudança se reflete em todo o site. Para saber mais sobre variáveis CSS, consulte a documentação do MDN: Using CSS custom properties.
Variáveis CSS facilitam a manutenção As variáveis declaradas no bloco :root ficam acessíveis em qualquer componente. Se for necessário mudar a paleta de cores no futuro, basta alterar o valor no global.css para que o site inteiro seja atualizado.
Reset e estilos base — O seletor * (que seleciona todos os elementos) aplica box-sizing: border-box e zera as margens e os espaçamentos padrão do navegador, criando uma base uniforme. O body define a fonte do sistema, a cor do texto e do fundo, o espaçamento entre linhas (line-height: 1.6) e usa Flexbox na direção vertical (flex-direction: column) com min-height: 100vh para que o rodapé fique sempre no final da página, mesmo quando o conteúdo é curto. O main recebe flex: 1 para ocupar todo o espaço disponível entre o cabeçalho e o rodapé.
Por que zerar as margens? Cada navegador (Chrome, Firefox, Safari) possui margens e espaçamentos padrão ligeiramente diferentes. A regra * { margin: 0; padding: 0; } limpa essas diferenças e garante que o layout se comporte de maneira idêntica em todos eles.
Tipografia e links — Os títulos h1, h2 e h3 recebem a cor primária e um espaçamento abaixo. Os links ficam com a cor secundária (azul), sem sublinhado, e ganham sublinhado ao passar o mouse.
Classes utilitárias — A classe .container centraliza o conteúdo com largura máxima de 960 pixels e espaçamento lateral. A classe .secao adiciona o espaçamento vertical entre as seções, e .secao-alt aplica um fundo alternativo mais claro. A classe .btn cria o estilo do botão com fundo azul, texto branco, cantos arredondados e uma transição suave ao passar o mouse.
5.2.1 Importando o CSS no Layout
Para que os estilos globais se apliquem a todas as páginas, precisamos importar o arquivo no layout. Abra o arquivo src/layouts/LayoutBase.astro e adicione a linha de importação no frontmatter:
src/layouts/LayoutBase.astro
---
import '../styles/global.css';
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
import { empresa } from '../data/empresa.js';
const { titulo, descricao } = Astro.props;
---
<html lang="pt-BR">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content={descricao} />
<title>{titulo} | {empresa.nome}</title>
</head>
<body>
<Header />
<main>
<slot />
</main>
<Footer />
</body>
</html>A primeira linha do frontmatter (import '../styles/global.css') carrega o arquivo CSS global. O Astro inclui automaticamente os estilos no HTML de todas as páginas que usam esse layout. Essa é a forma recomendada de aplicar estilos que valem para o site inteiro. Para saber mais sobre estilos no Astro, consulte a documentação oficial: Styles & CSS.
5.3 Imagens do Projeto
O site da TED System usa quatro imagens: o logotipo da empresa e as fotos dos três membros da equipe. Essas imagens ficam na pasta public/images/, de onde o Astro as serve diretamente na raiz do site.
Baixe o arquivo ted-system-imagens.zip e extraia, no seu computador, as quatro imagens: logo.png, wanderson.jpg, sheldon.jpg e amy.jpg.
No Explorador de Arquivos do Codespaces, passe o mouse sobre a pasta public/ e clique no ícone de Nova Pasta (New Folder). Escreva images e pressione Enter. Depois, arraste as quatro imagens extraídas para dentro da pasta public/images/.
5.3.1 Referenciando Imagens Públicas
Arquivos na pasta public/ são servidos na raiz do site. Para referenciá-los no código, o caminho sempre começa com uma barra / e nunca inclui a palavra “public”. Por exemplo:
- Correto:
/images/logo.png - Incorreto:
public/images/logo.png
5.4 Componente Cartão
Antes de estilizar as páginas, vamos criar o componente Cartao.astro. Ele será usado em todas as páginas: no público-alvo da página inicial, na missão, na visão e nos valores da página Sobre, nos membros da equipe e nos canais de contato.
No Explorador de Arquivos, passe o mouse sobre a pasta src/components/ e clique no ícone de Novo Arquivo (New File). Escreva Cartao.astro, pressione Enter e adicione o seguinte código:
src/components/Cartao.astro
---
const { destaque } = Astro.props;
---
<div class:list={['cartao', { 'cartao-destaque': destaque }]}>
<slot />
</div>
<style>
.cartao {
background-color: var(--cor-fundo);
border: 1px solid var(--cor-borda);
border-radius: var(--borda-raio);
padding: 2rem;
box-shadow: var(--sombra-cartao);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.cartao:hover {
transform: translateY(-4px);
box-shadow: var(--sombra-cartao-hover);
}
.cartao-destaque {
border-top: 4px solid var(--cor-secundaria);
}
</style>O componente recebe uma prop opcional chamada destaque. Quando destaque é verdadeiro, o cartão ganha uma faixa azul no topo (a classe cartao-destaque).
A diretiva class:list do Astro recebe um array e monta a lista de classes CSS dinamicamente. A classe cartao é aplicada sempre; a classe cartao-destaque é adicionada apenas quando a condição destaque é verdadeira. Essa é a forma recomendada pelo Astro para aplicar classes condicionais: class:list.
O bloco <style> dentro do componente cria estilos com escopo (scoped styles). Isso significa que as regras CSS definidas aqui valem apenas para o HTML deste componente, sem afetar o restante do site. Mesmo que outra parte do site use uma classe com o mesmo nome, os estilos não entram em conflito. Repare que os estilos com escopo podem usar as variáveis definidas no global.css (como var(--cor-fundo) e var(--sombra-cartao)), porque as variáveis CSS são globais por natureza.
A tag <slot /> funciona como um espaço reservado: o conteúdo que for passado entre as tags <Cartao> e </Cartao> aparece no lugar do slot. Já aprendemos sobre props e slots no capítulo anterior, quando criamos o LayoutBase.
5.6 Estilos do Rodapé
Abra o arquivo src/components/Footer.astro e substitua o conteúdo inteiro pelo código abaixo:
src/components/Footer.astro
---
import { empresa } from '../data/empresa.js';
const anoAtual = new Date().getFullYear();
---
<footer class="rodape">
<div class="faixa-topo"></div>
<div class="container rodape-container">
<div class="rodape-marca">
<h2>{empresa.nome}</h2>
<p>© {anoAtual} {empresa.nome}. Todos os direitos reservados.</p>
</div>
<div class="rodape-contato">
<p>{empresa.contato.endereco.logradouro}</p>
<p>{empresa.contato.endereco.complemento} - {empresa.contato.endereco.bairro}</p>
<p>{empresa.contato.endereco.cidadeEstado} - CEP: {empresa.contato.endereco.cep}</p>
<div class="links-contato">
<a href={`mailto:${empresa.contato.email}`}>{empresa.contato.email}</a>
<p>{empresa.contato.telefone}</p>
</div>
</div>
</div>
</footer>
<style>
.rodape {
background-color: var(--cor-primaria);
color: var(--cor-texto-invertido);
margin-top: auto;
}
.faixa-topo {
height: 4px;
background: var(--degrade-marca);
}
.rodape-container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: 2rem;
padding: 3rem 1.5rem;
}
.rodape-marca h2 {
color: var(--cor-texto-invertido);
margin-bottom: 0.5rem;
}
.rodape-marca p, .rodape-contato p {
color: var(--cor-texto-invertido-suave);
font-size: 0.875rem;
margin-bottom: 0.25rem;
}
.links-contato {
display: flex;
flex-direction: column;
gap: 0.5rem;
margin-top: 1rem;
}
.links-contato a {
color: var(--cor-texto-invertido);
text-decoration: none;
}
.links-contato a:hover {
color: var(--cor-texto-invertido-suave);
text-decoration: underline;
}
</style>O rodapé tem fundo escuro (--cor-primaria) e usa as variáveis de texto invertido para garantir a legibilidade. O Flexbox com flex-wrap: wrap organiza a marca à esquerda e o contato à direita, e adapta o layout automaticamente em telas menores. A faixa colorida no topo segue o mesmo padrão do cabeçalho.
5.7 Páginas Estilizadas
Agora vamos atualizar cada página para usar as classes CSS, o componente Cartao e os estilos com escopo.
5.7.1 Página Inicial
Abra o arquivo src/pages/index.astro e substitua o conteúdo inteiro pelo código abaixo:
src/pages/index.astro
---
import LayoutBase from '../layouts/LayoutBase.astro';
import Cartao from '../components/Cartao.astro';
import { empresa } from '../data/empresa.js';
---
<LayoutBase
titulo="Início"
descricao={`Bem-vindo à ${empresa.nome}. ${empresa.slogan}`}
>
<section class="hero">
<div class="container">
<h1>{empresa.slogan}</h1>
<p class="hero-descricao">{empresa.missao}</p>
<a href="/contato" class="btn">Fale Conosco</a>
</div>
</section>
<section class="publico secao secao-alt">
<div class="container">
<h2>Quem Atendemos</h2>
<Cartao>
<p class="texto-publico">{empresa.publicoAlvo}</p>
</Cartao>
</div>
</section>
</LayoutBase>
<style>
.hero {
background: var(--degrade-hero);
color: var(--cor-texto-invertido);
padding: 6rem 0;
}
.hero h1 {
color: var(--cor-texto-invertido);
font-size: 3rem;
margin-bottom: 1.5rem;
line-height: 1.1;
max-width: 800px;
}
.hero-descricao {
font-size: 1.25rem;
max-width: 700px;
margin-bottom: 2rem;
color: var(--cor-texto-invertido-suave);
}
.publico h2 {
margin-bottom: 2rem;
}
.texto-publico {
margin-bottom: 0;
font-size: 1.125rem;
color: var(--cor-texto-secundario);
}
</style>A página inicial tem duas seções. A primeira é o hero: uma área de destaque com o degradê escuro (--degrade-hero), o slogan da empresa como título, a missão como texto de apoio e um botão que leva à página de contato. A segunda seção mostra o público-alvo dentro de um Cartao, com fundo alternativo (.secao-alt).
Note que a página importa o componente Cartao no frontmatter e o usa como uma tag HTML. O texto do público-alvo é passado entre <Cartao> e </Cartao>, e aparece no lugar do <slot /> do componente.
5.7.2 Página Sobre
Abra o arquivo src/pages/sobre.astro e substitua o conteúdo inteiro pelo código abaixo:
src/pages/sobre.astro
---
import LayoutBase from '../layouts/LayoutBase.astro';
import Cartao from '../components/Cartao.astro';
import { empresa } from '../data/empresa.js';
---
<LayoutBase
titulo="Sobre Nós"
descricao={`Conheça a história e os valores da ${empresa.nome}.`}
>
<section class="secao">
<div class="container">
<div class="bloco-texto">
<h1>Sobre a {empresa.nome}</h1>
<p class="historia">{empresa.historia}</p>
</div>
<div class="grid-missao-visao">
<Cartao>
<h2>Missão</h2>
<p>{empresa.missao}</p>
</Cartao>
<Cartao>
<h2>Visão</h2>
<p>{empresa.visao}</p>
</Cartao>
</div>
</div>
</section>
<section class="secao secao-alt">
<div class="container">
<h2 class="titulo-valores">Nossos Valores</h2>
<div class="grid-valores">
{empresa.valores.map((valor) => (
<Cartao destaque={true}>
<h3>{valor.titulo}</h3>
<p>{valor.descricao}</p>
</Cartao>
))}
</div>
</div>
</section>
</LayoutBase>
<style>
.bloco-texto {
margin-bottom: 3rem;
max-width: 800px;
}
.historia {
font-size: 1.125rem;
color: var(--cor-texto-secundario);
}
.grid-missao-visao {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
.grid-missao-visao h2 {
font-size: 1.5rem;
color: var(--cor-secundaria);
}
.titulo-valores {
margin-bottom: 2rem;
}
.grid-valores {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 2rem;
}
.grid-valores h3 {
font-size: 1.25rem;
color: var(--cor-secundaria);
margin-bottom: 0.5rem;
}
</style>A página Sobre usa CSS Grid para organizar os cartões de missão e visão lado a lado, e os cartões de valores em uma grade responsiva. A regra grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) cria colunas que se ajustam automaticamente ao tamanho da tela: cada coluna tem no mínimo 300 pixels (na grade dos valores, 280 pixels), e o Grid distribui o espaço restante igualmente. Em telas menores, os cartões ficam empilhados automaticamente, sem necessidade de uma media query.
Os cartões de valores recebem destaque={true}, o que ativa a classe cartao-destaque e adiciona a faixa azul no topo. Para saber mais sobre CSS Grid, consulte a documentação do MDN: CSS Grid Layout.
Flexbox ou Grid? A regra de ouro é: use Flexbox para alinhar elementos em uma única direção (como nosso cabeçalho) e Grid quando precisar controlar o layout em duas direções simultaneamente, com linhas e colunas estruturadas.
5.7.3 Página Equipe
Abra o arquivo src/pages/equipe.astro e substitua o conteúdo inteiro pelo código abaixo:
src/pages/equipe.astro
---
import LayoutBase from '../layouts/LayoutBase.astro';
import Cartao from '../components/Cartao.astro';
import { empresa } from '../data/empresa.js';
---
<LayoutBase
titulo="Nossa Equipe"
descricao={`Conheça os profissionais por trás da ${empresa.nome}.`}
>
<section class="secao">
<div class="container">
<div class="cabecalho-secao">
<h1>Nossa Equipe Técnica</h1>
<p>Conheça os profissionais que transformam requisitos de negócio em soluções de software seguras e escaláveis</p>
</div>
<div class="grid-equipe">
{empresa.equipe.map((membro) => (
<Cartao>
<div class="card-membro-conteudo">
<img
src={membro.foto}
alt={membro.alt}
class="foto-perfil"
width="140"
height="140"
/>
<div class="info-membro">
<h3>{membro.nome}</h3>
<span class="cargo">{membro.cargo}</span>
<p class="descricao-membro">{membro.descricao}</p>
</div>
</div>
</Cartao>
))}
</div>
</div>
</section>
</LayoutBase>
<style>
.cabecalho-secao {
margin-bottom: 3rem;
}
.cabecalho-secao p {
font-size: 1.125rem;
color: var(--cor-texto-secundario);
max-width: 600px;
}
.grid-equipe {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 2rem;
}
.card-membro-conteudo {
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
}
.foto-perfil {
width: 140px;
height: 140px;
border-radius: 50%;
object-fit: cover;
margin-bottom: 1.25rem;
border: 4px solid var(--cor-borda);
}
.info-membro h3 {
font-size: 1.25rem;
margin-bottom: 0.25rem;
}
.cargo {
display: inline-block;
color: var(--cor-secundaria);
font-size: 0.875rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 1rem;
}
.descricao-membro {
font-size: 0.95rem;
color: var(--cor-texto-secundario);
margin-bottom: 0;
}
</style>A página da equipe mostra cada membro dentro de um cartão com a foto circular, o nome, o cargo e uma descrição. A foto usa border-radius: 50% para ficar redonda e object-fit: cover para manter as proporções sem distorcer — quando a imagem original não é quadrada, o object-fit: cover recorta o excesso e preenche o espaço circular. Os atributos width e height na tag <img> informam ao navegador o tamanho em que a foto será exibida (140 por 140 pixels), o que ajuda a reservar o espaço antes de carregá-la e evita que o layout “pule” durante o carregamento. Para saber mais, consulte o MDN: object-fit.
5.7.4 Página Contato
Abra o arquivo src/pages/contato.astro e substitua o conteúdo inteiro pelo código abaixo:
src/pages/contato.astro
---
import LayoutBase from '../layouts/LayoutBase.astro';
import Cartao from '../components/Cartao.astro';
import { empresa } from '../data/empresa.js';
---
<LayoutBase
titulo="Fale Conosco"
descricao={`Entre em contato com a ${empresa.nome}.`}
>
<section class="secao">
<div class="container">
<div class="cabecalho-secao">
<h1>Fale Conosco</h1>
<p>Deseja construir uma solução de software sob medida para o seu negócio? Entre em contato com a {empresa.nome}!</p>
</div>
<div class="grid-contato">
<Cartao>
<h2>Nossa Sede</h2>
<address>
{empresa.contato.endereco.logradouro}, {empresa.contato.endereco.complemento}<br/>
{empresa.contato.endereco.bairro}<br/>
{empresa.contato.endereco.cidadeEstado}<br/>
CEP: {empresa.contato.endereco.cep}
</address>
</Cartao>
<Cartao>
<h2>Canais Digitais</h2>
<p><strong>E-mail:</strong> <a href={`mailto:${empresa.contato.email}`}>{empresa.contato.email}</a></p>
<p><strong>Telefone:</strong> {empresa.contato.telefone}</p>
</Cartao>
</div>
</div>
</section>
</LayoutBase>
<style>
.cabecalho-secao {
margin-bottom: 3rem;
}
.cabecalho-secao p {
font-size: 1.125rem;
color: var(--cor-texto-secundario);
}
.grid-contato {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
.grid-contato h2 {
font-size: 1.5rem;
margin-bottom: 1rem;
color: var(--cor-secundaria);
}
address {
font-style: normal;
}
.grid-contato p {
margin-bottom: 0.5rem;
}
.grid-contato p:last-child {
margin-bottom: 0;
}
</style>A página de contato organiza o endereço e os canais digitais em dois cartões lado a lado com CSS Grid. O endereço usa a tag semântica <address>, e o e-mail é um link mailto: que abre o aplicativo de e-mail do visitante. Para saber mais, consulte o MDN: <address>.
5.8 Verificando o Resultado
Se o servidor de desenvolvimento não estiver em execução, inicie-o no terminal:
npm run devAbra a aba Portas (Ports), passe o mouse sobre o endereço na coluna Endereço Encaminhado (Forwarded Address) e clique no ícone do globo, Abrir no Navegador (Open in Browser). Navegue pelas quatro páginas e confira: o cabeçalho mostra o logotipo e destaca em azul o link da página atual; a página inicial tem o hero com o degradê escuro e o botão “Fale Conosco”; as fotos da equipe aparecem redondas; e o rodapé tem fundo escuro, com a faixa colorida no topo.
Para encerrar o servidor, volte ao terminal e pressione Ctrl + C. Por fim, execute o processo de construção para garantir que o código não possui erros que impeçam a geração do site estático:
npm run buildNa saída final, observe a mensagem indicando a criação das quatro páginas (4 page(s) built in ...).
5.9 Registrando o Progresso no Git
Registre suas melhorias no Git executando a sequência de comandos abaixo no terminal.
5.9.1 Verificando os arquivos modificados com git status
git statusO Git mostrará as novas pastas src/styles e public/images, o novo componente Cartao.astro e os arquivos alterados do layout, dos componentes e das páginas.
5.9.2 Adicionando as mudanças com git add
git add .5.9.3 Criando o commit descritivo com git commit
git commit -m "feat: adiciona estilos, imagens e componente de cartão"5.9.4 Sincronizando com o repositório remoto com git push
git push5.10 Resumo e Próximos Passos
Neste capítulo, você aprendeu:
- Como criar um arquivo de estilos globais (
src/styles/global.css) com variáveis CSS, importado no layout; - A usar estilos com escopo (
<style>dentro de cada componente), que não afetam o restante do site; - A organizar elementos na tela com Flexbox (cabeçalho e rodapé) e CSS Grid (cartões e grades);
- A destacar no menu a página atual usando
Astro.url.pathname, o métodostartsWithe a diretivaclass:list; - A usar a propriedade
object-fit: coverpara manter as proporções das fotos; - A incluir imagens estáticas na pasta
public/e referenciá-las no código; - A usar o componente
Cartaocom props e<slot />para exibir conteúdo de forma reutilizável.
No próximo capítulo, vamos publicar o site na internet usando a Cloudflare Pages.