Emmet: ID and Class
レッスン03では、[YIJIAN 0 PH]と[YIJIAN 1 PH]を簡単に紹介しました。このレッスンでは、これら2つの「CSSセレクタースタイル」の速記演算子について体系的に説明します。Emmetの略語は、構造と属性の両方を一度に表現することができます。最も重要なルール: HTMLコンテキストでタグ名を省略するとデフォルトは[YIJIAN 2 PH]になり、Emmetはクラス名に基づいて別の要素を決して「推測」しません(クラスが[YIJIAN 3 PH]であっても、[YIJIAN 4 PH]にはなりません)。
1.学ぶこと
- [YIJIAN 0 PH]省略形: [YIJIAN 1 PH]属性のCSSセレクタスタイル式
- [YIJIAN 0 PH]省略形: [YIJIAN 1 PH]属性のCSSセレクタスタイル式
- idとクラスの混合:[ YIJIAN 0 PH]は両方の属性を一度に設定します -複数のクラスの連鎖:[ YIJIAN 0 PH]は3つのクラスを一度に設定します -ネストとの組み合わせ:[ YIJIAN 0 PH]は階層全体に属性を分散します
2.フロントエンド開発者の実話
###( 1)痛み:タグと属性は常に2つの別々のパスが必要でした
Alice was upgrading the styling of a login form. She needed to add class="btn btn-primary btn-lg" to every <button> and id="loginForm" with class="form-horizontal" to the form itself. Manually, every tag required writing the full structure:
<button class="btn btn-primary btn-lg">Login</button>
<input id="username" class="form-control" type="text" name="user">
Every tag repeated the tag name plus attributes, and the order of tags and attributes relied on memory. By her count: an 8-line login form required hand-writing 8 tags + 24 attribute names = 32 repeated text segments. Just typing the quotes and equals signs for attributes was making her fingers ache.
Even worse: she recalled a previous project where she mistakenly assumed .btn would automatically trigger a <button> tag—a misunderstanding that sent her down a troubleshooting rabbit hole. Emmet's implicit tag rule absolutely does not switch tag names based on class names.
(2) How .class and #id Shorthand Solves It
Emmet uses exactly the same syntax as CSS selectors to express attributes—.btn directly adds to the current tag's class attribute, and #loginForm adds to the id attribute. This syntax lets you write attributes at the same time you write the tag structure, without switching between "tag mode" and "attribute mode."
Alice rewrote the entire login form with a single line of 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 sets both id and class simultaneously. .btn.btn-primary.btn-lg chains three classes with . in one go. 8 tags + 24 attributes, handled in 1 line. From 32 repeated text segments to 1 line, from 5 minutes to 12 seconds.
(3) Benefits
.class and #id are the key operators that merge "structure" and "attributes" into one in Emmet. After this lesson, Alice can write attributes for 80% of her tags simultaneously; the multi-class syntax is identical to CSS, with nearly zero learning curve; and remembering the "omit tag name → div" implicit rule (even if the class is btn, it stays a div) prevents her abbreviations from being misled by class names.
3. .class: CSS Selector-style Class Attribute
.classname in Emmet is equivalent to adding class="classname" to the current tag. When no tag is specified (Lesson 03 implicit rule), it defaults to div.
| Abbreviation | Expansion | Notes |
|---|---|---|
.box |
<div class="box"></div> |
Implicit div |
p.text |
<p class="text"></p> |
Explicit p |
section.hero |
<section class="hero"></section> |
Explicit section |
a.link |
<a href="" class="link"></a> |
Explicit a, a auto-adds href |
Tip: Multiple classes are chained with
.with no spaces between class names—.btn.btn-primarymeans two classes:btnandbtn-primary. Spaces in Emmet are stop characters; they are parsed as multiple independent abbreviations.
4. #id: CSS Selector-style id Attribute
#idname in Emmet is equivalent to adding id="idname" to the current tag. Usage is completely symmetric with .class and corresponds to the CSS ID selector (#id).
| Abbreviation | Expansion |
|---|---|
#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 and class Can Be Mixed
#id and .class on the same tag have no ordering requirement and can be freely combined:
| Abbreviation | Expansion |
|---|---|
#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> |
Key Point: Emmet's
#idand.classcome from CSS selector syntax, but the semantics are reversed—CSS uses#and.to select existing elements, while Emmet uses#and.to generate elements with those attributes. Same syntax, opposite purpose.
5. Practical Examples
The following 5 examples cover all core scenarios for .class and #id—from basic single class, to multiple classes, to attribute chains in nested structures.
▶ Example: Single Class .container (Difficulty ⭐)
The most basic class shorthand: omit the tag name and it defaults to div.
Abbreviation:
.container
Expansion:
<div class="container"></div>
Output:
TEXT 📖 参照専用Implicit div tag + single class. This shorthand is extremely common in utility-class frameworks like Bootstrap and Tailwind. .container in Bootstrap is a fixed-width container; in Tailwind it is a max-width utility. Note: when you write .container inside a ul parent, .container still implicitly becomes a div—unless your abbreviation position genuinely requires a li child of ul, .container will never auto-morph into a semantic element like li (Lesson 06 implicit rules).
▶ Example: Single ID #main (Difficulty ⭐)
The most basic id shorthand.
Abbreviation:
#main
Expansion:
<div id="main"></div>
Output:
TEXT 📖 参照専用An empty div with id="main". In HTML, ids must be globally unique, so this shorthand is often used for "page main container" or "route mount point." Note: Emmet does not validate id uniqueness—multiple #main abbreviations all expand to id="main"; whether that causes a conflict is up to you to check manually.
▶ Example: Multi-Class Chain .btn.btn-primary.btn-lg (Difficulty ⭐⭐)
Chaining multiple classes with .—note: the default is still <div>; it will not become <button> just because a class name contains "btn."
Abbreviation:
.btn.btn-primary.btn-lg
Expansion:
<div class="btn btn-primary btn-lg"></div>
Output:
TEXT 📖 参照専用
QUERY LENGTH LIMIT EXCEEDED. MAX ALLOWED QUERY : 500 CHARS
▶ Example: id + class Combination #header.nav (Difficulty ⭐)
Mixing #id and .class—order does not affect the expansion result.
Abbreviation:
#header.nav
Expansion:
<div id="header" class="nav"></div>
Output:
TEXT 📖 参照専用Sets both id="header" and class="nav" at once. This is the classic shorthand for a page header navigation. The order of id and class can be swapped (.nav#header produces the same result), but writing id first aligns with the semantic habit of "establish unique identity, then describe type." This shorthand is important in multi-page applications—the #header id remains the same across pages, so CSS can target it uniformly.
▶ Example: Nested Attribute Chain div#main.container>section.content>p.text (Difficulty ⭐⭐)
Distributing id and class across every level of nesting—3 levels of tags, each with its own attributes.
Abbreviation:
div#main.container>section.content>p.text
Expansion:
<div id="main" class="container">
<section class="content">
<p class="text"></p>
</section>
</div>
Output:
TEXT 📖 参照専用
QUERY LENGTH LIMIT EXCEEDED. MAX ALLOWED QUERY : 500 CHARS
6. Complete Example: Login Form + Attribute Chain
Combine .class and #id with the > and + operators from earlier lessons to build a complete login form in one line.
▶ Example: Complete Login Form (Difficulty ⭐⭐)
Abbreviation:
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})
Expansion:
<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>
Output:
TEXT 📖 参照専用Breakdown: form gets both id and class. Inside, + adds two input siblings, then + adds a button. Both inputs and buttons get styling classes via .class, and inputs additionally use #id (optional) and [type=name=placeholder=] (covered in the next lesson) for attributes. Note that the button level explicitly writes `<button>`, so .btn.btn-primary.btn-lg becomes a class on a button rather than an implicit div. This is the standard pattern of "using explicit tags to avoid misjudgment."
❓ よくある質問
.btn.btn-primary expand to <button> or <div>? Why?<div>. Emmet's implicit tag rules depend only on parent element context, not on the literal value of class/id names. Unless you explicitly write button.btn.btn-primary, the default when there is no explicit tag is always div. This is the most common pitfall for beginners—many assume .btn should map to button, and then think the div expansion is a bug.#my-id need to be escaped?#my-id and .my-class are valid CSS selector characters; Emmet treats them as part of the id/class name. However, an initial hyphen (e.g., #-main) is not valid CSS syntax and Emmet may throw an error or parse unexpectedly.# and . be mixed on the same tag?#a.b.c.d.e.f.g is fully valid and expands to <div id="a" class="b c d e f g"></div>. In practice, ids should be unique and limited in number, and too many classes make style management harder. Recommendation: 1 id + 2–4 classes is a common "reasonable upper limit."#header and .header after expansion?.header → <div class="header"></div> (class is for reusable "type"); #header → <div id="header"></div> (id is for "unique identity"). At the CSS selector level: .header can match multiple elements, #header can only match one. At the HTML semantic level: class is typically used for "component type" (button, card, form), while id is typically used for "page anchor or JS hook."📖 まとめ
.classnameaddsclass="classname"to the current tag#idnameaddsid="idname"to the current tag- When a tag is omitted, the default is
div(not influenced by class name association) - Multiple classes are chained with
.with no spaces #idand.classcan be mixed; order does not affect the expansion- When combined with nesting: each level can independently set its own id/class attributes
- To force a button tag, you must explicitly write
button.btn.btn-primary.btn-lg
📝 練習問題
- Basic (Difficulty ⭐): Write 5 Emmet abbreviations that expand to: (a)
.alert; (b)#app; (c).btn.btn-danger; (d)#header.nav.dark; (e)a.btn. - Intermediate (Difficulty ⭐⭐): Analyze the expansion structure of
header#top.navbar>nav.main>ul.nav-list>li.nav-item*3>a.nav-link(name each tag and attribute at every level), and verify that Emmet's expansion matches your analysis. - Challenge (Difficulty ⭐⭐⭐): Write a complete Bootstrap-style "card grid": outer
div.container, containingdiv.row, which contains 3.cardelements. Each card includesimg.card-img-top,div.card-body,h5.card-title,p.card-text, anda.btn.btn-primary. Write the entire structure in one line of Emmet, and explain why.btn.btn-primaryhere automatically becomes<a>instead of an implicit div (hint: is there an explicit tag in the abbreviation?).