Emmet: Wrap with Abbreviation

In lesson 14 you learned to expand a single shorthand line into complete HTML. But in real development, the scenario of already having code written is far more common — for example, you've already written a bunch of <li> items and suddenly realize they're missing an outer <ul> wrapper. Manually adding the wrapper means repeating 4–5 lines per occurrence. This lesson teaches Emmet's Wrap with Abbreviation action — select code + type shorthand = one-click wrapping. This is the second core action in Emmet's editor operations.

1. What You'll Learn


2. A Frontend Developer's Real Story

(1) Pain Point: You've Written the HTML, Then Realize You Forgot the Outer Wrapper

Alice inherits code from her colleague Bob. Bob wrote a blog's "Related Posts" module but forgot to wrap it with <ul>:

HTML
<li><a href="/post-1">Getting Started with Vue 3</a></li>
<li><a href="/post-2">React Hooks in Practice</a></li>
<li><a href="/post-3">Advanced TypeScript</a></li>

Alice wants to add a <ul class="related-posts"> to wrap the 3 <li> items. She tries doing it manually: copy the <ul> opening tag before the first <li>, copy </ul> after the third <li> — 2 copy-paste operations. If there are 5 such gaps across the codebase (blog post page, list page, detail page, archive page, search page), that's 10 copy-paste operations + 5 class name spelling checks.

Even worse, she often makes mistakes: pasting </ul> after a <li> accidentally places it in the middle (<li><a>...</a></li></ul>), breaking the DOM structure. Alice thinks: it's literally just "adding an outer wrapper" — why is it so tedious? Isn't there a "select + type shorthand = 1-step wrapping" method?

(2) The Wrap with Abbreviation Solution

Wrap with Abbreviation is Emmet's "reverse Expand Abbreviation" — not expanding from a blank slate, but adding a wrapper around existing code.

Alice's solution:

  1. Select all 3 <li> elements (column-select with Alt+mouse drag, or Ctrl+L to select lines)
  2. Press Shift+Alt+, to trigger Wrap
  3. Type the shorthand ul.related-posts>
  4. Auto-expands to the complete structure with the outer <ul>

With this single technique, Alice reduces fixing 5 missing wrappers from 10 copy-paste operations + 5 checks to 5 "select + Wrap" operations. Speed improvement of 3–5x, with zero typos (Emmet auto-generates class names).

(3) Benefits

Wrap with Abbreviation is the "bridge" in Emmet's editor operations — accelerating the "write first, optimize later" workflow by 3–5x. Combined with lesson 14's Expand Abbreviation (expanding from scratch) and lesson 16's Balance/Next Edit Point (editing acceleration), Emmet's complete "input → expand → edit → wrap" workflow is now in place. After this lesson, Alice's time for adding wrappers, inserting containers, and bulk restructuring drops from 5 minutes to 1 minute.


3. Core Definition of Wrap with Abbreviation

Wrap with Abbreviation is Emmet's action for rewriting existing code — wrapping selected code fragments with a new shorthand.

Dimension Detail
Purpose Adds a wrapper around selected code, restructures according to the new shorthand
Trigger Key VSCode Shift+Alt+, (comma); other editors Ctrl+Shift+A
Prerequisites Must have selected code (without selection, it calls Match Tag Pair to wrap the context)
Wrap Position Places selected content inside the last element by default (use $# placeholder to override)
Multi-line Support * marks repeating elements; * without a number means "repeat according to selected line count"
📌 Key Point: The default behavior places selected content inside the last element. To place selected content at a specific position (such as an attribute value or text node), use the $# placeholder — this is the key extension that differentiates Wrap from Expand.


4. Trigger Methods: Editor Comparison

Wrap with Abbreviation has significantly different trigger keys across editors because this action is relatively new (added after 2013), and implementation progress varies by editor.

Editor Default Trigger Key Command Palette Notes
VSCode None by default (use Command Palette) Emmet: Wrap with Abbreviation Opens an input box directly
WebStorm / IntelliJ Ctrl+Alt+J Emmet: Wrap with Abbreviation Popup for shorthand input
Sublime Text Ctrl+Shift+G (requires Emmet plugin) emmet: wrap Popup for shorthand input
Atom Ctrl+Shift+A Emmet: Wrap with Abbreviation Auto-select code prompt
💡 Tip: VSCode has no default shortcut for Wrap with Abbreviation — Shift+Alt+, in VSCode is Edit > Format Document, not Wrap. The community often custom-binds Shift+Alt+, to Wrap, but requires explicit binding in keybindings.json. The Command Palette (Ctrl+Shift+PEmmet: Wrap with Abbreviation) is the most reliable entry point — supported by every editor. Other editors may require selecting code before pressing the shortcut. First-time use should start with the Command Palette: trigger + input box + Enter — 3 steps.


5. Four Wrapping Modes

Wrap with Abbreviation supports 4 wrapping modes, covering 4 common needs: adding an outer wrapper, adding siblings, bulk restructuring, and nested wrapping.

(1) Single-Element Wrapping: Add an Outer Layer

Select 1 element, wrap with 1 shorthand. Common scenario: originally <p>text</p>, now needs to be wrapped inside <div class="wrapper">.

(2) Multi-Line Batch Wrapping: Select N Lines → Bulk Restructure

Select multiple consecutive lines, use * to mark repeating elements. The key difference is * without a number — meaning "auto-repeat based on selected line count".

(3) Nested Wrapping: Select Text → Add Inner Tag

Select a piece of text or a tag, use a shorthand to embed it inside a new element. This is the common pattern for "adding links, adding styles, adding semantics".

(4) Combined Wrapping: Select + Nest + Multiple Attributes

Simultaneously use select + nesting + custom attributes + multiple classes. This is Wrap's "ultimate form".


6. Hands-On Examples

The following 4 examples cover Wrap with Abbreviation's 4 wrapping modes.

▶ Example: Single-Element Wrapping <p>text</p>div.wrapper (Difficulty ⭐)

The most common Wrap scenario — adding an outer container to a single element.

Original code (in an HTML file):

HTML
<p>Hello World</p>

Steps:

  1. Select <p>Hello World</p> (drag with mouse or Ctrl+L)
  2. Press Shift+Alt+, to trigger Wrap
  3. Type the shorthand div.wrapper
  4. Press Enter to confirm

Expansion:

HTML
<div class="wrapper">
  <p>Hello World</p>
</div>

Output:

TEXT 📖 Display only
Explanation: After selecting `<p>Hello World</p>` and invoking Wrap, Emmet treats the entire `<p>` as the "wrapped content" and generates the outer structure from the `div.wrapper` shorthand. By default, Wrap places the selected content inside the **last element** — here `<p>` becomes a child of `<div>`. This is the most direct single-element wrapping scenario: a previously isolated `<p>` is now wrapped by `<div class="wrapper">`. Emmet auto-indents — `<p>` is indented by 2 spaces, consistent with lesson 06's implicit tag rules. This single step replaces 5 manual operations (copy opening tag, paste, adjust indentation, copy closing tag, paste).

▶ Example: List Wrapping — Select 3 <li>ul.nav (Difficulty ⭐⭐)

Multi-line batch wrapping — select 3 <li> items and one-click wrap with a nav container.

Original code:

HTML
<li><a href="/home">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>

Steps:

  1. Select all 3 lines (drag 3 lines with mouse, or Ctrl+L for 1 line + Ctrl+Shift+L for multi-line)
  2. Press Shift+Alt+, to trigger Wrap
  3. Type the shorthand ul.nav>
  4. Press Enter to confirm

Expansion:

HTML
<ul class="nav">
  <li><a href="/home">Home</a></li>
  <li><a href="/about">About</a></li>
  <li><a href="/contact">Contact</a></li>
</ul>

Output:

TEXT 📖 Display only
Explanation: Select 3 lines, invoke Wrap, type `ul.nav>`. Emmet treats `ul.nav>` as "the selected 3 lines become children of ul". Note: here **`>` is key** — it indicates "selected content as children". If the shorthand was written as `ul.nav` (without `>`), Emmet would place the 3 `<li>` elements as siblings of `<ul>` (incorrect structure). `>` determines the "wrap position" — whether it's child-node wrapping or sibling wrapping. Common rule: by default, use `>` to explicitly mark "child-node wrapping"; use `+` for "sibling addition".

Nested wrapping — select a piece of text and wrap it with a link tag.

Original code:

HTML
<p>Visit our website for more information.</p>

Steps:

  1. Select our website (double-click or drag)
  2. Press Shift+Alt+, to trigger Wrap
  3. Type the shorthand a[href="https://example.com"]
  4. Press Enter to confirm

Expansion:

HTML
<p>Visit <a href="https://example.com">our website</a> for more information.</p>

Output:

TEXT 📖 Display only
Explanation: Select the 11 characters of `our website` (excluding surrounding spaces), invoke Wrap, type `a[href="https://example.com"]`. Emmet treats the entire `<a>` tag as the "wrap template", with the selected content becoming the text inside `<a>`. Note: this scenario doesn't need `>` — because `<a>` is a leaf node (no children to position). **Key detail**: in `a[href="..."]`, `href` is an attribute and the wrapped content is text — `>` is unnecessary. This "plain text → text inside tag" conversion is extremely common in Emmet.

▶ Example: Combined Wrapping — Select Welcomeheader.container>h1.title (Difficulty ⭐⭐)

Combined wrapping — select + nest + custom class + multi-layer structure.

Original code:

HTML
<h1>Welcome</h1>

Steps:

  1. Double-click to select the text Welcome (text only, not the <h1> tag)
  2. Press Shift+Alt+, to trigger Wrap (VSCode users: Command Palette Ctrl+Shift+PEmmet: Wrap with Abbreviation)
  3. Type the shorthand header.container>h1.title
  4. Press Enter to confirm

Expansion:

HTML
<header class="container">
  <h1 class="title">Welcome</h1>
</header>

Output:

TEXT 📖 Display only
Explanation: This example combines Wrap + Expand. `header.container>h1.title` simultaneously includes 3 Emmet mechanisms: ① `header.container` — tag + class; ② `>` — child nesting; ③ selected content placed inside the last element (h1). Emmet expands according to the "header > h1" two-layer structure, placing the selected text `Welcome` as the text content of the last element (h1). This single step replaces 5 manual operations: write `<header class="container">`, newline, write `<h1 class="title">`, write Welcome, write `</h1></header>`. **Key detail**: select **text only**, not the entire `<h1>...</h1>` tag — because Wrap defaults to "placing selected content as-is inside the last element of the generated snippet" (official docs). If you select the entire `<h1>Welcome</h1>`, the result would be `<h1 class="title"><h1>Welcome</h1></h1>` (nested h1, invalid HTML). **Note the indentation**: Emmet auto-indents h1 by 2 spaces (header is the container), consistent with lesson 04's nesting rules.

7. Common Shorthand Quick Reference

Wrap with Abbreviation uses the same shorthands as Expand Abbreviation — any Emmet shorthand can be used as a Wrap parameter. Here are 4 commonly used shorthand types:

Scenario Shorthand Effect
Add outer wrapper div.wrapper Selected + div outer
Add semantics section.hero Selected + section semantic tag
Add navigation ul.nav>li* Selected N lines + ul/li structure
Add link a[href="..."] Selected text + a tag
Add header header.container>h1.title Selected + multi-layer nesting
⚠️ Note: *>3 and *3 are different — *>3 in Wrap means "repeat selected lines × 3" (e.g., ul>li*5 with 2 selected lines → 10 output lines); *3 always repeats 3 times. In Wrap, * (without a number) = auto-repeat based on selected line count is the most common.


❓ FAQ

Q Pressing Shift+Alt+, does nothing — VSCode's default "Format" shortcut pops up instead?
A Check for shortcut conflicts. VSCode's Shift+Alt+F is "Format Document". You may have misremembered — Wrap's actual shortcut is Shift+Alt+, (comma key, to the right of the M key). If it still doesn't work, use the Command Palette fallback: Ctrl+Shift+PEmmet: Wrap with Abbreviation.
Q After Wrap, the selected content disappears — for example, I selected <p>, and after Wrap only the outer <div> remains?
A This usually happens because the shorthand is missing >. For example, div.wrapper without > won't produce a nested structure — Emmet will only add <div> as a "sibling node beside the selected content". Wrap's core rule is "selected content = child of the last element" — you must explicitly express the "wrap position" using >. Fix: rewrite the shorthand as div.wrapper>.
Q Can I select multiple lines and specify a custom repeat count? For example, select 3 lines but want 5 output lines?
A Yes, but you need to use *N explicitly. ul>li*5 with 3 selected lines → 5 output lines (ignoring selected line count). But the more common pattern is * (without a number) = auto-repeat based on selected line count. This "auto by line count" is a core Wrap feature — it saves you from having to count how many lines you selected.
Q What is the $# placeholder for? When should I use it?
A $# is Wrap's unique "output position" placeholder — it controls where the selected content is placed in the Wrap result. Syntax: ul>li[title=$#]*>{$#}+img[alt=$#]. This shorthand means: the selected content appears in 3 places simultaneously (li's title attribute, li's text, img's alt attribute). Common scenario: copying a CSS comment to attribute, text, and alt simultaneously. Regular shorthands don't need *; regular Wrap only needs to place content in the last element.

📖 Summary


📝 Exercises

  1. Basic (Difficulty ⭐): In your HTML file, write a standalone <p>Hello World</p>, select it, press Shift+Alt+, to trigger Wrap, type div.wrapper, and press Enter. Verify the expansion result is <div class="wrapper"><p>Hello World</p></div>. If incorrect, check whether you forgot the >.

  2. Intermediate (Difficulty ⭐⭐): In an HTML file, write 3 standalone <li> elements (without ul). Use Wrap for batch wrapping: (a) select all 3 lines; (b) type ul.nav> and verify the output; (c) then use section.hero> to verify multi-line wrapping (no * needed — the selection itself means "as children of ul"). Record the expansion results of 3 Wrap operations.

  3. Challenge (Difficulty ⭐⭐⭐): In your HTML file, write a blog post fragment (<h1>...</h1> + <p>...</p> + <p>...</p>). Use 3 Wrap operations to transform it into a complete blog card structure: 1st Wrap header>h1 + 2nd Wrap article.content>(p)* + 3rd Wrap section.blog-post>. Record the final result of the 3 Wrap operations (should be a 3-layer nested structure) and write a "Wrap vs. Manual Wrapping" speed comparison report.

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%

🙏 帮我们做得更好

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

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