Emmet: Text Content `{text}` and Multi-`$` Zero-Padding

Through the first 8 lessons, you have learned Emmet's 8 HTML structure operators (> + ^ * () .class #id [attr]) and 1 numbering operator ($). But two "semantic" scenarios are still unsolved—"putting 'Click me' inside a button" and "10 cards with content numbered 001, 002." The former is solved by {text} text content insertion, and the latter by multi-$ zero-padding. This lesson combines these two operators, upgrading your abbreviations from "building structure" to "generating content."

1. What You Will Learn


2. A Frontend Developer's Real Story

(1) The Pain: Tags Are Built, But Content Still Needs Typing Character by Character

Alice was building a "Features Showcase" section for a product landing page, requiring 6 cards, each containing an icon, title, description, and button. She first wrote the card structure using Lesson 06's () and implicit tags:

TEXT 📖 Display only
section.features>(.card*6>i.icon+h3+p+button.btn)

The structure was done in 1 line—Emmet expanded 6 cards, each with an icon, h3, p, and button. But then Alice had to write the content for each card: titles like "High Performance," "Ease of Use," "Scalable," "Secure," "Cross-Platform," "Open Source," a 30-character description for each, and the "Learn More" button text repeated 6 times.

Alice started by hand—expanded HTML with 30+ empty tags, filling in content one by one. Just the titles took 5 minutes, descriptions another 10, and finally she typed "Learn More" 6 times (or just copy-pasted it).

Even worse was the pagination: a 100-page product list with <li>Page 1</li> through <li>Page 100</li> at the bottom of each page. Alice gave up after 30 lines. She tried using $: (ul.pagination>li>a{Page $})*100—the expansion gave "Page 1" through "Page 100," but pages 1–9 came out as single-digit numbers, looking like a bug. She wanted "01," "02," ..., "99," "100"—the first 9 pages needed two-digit zero-padding, while the rest could display normally.

(2) How {text} and Multi-$ Zero-Padding Solve It

Emmet provides two complementary mechanisms:

Text content {text}: Content inside curly braces is inserted as a text node inside the tag. Alice's 6 cards could be written as:

TEXT 📖 Display only
section.features>(.card*6>(i.icon)+h3{High Performance}+p{This is the first description}+button.btn{Learn More})

But with 6 cards each needing different content, *6 can't simply repeat the same text—this is where looping templates with $ numbering come in.

Numbering $ and multi-digit zero-padding: $ is the current sequence number; $$ zero-pads to 2 digits; $$$ zero-pads to 3 digits. Alice's pagination can be written as:

TEXT 📖 Display only
(ul.pagination>li>a{Page $$})*100

Which expands to "Page 01," "Page 02," ..., "Page 99," "Page 100"—the first 9 are auto-zero-padded to 2 digits, and from page 10 onward they display normally.

Alice rewrote the entire Features section in one line:

TEXT 📖 Display only
section.features>(h2{Product Features})+((.card>(i.icon)+h3{Feature $}+p{This is feature $ of 6}+button.btn{Learn More})*6)

And the 100-line pagination:

TEXT 📖 Display only
(ul.pagination>li>a{Page $$})*100

Alice verified and exclaimed: "6 cards' content went from 30 hand-written lines to 1 line, and the 100-line pagination went from 200 lines to 1 line. Emmet's efficiency boost in batch content generation scenarios is 50x or more."

(3) Benefits

{text} and multi-$ zero-padding are Emmet's core for handling "content factory" scenarios. The former lets you write content directly in the abbreviation (no need to fill it in after expansion), while the latter makes repeated elements' numbers auto-run, zero-pad, start from, and count backwards. After this lesson, Alice can write 6 feature cards in 15 seconds and 100-page pagination in 10 seconds. This lesson also begins Phase 3—the next lesson covers Lorem Ipsum placeholder text and implicit tag details.


3. Text Content {text} Definition

{text} is Emmet's syntax for inserting a text node inside a tag. Content inside curly braces becomes the tag's inner text verbatim—it can include any characters (Chinese, spaces, punctuation, etc.).

(1) Shorthand Rules

Abbreviation Expansion Notes
a{Click me} <a href="">Click me</a> Single tag + single text block
p{Hello world} <p>Hello world</p> p tag + text
button{Submit} <button>Submit</button> Works in any language
a{<strong>bold</strong>} <a href="">&lt;strong&gt;bold&lt;/strong&gt;</a> < and > auto-escaped to HTML entities

Key Point: Special characters (< > &) inside {text} are automatically escaped by Emmet to HTML entities (&lt; &gt; &amp;). This is an HTML5 safety requirement—preventing user input with angle brackets from breaking document structure. If you want to insert real HTML tags (so <strong> is parsed as a tag rather than text), you'll need the "filters" covered in Lesson 13, or manually edit after expansion.

(2) Where {text} Can Be Placed Inside a Tag

Position Abbreviation Expansion
Adjacent to tag name a{Click me} <a href="">Click me</a>
With > nesting p>{Click }+a{here} <p>Click <a href="">here</a></p>
Bare {text} { to continue} to continue (bare text, as an independent element)
With $ numbering li{item $}*3 <li>item 1</li>, <li>item 2</li>, <li>item 3</li>

4. Two Positions for {text}: Adjacent to Parent vs. Nested

This is the most refined design in Emmet's text content system. When {text} immediately follows a tag name, it does not change the parent context; but >{text} pushes the context one level deeper. The difference is the most common pitfall for beginners.

(1) Adjacent Mode: a{click}+b{here}

When {text} immediately follows a tag name (without a > prefix), the text is treated as a direct child of that tag, but it does not change the parent context—meaning subsequent + sibling elements remain at the same level as the current tag.

HTML
a{click}+b{here}
HTML
<a href="">click</a><b>here</b>

(2) Nested Mode: a>{click}+b{here}

When {text} is preceded by >, Emmet treats the >{text} as a child element and pushes the parent context inside a—subsequent + sibling elements are appended inside a.

HTML
a>{click}+b{here}
HTML
<a href="">click<b>here</b></a>

(3) Multi-Element Mixed Text: p{Click }+a{here}+{ to continue}

This classic example from the official documentation demonstrates the difference between the two modes:

HTML
p{Click }+a{here}+{ to continue}
HTML
<p>Click </p>
<a href="">here</a> to continue
HTML
p>{Click }+a{here}+{ to continue}
HTML
<p>Click <a href="">here</a> to continue</p>

Key Point: The first abbreviation (adjacent mode) produces 3 root-level elements (p, a, bare text), while the second (nested mode) puts the entire "Click here to continue" inside <p>. The difference comes from >: in the first version, {Click } makes p into a "p with click text" (without drilling down), while the second version's >{Click } pushes the context from p into p's interior, so the subsequent +a{here} and +{ to continue} are both appended inside p.

▶ Example: Basic Text Content a{Click me} (Difficulty ⭐)

The first text content example from Emmet's official documentation—adding a block of text to an a tag.

Abbreviation:

HTML
a{Click me}

Expansion:

HTML
<a href="">Click me</a>

Output:

TEXT 📖 Display only
Breakdown: a is the tag name (which defaults to including href=""), and {Click me} is the text node. Emmet automatically adds the href="" attribute to a (HTML5 default behavior), and the text "Click me" becomes a's child node. Note: {text} after the a tag does not change the parent context—if followed by +b{some}, b will be a sibling of a, not a child of a.

▶ Example: Multi-Element Mixed Text p>{Click }+a{here}+{ to continue} (Difficulty ⭐⭐)

Use nested mode to put the entire "Click here to continue" inside <p>.

Abbreviation:

HTML
p>{Click }+a{here}+{ to continue}

Expansion:

HTML
<p>Click <a href="">here</a> to continue</p>

Output:

TEXT 📖 Display only
Breakdown: p>{Click } pushes the context inside p, and "Click " becomes p's first text child; +a{here} appends an a with "here" text inside p; +{ to continue} appends the bare text " to continue" inside p. The final p contains 3 children: text "Click ", an a tag, and text " to continue". Without > (i.e., p{Click }+a{here}+{ to continue}), p would only contain "Click ", and a and the bare text would become root-level siblings—resulting in <p>Click </p> followed by <a>here</a> and bare text.

5. Numbering $ and Multi-Digit Zero-Padding

$ is Emmet's numbering placeholder (introduced in Lesson 08). This lesson extends it with two advanced uses: multi-digit zero-padding and start/reverse control.

(1) Multi-Digit Zero-Padding $$ $$$ $$$$

Lesson 08 used a single $ to generate 1, 2, 3. When the number range exceeds 9 (e.g., 100 table row numbers), a single $ displays mixed digit widths: 1, 2, ..., 9, 10, 11. Multiple $ characters make numbering auto-zero-pad to a fixed minimum width:

$ Count Expanded Form (*5) Use Case
$ 1, 2, 3, 4, 5 Simple lists
$$ 01, 02, 03, 04, 05 Small lists, months
$$$ 001, 002, 003, 004, 005 Order numbers, table row IDs
$$$$ 0001, 0002, ... Thousand-row tables, chapter numbers

Key Point: The number of $ characters determines the minimum padding width. If the actual number exceeds this width, Emmet does not truncate—*12 with $$ expands to 01, 02, ..., 09, 10, 11, 12 (the first 9 are zero-padded; the last 3 display normally). This semantic is "padding width = minimum width, not maximum."

(2) Starting Value $@N and Reverse $@-

By default, numbering starts from 1 ascending. Use @N to start from N, and @- for descending:

Modifier Meaning Example (*5)
$ (default) Ascending, from 1 1, 2, 3, 4, 5
$@3 Ascending, from 3 3, 4, 5, 6, 7
$@- Descending (iteration count → 1) 5, 4, 3, 2, 1
$@-3 Descending, from 3 backward *5 → 7, 6, 5, 4, 3 (based on @-3 start + iteration count overlay)

Note: $@-3 is supported in Emmet 1.2+. Common combinations are $@N (starting value) and $@- (descending starting from the iteration count). In @N, N is the starting value, not the ending value.

▶ Example: Numbering + Text ul>li{item $}*3 (Difficulty ⭐)

Embed $ inside {text} so each li's content carries an auto-number.

Abbreviation:

HTML
ul>li{item $}*3

Expansion:

HTML
<ul>
  <li>item 1</li>
  <li>item 2</li>
  <li>item 3</li>
</ul>

Output:

TEXT 📖 Display only
Breakdown: li{item $} is "an li tag + a block of text (item + current number)," and *3 repeats this template 3 times. Each repetition replaces $ with the current iteration number (1, 2, 3). The final 3 li elements each contain a block of "item N" text. This is Emmet's core pattern for scenarios like todo lists, feature lists, and FAQ numbering. Note: the space after "item" is part of the text (not an operator).

▶ Example: Zero-Padding ul>li{$$}*5 (Difficulty ⭐)

2-digit zero-padding—the first 9 elements auto-zero-pad; numbers beyond 9 display normally.

Abbreviation:

HTML
ul>li{$$}*5

Expansion:

HTML
<ul>
  <li>01</li>
  <li>02</li>
  <li>03</li>
  <li>04</li>
  <li>05</li>
</ul>

Output:

TEXT 📖 Display only
Breakdown: $$ means "display the current number with 2 digits." *5 repeats li 5 times, with $ values of 1, 2, 3, 4, 5—after 2-digit zero-padding, they become 01, 02, 03, 04, 05. With *12, the expansion would be 01, 02, ..., 09, 10, 11, 12—the first 9 are zero-padded, while the last 3 exceed 2 digits and display normally (no truncation). Zero-padding scenarios: pagination page numbers, months, product SKU codes.

▶ Example: Starting Value + Reverse ol>li{Step $@3}*5 (Difficulty ⭐⭐)

A 5-step process starting from 3—use $@3 to control the starting value.

Abbreviation:

HTML
ol>li{Step $@3}*5

Expansion:

HTML
<ol>
  <li>Step 3</li>
  <li>Step 4</li>
  <li>Step 5</li>
  <li>Step 6</li>
  <li>Step 7</li>
</ol>

Output:

TEXT 📖 Display only
Breakdown: $@3 means "the current number starts from 3." ol>li makes li an ordered child of ol; {Step $@3} is the text template where "Step " is a fixed string and $@3 is the current number starting from 3. *5 repeats li 5 times, with numbers 3, 4, 5, 6, 7. This is Emmet's standard pattern for scenarios like "pagination starting from a certain page," "product chapters starting from chapter 3," and "step numbers not starting from 1." For reverse (from 5 down to 1), use $@- instead (auto-backtracks based on the iteration count).

6. Complete Example: Paginator + Numbering + Text Content

Combine {text}, multi-$ zero-padding, and $@N starting value—a 100-page paginator with each page displayed in 2-digit zero-padded format.

▶ Example: 100-Page Paginator (Difficulty ⭐⭐)

Abbreviation:

HTML
(ul.pagination>li.page$$>a{Page $$})*100

Expansion (excerpt):

HTML
<ul class="pagination">
  <li class="page01"><a href="">Page 01</a></li>
  <li class="page02"><a href="">Page 02</a></li>
  <li class="page03"><a href="">Page 03</a></li>
  <!-- ... -->
  <li class="page09"><a href="">Page 09</a></li>
  <li class="page10"><a href="">Page 10</a></li>
  <li class="page11"><a href="">Page 11</a></li>
  <!-- ... -->
  <li class="page99"><a href="">Page 99</a></li>
  <li class="page100"><a href="">Page 100</a></li>
</ul>

Output:

TEXT 📖 Display only
Breakdown: this example combines all of this lesson's operators—{} (text content), $ (numbering), $$ (2-digit zero-padding), () (grouping), * (multiplication), .class, > (nesting). The outer parentheses make the entire li template a repeatable unit; li.page$$ uses $$ in both the class name and the {text}, ensuring the class and content numbers stay in sync; the a tag acts as the li's child with content "Page XX." Note: the actual HTML for 100 pages has 100 li elements; this excerpt shows only the first 3, 9–11, and 99–100. Padding width = 2: pages 1–9 are 01–09, and from page 10 onward the numbers exceed 2 digits and display normally (10, 11, ...). For 3-digit zero-padding (001–100), use $$$ instead.

❓ FAQ

Q What happens to angle brackets < > inside {text}?
A Emmet auto-escapes them to HTML entities—< becomes &lt;, > becomes &gt;, and & becomes &amp;. This is an HTML5 safety requirement to prevent user input from breaking document structure. So a{<strong>bold</strong>} expands to <a href="">&lt;strong&gt;bold&lt;/strong&gt;</a> (angle brackets become entity characters; the browser displays the literal text "<strong>bold</strong>" without parsing it as a tag). To insert real HTML tags, use filters or manually edit after expansion.
Q What is the key difference between a{click}+b{here} and a>{click}+b{here} after expansion?
A The former (adjacent mode) produces two root-level siblings: <a>click</a><b>here</b>. The latter (nested mode) embeds <b> inside <a>: <a>click<b>here</b></a>. The critical difference is the >: adjacent mode does not change the parent context; nested mode pushes the context one level deeper. The mnemonic is: "if there's a > before the curly brace, go one level deeper; if not, stay at the current level." This is the most refined design in Emmet's text content system and a boundary every beginner must master.
Q Can $ appear multiple times within the same {text} block? Do multiple $ symbols produce the same or different numbers?
A They can appear multiple times, and all $ symbols within the same {text} block share the same number (the current iteration count). For example, li{item $: number $}*3 expands to <li>item 1: number 1</li>, <li>item 2: number 2</li>, <li>item 3: number 3</li>. Multiple $ are mainly used for padding-width control ($ for raw number, $$ for 2-digit zero-padding, $$$ for 3-digit zero-padding). To have different $ symbols within the same element produce different numbers (e.g., i=1, j=2), you need nested * repetition structures.
Q Can N in $@N be a negative number? What does N=0 mean?
A N can be negative or 0. $@-5*3 means ascending from -5 (-5, -4, -3); $@0*3 means ascending from 0 (0, 1, 2). However, negative numbers and 0 are rarely used as starting values in practice (negative sequence numbers are meaningless in HTML, and starting from 0 skips 1). Common usage: $@1 explicitly starts from 1 (equivalent to the default but more explicit in code), and $@100 starts from 100 (deep pagination scenarios). Use $@- for reverse; don't mix $@-N unless necessary.

📖 Summary


📝 Exercises

  1. Basic (Difficulty ⭐): Write one-line Emmet abbreviations that expand to: (a) a button{Sign Up} tag; (b) a <strong> tag with text "Warning"; (c) a p>lorem paragraph (i.e., <p>Lorem ipsum...</p>, not covered in this lesson; Lorem is covered in the next lesson).
  2. Intermediate (Difficulty ⭐⭐): Write a 12-item "Month List" ol>li{Month $$}*12 and verify the expansion (should be "Month 01" through "Month 12"). Then rewrite as a "Quarter List" ol>li{Quarter $}*4, verifying numbering from 1–4. Finally, write a "Product Features Section" with 5 cards, each containing <h3>Feature $</h3> and <p>Description for feature $</p>, all in one Emmet line.
  3. Challenge (Difficulty ⭐⭐⭐): Write a 100-page paginator with 3-digit zero-padding (Page 001 through Page 100). Requirements: (a) class using page$$$ (3-digit zero-padding); (b) text using Page $$$ (3-digit zero-padding); (c) starting page using $@1 (same as default behavior but explicitly declared). Verify the expansion in one Emmet line, and explain why $$$ does not truncate numbers beyond 99 (hint: Emmet's zero-padding = minimum width, not maximum width).
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏