Pular para o conteúdo
Cursos

DevClub

LógicaFront-endBack-endMobile

IA Club

IA na prática
Estudar programaçãoEstudar IA
LiçãoIniciantecódigo testado

Formatar texto em HTML: negrito, itálico, código e citação

strong, em, mark, small, code, pre e blockquote: o que cada tag significa, como um leitor de tela lê e quando o trabalho é do CSS.

Rodolfo Mori11 min de leitura

Formatar texto em HTML não é escolher aparência: é dizer o que aquele trecho significa. <strong> diz “isto é importante”, <em> diz “a entonação muda aqui”, <code> diz “isto é código”. O visual padrão que o navegador aplica em cima disso é consequência — e quando você quer só o visual, quem trabalha é o CSS, não a tag.

Todos os exemplos aqui são da página de um livro na Livraria Andradas: preço, estoque, cupom, ficha catalográfica e um trecho citado. É a mesma página que começou em títulos e parágrafos em HTML, a lição anterior desta trilha.

Cada saída colada abaixo veio de um Chromium 151 rodando de verdade, dirigido por script no macOS. Onde aparece console.log, é o mesmo comando que você pode colar no console do DevTools da sua página.

O nome técnico dessa informação é semântica. Em palavras simples, a tag diz o papel do trecho; o CSS decide como esse papel será desenhado. A gente vai olhar para os dois lados sem confundir um com o outro.

A ficha da biblioteca vem antes da cor da capa

Numa biblioteca, a lombada vermelha pode chamar atenção, mas é a ficha dizendo “referência”, “ficção” ou “consulta local” que informa como o livro deve ser usado. No HTML, a tag cumpre o papel da ficha e o CSS cuida da aparência. Duas tags podem desenhar igual e transmitir informações diferentes para quem navega sem enxergar o estilo.

Antes de comparar b e strong, desligue mentalmente o CSS e escreva o que cada trecho deveria comunicar. Depois inspecione a árvore de acessibilidade do exemplo, além da tela. A pergunta verificável não é “ficou negrito?”, mas “o significado continuou disponível sem a aparência?”.

Comece pelo aviso de estoque do livro. As duas linhas abaixo parecem a mesma coisa na tela:

html
<p>Entrega em <b>3 dias úteis</b>.</p>
<p>Entrega em <strong>3 dias úteis</strong>.</p>

E são mesmo. O navegador aplica o mesmo estilo padrão nas duas:

js
const b = getComputedStyle(document.querySelector('b'));
const s = getComputedStyle(document.querySelector('strong'));
console.log('font-weight:', b.fontWeight, s.fontWeight);
console.log('font-size:  ', b.fontSize, s.fontSize);
console.log('font-style: ', b.fontStyle, s.fontStyle);
font-weight: 700 700 font-size: 16px 16px font-style: normal normal

Pixel por pixel, empate. A diferença não está no que você vê — está na segunda árvore que o navegador monta a partir do seu HTML. Além do DOM, que é a árvore dos elementos (o assunto de como o navegador monta a árvore DOM), ele monta a árvore de acessibilidade: uma versão resumida da página que descreve o papel de cada parte. É essa árvore que um leitor de tela lê, e não o seu HTML.

Esta é a árvore das duas linhas acima, exportada do mesmo Chromium:

paragraph StaticText "Entrega em" StaticText "3 dias úteis" StaticText "." paragraph StaticText "Entrega em" strong StaticText "3 dias úteis" StaticText "."

No primeiro parágrafo, o <b> sumiu: sobrou texto liso, três pedaços sem nenhuma marca. No segundo, apareceu um nó com o papel strong envolvendo o trecho. Quem lê a página pelo ouvido recebe a informação “isto é importante” numa das duas — e só numa.

A regra prática: <strong> é para importância de verdade, aquela que muda a decisão de quem lê. “Últimas 3 unidades”, “não recebemos devolução depois de 7 dias”. <b> é destaque sem peso: o nome do autor numa lista de resultados, para o olho achar mais rápido.

em e i: a ênfase que muda o sentido

A dupla itálica funciona igualzinho. <em> marca ênfase — o trecho em que a voz muda e a frase troca de sentido. <i> marca um trecho que está “à parte”: termo estrangeiro, nome científico, pensamento de personagem.

html
<p>Este exemplar <i>está</i> na loja.</p>
<p>Este exemplar <em>está</em> na loja.</p>
js
const i = getComputedStyle(document.querySelector('i'));
const em = getComputedStyle(document.querySelector('em'));
console.log('font-style: ', i.fontStyle, em.fontStyle);
console.log('font-weight:', i.fontWeight, em.fontWeight);
font-style: italic italic font-weight: 400 400

De novo, empate visual. E de novo a árvore separa os dois: o <em> vira um nó com papel emphasis, o <i> não vira nada.

paragraph StaticText "Este exemplar" StaticText "está" StaticText "na loja." paragraph StaticText "Este exemplar" emphasis StaticText "está" StaticText "na loja."

Repare no exemplo: “este exemplar está na loja” com ênfase responde a uma dúvida (“mas chegou mesmo?”). Sem a ênfase, é uma frase neutra. É exatamente o tipo de informação que se perde quando alguém não vê o itálico.

mark, small, del e ins: marcar preço e busca

Estas quatro resolvem situações concretas de uma loja. <del> é o que foi removido, <ins> é o que entrou no lugar, <small> é letra miúda e <mark> destaca o que interessa agora.

html
<p>De <del>R$ 89,90</del> por <ins>R$ 62,90</ins>.
   <small>Frete grátis acima de R$ 120.</small></p>

<p>Resultado: Cartas de um verão <mark>sem chuva</mark></p>

O visual padrão de cada uma:

js
for (const t of ['del', 'ins', 'small', 'mark']) {
  const s = getComputedStyle(document.querySelector(t));
  console.log(t.padEnd(6), s.textDecorationLine.padEnd(13), s.fontSize.padEnd(10), s.backgroundColor);
}
del line-through 16px rgba(0, 0, 0, 0) ins underline 16px rgba(0, 0, 0, 0) small none 13.3333px rgba(0, 0, 0, 0) mark none 16px rgb(255, 255, 0)

O <mark> já vem com fundo amarelo puro — é o único da lista que pinta alguma coisa. E o <small> cai para 13,33px: o estilo padrão dele é font-size: smaller, um degrau abaixo dos 16px do parágrafo.

Rodando a mesma checagem de árvore em cada uma dessas tags, dá para montar a tabela que vale para o resto da lição:

tag nó na árvore de acessibilidade visual padrão
<b> nenhum negrito
<strong> strong negrito
<i> nenhum itálico
<em> emphasis itálico
<mark> mark fundo amarelo
<small> nenhum fonte menor
<del> deletion riscado
<ins> insertion sublinhado
<code> code fonte monoespaçada
<sub> subscript abaixo da linha
<sup> superscript acima da linha
<abbr> Abbr sublinhado pontilhado
<cite> nenhum itálico

code e pre: o espaço em branco que finalmente conta

O cupom de desconto é um trecho de código: uma sequência literal que precisa ser digitada exatamente assim. Isso é <code>.

html
<p>Use o cupom <code>ANDRADAS10</code> no carrinho.</p>

Já a ficha catalográfica do livro é um bloco inteiro em que os espaços e as quebras de linha fazem parte do conteúdo. Dentro de um <p> normal, o HTML colapsa tudo isso em um espaço só. Compare os dois com o mesmo texto dentro:

html
<p id="p">ANDRADAS, Marina.
   Cartas de um verão sem chuva /
   Marina Andradas. — 2. ed.</p>

<pre id="pre">ANDRADAS, Marina.
   Cartas de um verão sem chuva /
   Marina Andradas. — 2. ed.</pre>
js
const p = document.getElementById('p');
const pre = document.getElementById('pre');
console.log('p  ', getComputedStyle(p).whiteSpace, '|', Math.round(p.getBoundingClientRect().height) + 'px de altura');
console.log('pre', getComputedStyle(pre).whiteSpace, '  |', Math.round(pre.getBoundingClientRect().height) + 'px de altura');
console.log(JSON.stringify(p.innerText));
console.log(JSON.stringify(pre.innerText));
p normal | 18px de altura pre pre | 45px de altura "ANDRADAS, Marina. Cartas de um verão sem chuva / Marina Andradas. — 2. ed." "ANDRADAS, Marina.\n Cartas de um verão sem chuva /\n Marina Andradas. — 2. ed."

O parágrafo virou uma linha de 18 pixels, com todas as quebras e os recuos transformados em espaço simples. O <pre> ocupou 45 pixels, três linhas, com os \n e os três espaços de recuo intactos.

Tem uma pegadinha só no <pre>, e ela pega todo mundo uma vez: o interpretador de HTML descarta a primeira quebra de linha logo depois da tag de abertura.

html
<pre id="a">
ISBN 978-85-0000-000-0</pre>

<pre id="b">

ISBN 978-85-0000-000-0</pre>
js
console.log(JSON.stringify(document.getElementById('a').textContent));
console.log(JSON.stringify(document.getElementById('b').textContent));
"ISBN 978-85-0000-000-0" "\nISBN 978-85-0000-000-0"

A primeira quebra some para você poder escrever <pre> numa linha e o conteúdo começar na linha de baixo, sem ganhar uma linha vazia de brinde. A segunda quebra sobrevive. Por isso a tag de fechamento gruda no conteúdo: um </pre> na linha seguinte adiciona uma quebra visível no fim.

Citação: blockquote, q e cite

Três tags para três coisas diferentes. <blockquote> é a citação em bloco, <q> é a citação curta dentro da frase, e <cite> é o título da obra — não o nome de quem escreveu.

html
<blockquote cite="https://livrariaandradas.exemplo/cartas">
  <p>Choveu por dentro naquele verão inteiro.</p>
  <footer>— <cite>Cartas de um verão sem chuva</cite>, Marina Andradas</footer>
</blockquote>

O <q> tem um detalhe que quase ninguém conhece: você não digita as aspas. O navegador as coloca sozinho, e escolhe o desenho delas pelo idioma declarado no lang do trecho.

html
<p lang="pt-BR">A resenha diz: <q>o melhor romance do ano</q></p>
<p lang="fr">A resenha diz: <q>o melhor romance do ano</q></p>
<p lang="de">A resenha diz: <q>o melhor romance do ano</q></p>

O que aparece na tela, linha por linha:

lang="pt-BR" → A resenha diz: “o melhor romance do ano” lang="fr" → A resenha diz: «o melhor romance do ano» lang="de" → A resenha diz: „o melhor romance do ano“

O francês ganhou as aspas angulares e o alemão ganhou a aspa de abertura embaixo, sem você escrever uma linha a mais. Se você digitar as aspas na mão dentro do <q>, elas aparecem duplicadas.

Essas aspas têm uma característica que surpreende na primeira vez: elas não fazem parte do texto. O navegador as desenha com content nos pseudo-elementos ::before e ::after, então elas somem de qualquer leitura programática do conteúdo.

js
const q = document.querySelector('q');
console.log('textContent:', JSON.stringify(q.textContent));
console.log('::before   ', getComputedStyle(q, '::before').content);
console.log('::after    ', getComputedStyle(q, '::after').content);
textContent: "o melhor romance do ano" ::before open-quote ::after close-quote

O textContent volta sem aspa nenhuma, e o valor declarado é a palavra-chave open-quote — não o caractere. Quem escolhe o desenho é a propriedade quotes da folha de estilo padrão, que o navegador troca conforme o lang.

Na árvore de acessibilidade, porém, as aspas aparecem como texto de verdade:

paragraph StaticText "A resenha diz:" StaticText "“" StaticText "o melhor romance do ano" StaticText "”"

Ou seja: quem lê a página pelo ouvido recebe a citação delimitada, mesmo com as aspas nascendo do CSS. Só o seu JavaScript é que não as enxerga.

O atributo cite no <blockquote> guarda a URL da fonte. Ele não aparece na tela — é metadado, lido por scripts e por ferramentas. O <blockquote> também chega com margin-left: 40px de estilo padrão, e essa margem é decoração: quem dá o significado é a tag, não o recuo.

sub, sup e abbr na ficha do livro

A ficha técnica junta as três. Ordinal em <sup>, fórmula em <sub>, sigla em <abbr> com o significado no atributo title.

html
<p>2<sup>a</sup> edição ·
   <abbr title="International Standard Book Number">ISBN</abbr>
   978-85-0000-000-0</p>

<p>Coleção Água: do H<sub>2</sub>O ao mar</p>

A árvore de acessibilidade dos dois parágrafos:

paragraph StaticText "2" superscript StaticText "a" StaticText "edição ·" Abbr "International Standard Book Number" StaticText "ISBN" StaticText "978-85-0000-000-0" paragraph StaticText "Coleção Água: do H" subscript StaticText "2" StaticText "O ao mar"

E o estilo padrão que o navegador aplica nas duas primeiras:

js
const abbr = getComputedStyle(document.querySelector('abbr'));
const sup = getComputedStyle(document.querySelector('sup'));
console.log('abbr:', abbr.textDecorationLine, abbr.textDecorationStyle);
console.log('sup: ', sup.verticalAlign, sup.fontSize);
abbr: underline dotted sup: super 13.3333px

Repare no que o <abbr> faz: o texto do title virou o nome acessível do nó — o ISBN continua ali como texto, e a expressão por extenso passa a viajar junto com ele. Quem usa mouse vê essa expressão na dica que aparece ao parar em cima; isso é garantido. Já anunciar a forma extensa em voz é decisão do leitor de tela, e vários só fazem isso com a opção de expandir abreviações ligada. O que está na sua mão é publicar a informação: sem o title, não existe nem a opção. Esse é o tipo de detalhe que a lição de acessibilidade em HTML desenvolve por completo.

O <sup> e o <sub>, por outro lado, entram na árvore com papel próprio mas sem nome nenhum — o conteúdo deles é lido como texto comum, na sequência. Para ordinal e fórmula isso basta. Para notação em que a posição carrega o significado sozinha, o texto ao redor precisa dizer o que a marcação mostra.

O erro mais comum: < dentro de <code>

Você quer mostrar um trecho de HTML na página — o campo de e-mail do formulário de cupom, por exemplo. Escreve assim, do jeito óbvio:

html
<p id="alvo">Cole no seu site: <code><input type="email" name="cupom"></code></p>

E o resultado é este:

js
const alvo = document.getElementById('alvo');
console.log(alvo.outerHTML);
console.log('texto visível:', JSON.stringify(alvo.innerText));
console.log('campos de formulário na página:', document.querySelectorAll('input').length);
<p id="alvo">Cole no seu site: <code><input type="email" name="cupom"></code></p> texto visível: "Cole no seu site: " campos de formulário na página: 1

O código que você queria mostrar virou um campo de digitação de verdade. Não há erro no console, não há aviso: o navegador leu < como início de tag e fez o que você mandou. O texto visível ficou em “Cole no seu site: “ e a página ganhou um <input> que ninguém pediu.

O conserto é escrever os sinais como entidades: &lt; no lugar de < e &gt; no lugar de >.

html
<p id="alvo">Cole no seu site: <code>&lt;input type="email" name="cupom"&gt;</code></p>
texto visível: "Cole no seu site: <input type=\"email\" name=\"cupom\">" campos de formulário na página: 0

Agora o texto aparece inteiro e nenhum campo foi criado. <code> não escapa nada sozinho — ele só diz “isto é código”. Escapar continua sendo trabalho seu, e é o assunto da próxima lição, sobre entidades HTML.

Quando parar de marcar e chamar o CSS

O teste é sempre o mesmo: desligue a folha de estilo e pergunte se o texto perdeu informação. Se perdeu, era semântica e a tag estava certa. Se ele só ficou mais feio, era aparência e o lugar disso é o CSS.

css
/* aparência: nenhuma dessas linhas muda o significado do texto */
strong { font-weight: 800; }
mark { background: oklch(0.95 0.15 100); padding: 0 0.15em; }
del { text-decoration-color: crimson; }
abbr[title] { text-decoration: underline dotted; cursor: help; }
code { font-family: ui-monospace, monospace; font-size: 0.9em; }

Repare que todas essas regras redecoram tags que já significam alguma coisa. O caminho contrário — pegar um <span> e deixá-lo em negrito para fingir um <strong> — devolve exatamente o problema do começo da lição: a árvore de acessibilidade fica sem o nó. Escolher a tag pelo significado e ajustar o visual depois é o mesmo raciocínio que sustenta o HTML semântico das tags de estrutura. A folha que cuida da aparência entra pelo head do documento e pode mudar o visual sem trocar o significado.

Juntando tudo, a página do livro fica com esta marcação:

html
<h2>Cartas de um verão sem chuva</h2>
<p>De <b>Marina Andradas</b>. <strong>Últimas 3 unidades</strong> em estoque.</p>
<p>Preço: <del>R$ 89,90</del> <ins>R$ 62,90</ins>
   <small>frete grátis acima de R$ 120</small></p>
<p>Use o cupom <code>ANDRADAS10</code> no carrinho.</p>
<blockquote><p>Choveu por dentro naquele verão inteiro.</p></blockquote>
<p><abbr title="International Standard Book Number">ISBN</abbr> 978-85-0000-000-0</p>

E é assim que o navegador a entrega para quem não vê a tela:

RootWebArea "Livraria Andradas" heading "Cartas de um verão sem chuva" StaticText "Cartas de um verão sem chuva" paragraph StaticText "De" StaticText "Marina Andradas" StaticText "." strong StaticText "Últimas 3 unidades" StaticText "em estoque." paragraph StaticText "Preço:" deletion StaticText "R$ 89,90" insertion StaticText "R$ 62,90" StaticText "frete grátis acima de R$ 120" paragraph StaticText "Use o cupom" code StaticText "ANDRADAS10" StaticText "no carrinho." blockquote paragraph StaticText "Choveu por dentro naquele verão inteiro." paragraph Abbr "International Standard Book Number" StaticText "ISBN" StaticText "978-85-0000-000-0"

O RootWebArea do topo é a página inteira, nomeada pelo <title> do documento. Abaixo dele, o nome da autora está em <b> e aparece como texto liso — está certo, é destaque sem importância. Já o aviso de estoque, o preço antigo, o preço novo, o cupom, a citação e a sigla chegaram todos com papel próprio. Essa é a página que continua funcionando sem CSS, sem imagem e sem enxergar a tela.

O que vem depois

A próxima lição resolve a dívida que ficou aqui: escrever <, >, &, acento e espaço fixo sem quebrar a página, em entidades HTML. Depois disso a trilha de HTML segue para links e imagens, onde o mesmo raciocínio de significado antes de aparência volta a decidir tudo.

Prefere aprender em vídeo?

Tem uma aula sobre este assunto no nosso canal.

Ver todos os vídeos do canal
  • html
  • texto
  • negrito
  • italico
  • semantica

Perguntas frequentes

Então usar a tag b hoje é errado?
Não. A especificação mantém o <b> para destacar um trecho sem atribuir importância a ele — o nome do autor numa lista de resultados, a palavra-chave de um parágrafo. O critério é simples: se a frase perde informação quando o destaque some, é <strong>; se perde só conforto de leitura, é <b>.
O leitor de tela muda mesmo a voz nos trechos importantes?
Depende do leitor e da configuração de quem usa. O que o navegador garante é entregar a informação: o <strong> vira um nó com papel próprio na árvore de acessibilidade e o <b> não vira nada. Sem esse nó, nenhum leitor tem como anunciar diferença nenhuma.
Posso usar mark para qualquer destaque amarelo?
Não é para isso. O <mark> significa "relevante para o que você está fazendo agora" — o termo buscado dentro do resultado, o trecho que a página pediu para conferir. Destaque decorativo permanente é <span> com uma classe e uma regra de CSS.
Qual a diferença entre a tag pre e a propriedade white-space do CSS?
O <pre> é um elemento de bloco que já significa "texto pré-formatado" e chega com fonte monoespaçada e espaços preservados. A propriedade do CSS só muda a renderização de um elemento qualquer: se a folha de estilo não carregar, o texto volta a colapsar os espaços e a formatação some.
Preciso colocar code dentro de pre?
Para bloco de código, sim — é a combinação que a especificação recomenda. O <pre> preserva o espaço em branco e o <code> diz que aquele conteúdo é código. Para saída de terminal ou texto tabulado, como uma ficha catalográfica, o <pre> sozinho basta.

Dúvidas e comentários

Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.

Todo o código deste artigo foi executado em Chromium 151.0.7922.34 no macOS, dirigido por script, e as saídas exibidas são as reais — como produzimos este conteúdo.

Fontes consultadas

  1. MDN — strong: The Strong Importance element — developer.mozilla.org
  2. WHATWG HTML Standard — Text-level semantics — html.spec.whatwg.org
  3. W3C — HTML Accessibility API Mappings 1.0 — w3.org

Continue por aqui