Emmet: ID e Classe
A Aula 03 introduziu brevemente
.classe#id. Esta aula aborda sistematicamente esses dois operadores de atalho "estilo seletor CSS" — eles permitem que as abreviações Emmet expressem estrutura e atributos ao mesmo tempo. A regra mais crítica: omitir um nome de tag no contexto HTML assumedivpor padrão, e o Emmet nunca "adivinha" um elemento diferente com base no nome de uma classe (mesmo que a classe sejabtn, não se tornará um<button>).
1. O Que Você Vai Aprender
- Atalho
.class: expressão estilo seletor CSS para o atributoclass="class" - Atalho
#id: expressão estilo seletor CSS para o atributoid="id" - Misturando id e classe:
#header.navdefine ambos os atributos de uma vez - Encadeando múltiplas classes:
.btn.btn-primary.btn-lgdefine 3 classes de uma vez - Combinando com aninhamento:
div#main.container>section.content>p.textdistribui atributos pela hierarquia
2. A História Real de Uma Desenvolvedora Front-End
(1) A Dor: Tags e Atributos Sempre Precisavam de Duas Passagens Separadas
Alice estava atualizando o estilo de um formulário de login. Ela precisava adicionar class="btn btn-primary btn-lg" a cada <button> e id="loginForm" com class="form-horizontal" ao próprio formulário. Manualmente, cada tag exigia escrever a estrutura completa:
<button class="btn btn-primary btn-lg">Login</button>
<input id="username" class="form-control" type="text" name="user">
Cada tag repetia o nome da tag mais os atributos, e a ordem das tags e atributos dependia da memória. Pelas contas dela: um formulário de login de 8 linhas exigia escrever manualmente 8 tags + 24 nomes de atributos = 32 segmentos de texto repetidos. Só digitar as aspas e sinais de igual para os atributos estava fazendo seus dedos doerem.
Pior ainda: ela se lembrou de um projeto anterior onde assumiu erroneamente que .btn acionaria automaticamente uma tag <button> — um mal-entendido que a levou a uma longa investigação de problemas. A regra de tag implícita do Emmet absolutamente não alterna nomes de tag com base em nomes de classe.
(2) Como o Atalho .class e #id Resolve Isso
O Emmet usa exatamente a mesma sintaxe dos seletores CSS para expressar atributos — .btn adiciona diretamente ao atributo class da tag atual, e #loginForm adiciona ao atributo id. Esta sintaxe permite escrever atributos ao mesmo tempo que escreve a estrutura da tag, sem alternar entre "modo tag" e "modo atributo".
Alice reescreveu todo o formulário de login com uma única linha de Emmet:
form#loginForm.form-horizontal>(input#username.form-control[type=text name=user])+(input#pwd.form-control[type=password name=pwd])+(button.btn.btn-primary.btn-lg{Login})
#loginForm.form-horizontal define id e class simultaneamente. .btn.btn-primary.btn-lg encadeia três classes com . de uma vez. 8 tags + 24 atributos, tratados em 1 linha. De 32 segmentos de texto repetidos para 1 linha, de 5 minutos para 12 segundos.
(3) Benefícios
.class e #id são os operadores-chave que fundem "estrutura" e "atributos" em um no Emmet. Após esta aula, Alice pode escrever atributos para 80% de suas tags simultaneamente; a sintaxe de múltiplas classes é idêntica ao CSS, com curva de aprendizado quase zero; e lembrar da regra implícita "omitir nome da tag → div" (mesmo que a classe seja btn, permanece um div) impede que suas abreviações sejam enganadas por nomes de classe.
3. .class: Atributo de Classe Estilo Seletor CSS
.classname no Emmet é equivalente a adicionar class="classname" à tag atual. Quando nenhuma tag é especificada (regra implícita da Aula 03), assume div por padrão.
| Abreviação | Expansão | Observações |
|---|---|---|
.box |
<div class="box"></div> |
div implícito |
p.text |
<p class="text"></p> |
p explícito |
section.hero |
<section class="hero"></section> |
section explícito |
a.link |
<a href="" class="link"></a> |
a explícito, a adiciona href automaticamente |
Dica: Múltiplas classes são encadeadas com
.sem espaços entre os nomes das classes —.btn.btn-primarysignifica duas classes:btnebtn-primary. Espaços no Emmet são caracteres de parada; são analisados como múltiplas abreviações independentes.
4. #id: Atributo id Estilo Seletor CSS
#idname no Emmet é equivalente a adicionar id="idname" à tag atual. O uso é completamente simétrico com .class e corresponde ao seletor de ID do CSS (#id).
| Abreviação | Expansão |
|---|---|
#main |
<div id="main"></div> |
header#top |
<header id="top"></header> |
form#login |
<form id="login"></form> |
div#app |
<div id="app"></div> |
(1) id e Classe Podem Ser Misturados
#id e .class na mesma tag não têm requisito de ordenação e podem ser livremente combinados:
| Abreviação | Expansão |
|---|---|
#main.container |
<div id="main" class="container"></div> |
.container#main |
<div class="container" id="main"></div> |
header#top.nav |
<header id="top" class="nav"></header> |
nav.main.dark |
<nav class="main dark"></nav> |
Ponto-Chave: O
#ide.classdo Emmet vêm da sintaxe de seletores CSS, mas a semântica é invertida — o CSS usa#e.para selecionar elementos existentes, enquanto o Emmet usa#e.para gerar elementos com esses atributos. Mesma sintaxe, propósito oposto.
5. Exemplos Práticos
Os 5 exemplos a seguir cobrem todos os cenários principais para .class e #id — desde classe única básica, a múltiplas classes, a cadeias de atributos em estruturas aninhadas.
▶ Exemplo: Classe Única .container (Dificuldade ⭐)
O atalho de classe mais básico: omita o nome da tag e assume div por padrão.
Abreviação:
.container
Expansão:
<div class="container"></div>
Saída:
TEXT 📖 Somente leituraTag div implícita + classe única. Este atalho é extremamente comum em frameworks de classes utilitárias como Bootstrap e Tailwind. .container no Bootstrap é um contêiner de largura fixa; no Tailwind é uma utilidade de largura máxima. Nota: quando você escreve .container dentro de um pai ul, .container ainda implicitamente se torna um div — a menos que sua posição de abreviação genuinamente exija um filho li de ul, .container nunca se transformará automaticamente em um elemento semântico como li (regras implícitas da Aula 06).
▶ Exemplo: ID Único #main (Dificuldade ⭐)
O atalho de id mais básico.
Abreviação:
#main
Expansão:
<div id="main"></div>
Saída:
TEXT 📖 Somente leituraUm div vazio com id="main". Em HTML, ids devem ser globalmente únicos, então este atalho é frequentemente usado para "contêiner principal da página" ou "ponto de montagem de rota". Nota: o Emmet não valida a unicidade de ids — múltiplas abreviações #main todas expandem para id="main"; se isso causa um conflito, cabe a você verificar manualmente.
▶ Exemplo: Cadeia de Múltiplas Classes .btn.btn-primary.btn-lg (Dificuldade ⭐⭐)
Encadeando múltiplas classes com . — nota: o padrão ainda é <div>; não se tornará <button> só porque um nome de classe contém "btn".
Abreviação:
.btn.btn-primary.btn-lg
Expansão:
<div class="btn btn-primary btn-lg"></div>
Saída:
TEXT 📖 Somente leituraEsta é a abreviação que iniciantes mais frequentemente interpretam mal: porque o nome da classe é `btn`, muitos assumem que o Emmet reconhecerá `.btn` como um `<button>`. Mas as regras implícitas do Emmet não dependem dos valores de class/id — dependem apenas do contexto do elemento pai (veja a Aula 06). Quando não há contexto pai e nenhuma tag explícita, o Emmet sempre assume `div`. Para obter `<button class="btn btn-primary btn-lg">`, você deve escrever explicitamente `button.btn.btn-primary.btn-lg` ou `button.btn.btn-primary.btn-lg{Login}` (com conteúdo de texto, Aula 09). Verifique você mesmo: digite `.btn` no seu editor e pressione Tab para ver se expande para `div` ou `button`.
▶ Exemplo: Combinação id + classe #header.nav (Dificuldade ⭐)
Misturando #id e .class — a ordem não afeta o resultado da expansão.
Abreviação:
#header.nav
Expansão:
<div id="header" class="nav"></div>
Saída:
TEXT 📖 Somente leituraDefine ambos id="header" e class="nav" de uma vez. Este é o atalho clássico para uma navegação de cabeçalho de página. A ordem de id e class pode ser trocada (.nav#header produz o mesmo resultado), mas escrever id primeiro se alinha com o hábito semântico de "estabelecer identidade única, depois descrever tipo". Este atalho é importante em aplicações de múltiplas páginas — o id #header permanece o mesmo entre páginas, então o CSS pode direcioná-lo uniformemente.
▶ Exemplo: Cadeia de Atributos Aninhados div#main.container>section.content>p.text (Dificuldade ⭐⭐)
Distribuindo id e class por cada nível de aninhamento — 3 níveis de tags, cada um com seus próprios atributos.
Abreviação:
div#main.container>section.content>p.text
Expansão:
<div id="main" class="container">
<section class="content">
<p class="text"></p>
</section>
</div>
Saída:
TEXT 📖 Somente leituraDetalhamento: div carrega id="main" e class="container", desce um nível para section (com class="content"), depois desce para p (com class="text"). Cada nível define seus próprios atributos via #id ou .class. Este é o uso típico do Emmet para "estrutura baseada em componentes" — cada nível representa um contêiner ou componente semanticamente claro. Se você quiser definir atributos apenas em um nível (deixando outros vazios), simplesmente omita #/. desses níveis — ex.: div>section>p são apenas 3 níveis de aninhamento vazios.
6. Exemplo Completo: Formulário de Login + Cadeia de Atributos
Combine .class e #id com os operadores > e + das aulas anteriores para construir um formulário de login completo em uma linha.
▶ Exemplo: Formulário de Login Completo (Dificuldade ⭐⭐)
Abreviação:
form#loginForm.form-horizontal>(input#user.form-control[type=text name=user placeholder="Username"])+(input#pwd.form-control[type=password name=pwd placeholder="Password"])+(button.btn.btn-primary.btn-lg{Login})
Expansão:
<form id="loginForm" class="form-horizontal">
<input id="user" class="form-control" type="text" name="user" placeholder="Username">
<input id="pwd" class="form-control" type="password" name="pwd" placeholder="Password">
<button class="btn btn-primary btn-lg">Login</button>
</form>
Saída:
TEXT 📖 Somente leituraDetalhamento: form recebe tanto id quanto class. Dentro, + adiciona dois inputs irmãos, depois + adiciona um button. Ambos inputs e button recebem classes de estilo via .class, e os inputs adicionalmente usam #id (opcional) e [type=name=placeholder=] (abordado na próxima aula) para atributos. Note que o nível button escreve explicitamente `<button>`, então .btn.btn-primary.btn-lg se torna uma classe em um button em vez de um div implícito. Este é o padrão padrão de "usar tags explícitas para evitar interpretação equivocada".
❓ Perguntas Frequentes
P:
.btn.btn-primaryexpande para<button>ou<div>? Por quê? R:<div>. As regras de tag implícita do Emmet dependem apenas do contexto do elemento pai, não do valor literal dos nomes de class/id. A menos que você escreva explicitamentebutton.btn.btn-primary, o padrão quando não há tag explícita é semprediv. Esta é a armadilha mais comum para iniciantes — muitos assumem que.btndeveria mapear para button, e então pensam que a expansão para div é um bug.
P: Hifens em
#my-idprecisam ser escapados? R: Não. Hifens em#my-ide.my-classsão caracteres válidos de seletor CSS; o Emmet os trata como parte do nome id/class. No entanto, um hífen inicial (ex.:#-main) não é sintaxe CSS válida e o Emmet pode lançar um erro ou analisar de forma inesperada.
P: Quantas vezes
#e.podem ser misturados na mesma tag? R: Teoricamente ilimitado.#a.b.c.d.e.f.gé totalmente válido e expande para<div id="a" class="b c d e f g"></div>. Na prática, ids devem ser únicos e limitados em número, e classes demais dificultam o gerenciamento de estilo. Recomendação: 1 id + 2–4 classes é um "limite superior razoável" comum.
P: Qual é a diferença entre
#headere.headerapós a expansão? R:.header→<div class="header"></div>(classe é para "tipo" reutilizável);#header→<div id="header"></div>(id é para "identidade única"). No nível do seletor CSS:.headerpode corresponder a múltiplos elementos,#headerpode corresponder apenas a um. No nível semântico HTML: class é tipicamente usado para "tipo de componente" (botão, cartão, formulário), enquanto id é tipicamente usado para "âncora de página ou gancho JS".
📖 Resumo
.classnameadicionaclass="classname"à tag atual#idnameadicionaid="idname"à tag atual- Quando uma tag é omitida, o padrão é
div(não influenciado por associação de nome de classe) - Múltiplas classes são encadeadas com
.sem espaços #ide.classpodem ser misturados; a ordem não afeta a expansão- Quando combinado com aninhamento: cada nível pode definir independentemente seus próprios atributos id/class
- Para forçar uma tag button, você deve escrever explicitamente
button.btn.btn-primary.btn-lg
📝 Exercícios
- Básico (Dificuldade ⭐): Escreva 5 abreviações Emmet que expandam para: (a)
.alert; (b)#app; (c).btn.btn-danger; (d)#header.nav.dark; (e)a.btn. - Intermediário (Dificuldade ⭐⭐): Analise a estrutura de expansão de
header#top.navbar>nav.main>ul.nav-list>li.nav-item*3>a.nav-link(nomeie cada tag e atributo em cada nível), e verifique se a expansão do Emmet corresponde à sua análise. - Desafio (Dificuldade ⭐⭐⭐): Escreva uma "grade de cartões" completa no estilo Bootstrap:
div.containerexterno, contendodiv.row, que contém 3 elementos.card. Cada cartão incluiimg.card-img-top,div.card-body,h5.card-title,p.card-textea.btn.btn-primary. Escreva toda a estrutura em uma linha de Emmet e explique por que.btn.btn-primaryaqui automaticamente se torna<a>em vez de um div implícito (dica: há uma tag explícita na abreviação?).