Emmet: Balance, Jump, and Select
In lessons 14–15 you learned Expand and Wrap — Emmet's two core "input" actions. But in real development, you still need to edit after expanding — changing the content of 5
<li>items, adding comments, removing outer tags. This lesson teaches Emmet's "editing trio": Balance / Next Edit Point / Select Item, plus Toggle Comment and Remove Tag. These 5 actions let you continue accelerating 3–5x after expansion.
1. What You'll Learn
- Balance / Go to Matching Pair: Jump to matching HTML tags (or CSS brackets), supporting inward and outward bidirectional navigation
- Next/Previous Edit Point: Navigate between multiple tabstops (editable points) after Emmet expansion
- Select Item: Select the current element at progressively fine-grained levels (tag name → full attribute → attribute value → distinct class → entire element), without crossing elements
- Toggle Comment: Switch between HTML comments
<!-- -->and CSS comments/* */(context-aware) - Remove Tag: Strip the outer tag while preserving content (for renaming or shell removal)
2. A Frontend Developer's Real Story
(1) Pain Point: After Expanding 100 Lines of HTML, Finding the Place to Edit Takes 30 Seconds
Alice has written the HTML container for a blog post page:
<article>
<header>
<h1>Hello World</h1>
<time>2026-07-31</time>
</header>
<section>
<p>...</p>
<p>...</p>
</section>
<footer>
<address>...</address>
</footer>
</article>
She now needs to make 3 bulk replacements:
- Change
<h1>Hello World</h1>to<h1>Hello Emmet</h1> - Add one line of lorem ipsum placeholder text to each of the 2
<p>tags - Add a comment to
<footer>
Her workflow:
- Find
<h1>:Ctrl+F→ typeHello World→ replace withHello Emmet(5 seconds) - Find 1st
<p>:Ctrl+F→ replace (5 seconds); find 2nd<p>:Ctrl+Fagain (5 seconds) - Find
<footer>:Ctrl+F→ add comment (5 seconds)
Total: 20 seconds, 9 Ctrl+F operations. Alice thinks: HTML is inherently a tree structure — there should be "structure-based navigation" shortcuts. Move the cursor to <h1>, press a single key to jump directly to </h1>, press a key to jump to the outer <header>... Emmet should have these "tree structure shortcuts".
(2) The Emmet Editing Trio Solution
Emmet's 5 editing actions are "tree structure shortcuts" — turning the HTML/CSS tree structure into your navigation tool.
Alice's solution:
- Balance: Cursor inside
<h1>, pressCtrl+Alt+Bto select up to</h1>closing tag → 2 seconds - Next Edit Point: After expanding
ul>li*3, pressCtrl+Alt+→to jump to each<li>'s content position → 5 seconds - Select Item: Cursor on
<p>, pressShift+Ctrl+.to select the next<p>→ 3 seconds - Toggle Comment: Cursor on
<footer>, pressCtrl+/to add<!-- -->comment → 1 second - Remove Tag: Cursor on
<h1>, pressShift+Ctrl+;to delete<h1>but keep "Hello World" → 2 seconds
Total: 13 seconds, 5 shortcut operations. 35% faster than Ctrl+F replacement, with zero false replacements (Ctrl+F can easily match multiple locations).
(3) Benefits
The editing trio reduces "post-expansion editing" time from 20 seconds to 13 seconds, and more importantly reduces misoperations — Ctrl+F replacement can easily skip or over-replace; Emmet's structural navigation moves along the HTML tree, never misfiring. After mastering these 5 actions, Alice's total editing time for a 5-paragraph article page drops from 5 minutes to 2 minutes.
3. Core Definition of the 5 Editing Actions
Emmet provides 5 "editing acceleration" actions covering the 5 most common post-expansion operations: tag jumping, tabstop navigation, element selection, comment toggling, and outer tag removal.
| Action | Purpose | Use Case |
|---|---|---|
| Balance | Select content (inward/outward balance) | Select current tag content / outer |
| Go to Matching Pair | Jump to matching tag | Move to </tag> or <tag> |
| Next/Previous Edit Point | Jump to next/previous tabstop | Navigate editable positions after expansion |
| Select Item | Select next/previous element with same name | Batch-select similar elements |
| Toggle Comment | Toggle comments | HTML/CSS smart commenting |
| Remove Tag | Strip outer tag | Remove shell, keep content |
4. Trigger Key Comparison Across 4 Editors
The 5 actions have significantly different trigger keys across 4 major editors because these are relatively new actions and implementation progress varies by editor. Key fact: VSCode has only 1 default keybinding for Emmet's built-in actions — Tab triggers Expand Abbreviation (lesson 14). All other Emmet actions (Balance / Wrap / Select Item / Remove Tag, etc.) have no default shortcut in VSCode and must be triggered via the Command Palette or custom keybindings.json.
| Action | VSCode | WebStorm | Sublime | Atom |
|---|---|---|---|---|
| Expand Abbreviation | Tab (default, lesson 14) |
Tab |
Ctrl+E |
Tab |
| Balance | None (Command Palette / custom keybindings.json) | Ctrl+] |
Ctrl+D |
Ctrl+Alt+B |
| Go to Matching Pair | None (Command Palette / custom keybindings.json) | Ctrl+M |
Ctrl+Alt+J |
Ctrl+Alt+J |
| Next Edit Point | None (Command Palette / custom keybindings.json) | Ctrl+Alt+→ |
Ctrl+Alt+→ |
Ctrl+Alt+→ |
| Select Item | None (Command Palette / custom keybindings.json) | Shift+Alt+. |
Shift+Ctrl+. |
Shift+Ctrl+. |
| Toggle Comment | No Emmet default (VSCode native Ctrl+/ comments current line) |
Ctrl+/ |
Ctrl+/ |
Ctrl+/ |
| Remove Tag | None (Command Palette / custom keybindings.json) | Ctrl+Shift+Delete |
Ctrl+Shift+; |
Ctrl+Shift+; |
Ctrl+Alt+B / Shift+Ctrl+. / Shift+Ctrl+;, etc.) must be explicitly declared in keybindings.json with commands like "command": "editor.emmet.action.balance" / "editor.emmet.action.selectItem" / "editor.emmet.action.removeTag". First-time use should start with the Command Palette (Ctrl+Shift+P → Emmet: Balance, etc.) — this both verifies editor support for the action and reveals the exact command name (which you then write into keybindings.json).
5. Mermaid Diagram: Editor Cursor Movement Path
The diagram below shows the cursor navigation path between editable points (tabstops) after Emmet expands ul>li*3.
graph TB
Start([User types ul>li*3<br>Presses Tab to expand]) --> Expand[Emmet expands 4 lines of HTML]
Expand --> S1[tabstop 1:<br>Content position of first li in ul]
S1 -->|Press Ctrl+Alt+→| S2[tabstop 2:<br>Content position of second li in ul]
S2 -->|Press Ctrl+Alt+→| S3[tabstop 3:<br>Content position of third li in ul]
S3 -->|Press Ctrl+Alt+→| End([Expansion end point:<br>After ul closing tag])
S1 -->|Press Ctrl+Alt+←| Start
S2 -->|Press Ctrl+Alt+←| S1
S3 -->|Press Ctrl+Alt+←| S2
End -->|Press Ctrl+Alt+←| S3
style Start fill:#3b82f6,color:#fff
style Expand fill:#8b5cf6,color:#fff
style S1 fill:#10b981,color:#fff
style S2 fill:#10b981,color:#fff
style S3 fill:#10b981,color:#fff
style End fill:#ef4444,color:#fff
ul>li*3, there are 3 tabstops (each li's content position) + 1 end point (after </ul>). Next Edit Point jumps between these one by one. Backward jumps to the previous point, Forward jumps to the next. Notably: this is NOT "pressing Tab" — pressing Tab in VSCode after expansion is "indentation" or "accept Emmet expansion" (if still at the original shorthand), but to continue navigating tabstops after expansion, use Ctrl+Alt+→ instead of Tab.
6. Hands-On Examples
The following 5 examples cover the core scenarios of the editing trio + Toggle Comment + Remove Tag.
▶ Example: Balance — Jump to Matching <div> Tag (Difficulty ⭐)
The most common "tag navigation" — cursor inside <div>, press Balance to select content, press again to select the entire tag.
Original code:
<div class="container">
<p>Hello World</p>
</div>
Steps:
- Place cursor anywhere inside the content area of
<p>Hello World</p> - Press
Ctrl+Alt+Bonce → selectsHello World(content) - Press
Ctrl+Alt+Bagain → selects<p>Hello World</p>(entire p tag) - Press
Ctrl+Alt+Bagain → selects the entire<div>and all its content - Continue pressing
Ctrl+Alt+B→ selection expands outward level by level (outward balance)
Press again (Shift+Ctrl+Alt+B) → selection contracts inward (inward balance)
Output:
TEXT 📖 Display onlyExplanation: Balance's "bidirectional balancing" is a unique Emmet feature — most editors only support "outward expansion", but Emmet also supports inward contraction. This "adjustable selection size" design makes Balance a versatile tool for HTML editing: select 1 word, select 1 tag, select 1 container, select 1 section — adjust level by level with each Balance press. **Important detail**: Emmet's Balance is not "cursor movement" — it's "selection change". The cursor stays in place, but the selected range expands or shrinks. If you only want to "jump" without "selecting", use Go to Matching Pair.
▶ Example: Next Edit Point — Jumping Tabstops After Expansion (Difficulty ⭐⭐)
After expanding ul>li*3, press Ctrl+Alt+→ to jump to each li's content position.
Original code:
ul>li*3
Steps:
- Press Tab to trigger Expand → 4 lines of HTML appear
- Cursor is at tabstop 1 (inside the first li)
- Press
Ctrl+Alt+→→ jump to tabstop 2 (inside the second li) - Press
Ctrl+Alt+→→ jump to tabstop 3 (inside the third li) - Press
Ctrl+Alt+→→ jump to the end point (after</ul>)
Expanded HTML:
<ul>
<li>|</li>
<li>|</li>
<li>|</li>
</ul>
Output:
TEXT 📖 Display onlyExplanation: Lesson 14 on Expand Abbreviation mentioned that "expansion includes tabstops" — but didn't explain how to navigate them. Next Edit Point is the dedicated action for "jumping to the next tabstop". `Ctrl+Alt+→` is forward, `Ctrl+Alt+←` is backward. **Why not use the Tab key?** Because after expansion completes, VSCode treats Tab as "indentation" (the cursor is already at an "editable position" inside the li's content), so it won't trigger Emmet navigation again. To "jump between tabstops", use `Ctrl+Alt+→`. This is Emmet's key design decision separating "input triggering" (Tab) from "editing navigation" (Ctrl+Alt+→).
▶ Example: Select Item — Progressive Granularity Selection (Difficulty ⭐⭐)
HTML contains a <p> with a class; the cursor is on the text. Press Select Item to progressively expand the selection — only within the current element, never jumping to adjacent elements.
Original code:
<p class="fruit">Apple</p>
Steps:
- Place cursor on the
Appletext inside<p class="fruit">Apple</p> - Press
Shift+Ctrl+.once → selectsApple(text node) - Press again → selects
fruit(distinct class name) - Press again → selects
class="fruit"(attribute value) - Press again → selects
class="fruit"(full attribute) - Press again → selects the entire
<p class="fruit">Apple</p>(entire element)
Output:
TEXT 📖 Display onlyExplanation: Select Item's "expanding selection" works progressively deeper **only within the current element** — from text → distinct class → attribute value → full attribute → entire element (official docs: "expands current selection to its parent item"). It does **not cross elements** — to jump from `<p>Apple</p>` to the next `<p>Banana</p>` for batch selection, use VSCode's `Ctrl+F2` (Change All Occurrences) or multi-cursor (`Ctrl+D` for next, `Ctrl+Shift+L` for all with same name) — those are native IDE features, not Emmet. **`Shift+Ctrl+.` is forward (outward expansion)**, `Shift+Ctrl+,` is backward (inward contraction). Similar behavior in CSS: selector → property → value; useful for "quickly selecting a single CSS property line" scenarios. This "progressive granularity expansion" mimics JetBrains IDE's Extend Selection (W/A style).
▶ Example: Toggle Comment — Switch Comments On/Off (Difficulty ⭐)
Cursor on the <footer> tag in HTML, press Ctrl+/ to add <!-- --> comment.
Original code (no comment):
<footer>
<address>contact@example.com</address>
</footer>
Steps:
- Place cursor anywhere on the
<footer>tag - Press
Ctrl+/→ the entire<footer>tag is wrapped with<!-- -->
Expanded:
<!-- <footer>
<address>contact@example.com</address>
</footer> -->
Press Ctrl+/ again → comment removed (restores original HTML)
Output:
TEXT 📖 Display onlyExplanation: Toggle Comment's "context awareness" is what distinguishes Emmet from regular editor commenting. Ordinary `Ctrl+/` only comments the current line; Emmet's Toggle Comment **recognizes the current context** — in HTML it comments the entire tag (since HTML comments can span lines), in CSS it comments the current rule or property. This "context awareness" makes Toggle Comment more useful than the IDE's built-in commenting — fewer keystrokes. **Note**: Toggle Comment is similarly context-aware in CSS — when the cursor is on the full `padding: 10px;` line, `Ctrl+/` comments the entire `padding: 10px;`; when the cursor is on the word `padding`, `Ctrl+/` still comments `padding: 10px;` (the entire property). Similarly in HTML — cursor anywhere in `<p>` comments the entire `<p>...</p>`.
▶ Example: Remove Tag — Strip Outer Tag, Keep Content (Difficulty ⭐⭐)
Cursor on <h1>, press Shift+Ctrl+; to delete <h1></h1> but keep the text content.
Original code:
<h1>Hello World</h1>
Steps:
- Place cursor on the
<h1>tag - Press
Shift+Ctrl+;→ deletes<h1>and</h1>, keeps "Hello World"
Expanded:
Hello World
Compound scenario: stripping nested outer tags
Original code:
<section class="hero">
<h1>Welcome</h1>
</section>
Steps:
- Place cursor on the
<section>tag - Press
Shift+Ctrl+;→ deletes<section>and</section>, keeps<h1>Welcome</h1>
Expanded:
<h1>Welcome</h1>
Output:
TEXT 📖 Display onlyExplanation: Remove Tag's "shell removal, keep content" is the most concise of Emmet's editing actions — one keypress strips the outer tag. Common scenarios: ① design revision — the original `<header>` container is no longer wanted, but the `<h1>` text inside needs to be preserved; ② temporary debugging — strip the outer layer to inspect styles; ③ refactoring — reduce DOM nesting depth. Note: Remove Tag doesn't strip multiple layers at once — to strip 3 layers of nesting (div > section > h1), press `Shift+Ctrl+;` 3 times consecutively. The semicolon key (`;`) in `Shift+Ctrl+;` is a "macro command" key in many editors — corresponding to Emmet's internal `removeTag` command.
7. Decision Tree for Choosing Among the 5 Actions
In real development, the 5 actions often need to be combined. Here's a decision tree:
| Scenario | Recommended Action | Reason |
|---|---|---|
Want to jump to </tag> to see the closing tag |
Go to Matching Pair |
Jump only, no selection |
Want to select the entire <tag> to copy it |
Balance |
Selection expands 1 level |
Want to bulk-replace 5 <p> elements |
Select Item |
Select elements with same name one by one |
Want to comment out a <div> |
Toggle Comment |
Context-aware smart commenting |
Want to temporarily strip outer <div> for debugging |
Remove Tag |
Shell removal, keep content |
| Want to locate editable positions after expansion | Next Edit Point |
Jump to tabstops |
❓ FAQ
<section> ends — use Go to Matching Pair to jump there; you want to copy the entire <section>...</section> block — use Balance to select it. Both are common; learn both.Ctrl+Alt+→ jumps to the next tabstop, but wouldn't pressing Tab after expansion be simpler?Ctrl+Alt+→ to jump to the next editable point. If you want to use Tab to jump tabstops, you need emmet.triggerExpansionOnTab set to true in settings.json (on by default), but this only applies "before expansion" — after expansion, Tab no longer carries "jump tabstop" semantics.<p> vs <p>), not by class or id. So <p class="a"> and <p class="b"> are both treated as "same-name elements" by Select Item. To select by class, use VSCode's "Change All Occurrences" (Ctrl+F2) — that's a native IDE feature, not something Emmet provides.Ctrl+Z undo will restore it. So the "regret" operation after Remove Tag is Ctrl+Z. If you frequently need "strip + restore" operations, consider using the reverse of Wrap (Remove Tag then Wrap) — but this is rarely needed in practice, so Remove Tag is usually paired with the undo key.📖 Summary
- Editing trio: Balance (selection change) / Next Edit Point (tabstop jumping) / Select Item (same-name element selection)
- Toggle Comment: Comments entire HTML tags, entire CSS property lines (context-aware)
- Remove Tag: Strips outer tag but preserves content (shell removal), 1 press strips 1 layer
- Go to Matching Pair: Jump (no selection); Balance: Select (selection change)
- Trigger keys: VSCode
Ctrl+Alt+B/Ctrl+Alt+→/Shift+Ctrl+./Ctrl+//Shift+Ctrl+; - Next Edit Point ≠ Tab key: Tab is indentation/accept completion;
Ctrl+Alt+→is tabstop jumping
📝 Exercises
-
Basic (Difficulty ⭐): In your HTML file, write a nested structure (
<div><section><p>...</p></section></div>), place the cursor on<p>, and press Balance 5 times. Record each selection range ("content" → "p tag" → "section content" → "section tag" → "div tag"). Screenshot the selection changes. -
Intermediate (Difficulty ⭐⭐): In your HTML file, write 3
<p>elements (<p>One</p>,<p>Two</p>,<p>Three</p>). Place the cursor on the tag name of the first<p>and press Select Item 6 times (Shift+Ctrl+.). Record the specific content selected each time (tag name / full content / next tag name / next full content). Finally, use Toggle Comment to comment out all 3<p>elements as a group. -
Challenge (Difficulty ⭐⭐⭐): Write a complete HTML landing page container (article > header + section + footer with 3-level nesting). Optimize it using 5 actions in combination: (a) Expand
article>header>h1+section.content>p*3+footer.address; (b) Next Edit Point to jump to each<p>and fill in content; (c) Balance to select the entire article tag and copy it; (d) Toggle Comment to comment out the footer; (e) Remove Tag to temporarily strip the article and inspect styles (use Ctrl+Z to undo). Record the trigger sequence and final state for all 5 actions, and write an "Editing Trio Workflow" vs. "Ctrl+F Replacement" efficiency comparison report.