VSCodeでカスタムEmmetスニペットを作成する
公開: 2022-03-10 今年の初めに、ブログで行ごとの説明を含む新しいWebプロジェクトを開始するときに使用するHTMLボイラープレートを共有しました。 これは、私が構築するすべてのWebサイトで通常使用するほとんどの<head>
タグと属性のコレクションです。 最近まで、ボイラープレートは必要なときにコピーして貼り付けるだけでしたが、選択したエディターであるVSCodeにスニペットとして追加することでワークフローを改善することにしました。
VisualStudioCodeのスニペットと略語
VS Codeには、Emmetが提供するカスタムユーザースニペットとHTMLおよびCSSスニペットと略語が組み込まれています。
たとえば、HTMLドキュメントにp>a{Sign Up}
と入力し、 EnterキーまたはTabキーを押すと、Emmetはそれを次のマークアップに変換します。
<p><a href="">Sign Up</a></p>
注:略語構文の使用方法については、Emmetのドキュメントにアクセスしてください。
この特定の略語が定期的に必要な場合は、ワークフローをさらに改善するためにスニペットとして保存できます。
{ "html": { "snippets": { "signup": "p>a{Sign Up}" } } }
これで、 signup
と入力して、 EnterキーまたはTabキーを押すと、同じ結果が得られます。 次のセクションでは、スニペットを作成する方法について説明します。
Emmetには、デフォルトで多数のHTMLスニペットが付属しています。 たとえば、 !
HTMLドキュメントの基本構造を作成します。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> </body> </html>
これはすばらしいことですが、要素と属性を削除または追加してこのスニペットを適応させる場合は、それを上書きして独自のスニペットを作成する必要があります。
スニペットの作成と上書き
独自のEmmetスニペットを作成したり、VS Codeで既存のスニペットを上書きしたりする場合は、次の手順が必要です。
- snippets.jsonファイルを作成し、この基本的なJSON構造を追加して、ハードディスクのどこかに保存します。
{ "html": { "snippets": { } }, "css": { "snippets": { } } }
- VS Code設定を開き([コード]→[設定]→[設定])、「EmmetExtensionsPath」を検索します。
- 「アイテムの追加」をクリックし、前に作成したsnippets.jsonファイルを保存したフォルダーへのパスを入力して、「OK」を押します。
それでおしまい。 これで、 html
オブジェクトとcss
オブジェクトにプロパティを追加してスニペットを作成する準備が整いました。ここで、 key
はスニペットの名前であり、 value
は省略形または文字列です。
私のカスタムHTMLスニペットのいくつか
スニペットの作成について詳しく説明し、HTMLボイラープレートのスニペットを作成した方法を説明する前に、まず、作成した小さいながらも便利なスニペットでウォームアップしましょう。
遅延読み込み
箱から出して、 img
の省略形がありますが、遅延ロードされた画像の省略形はありません。 デフォルトの省略形を使用して、必要な属性と属性値を角かっこで囲んで追加するだけです。
{ "html": { "snippets": { "img:l": "img[width height loading='lazy']" } } }
img:l
+ Enter / Tabは、次のマークアップを作成するようになりました。
<img src="" alt="" width="" height="" loading="lazy">
ページ
私が作成するほとんどのページは、 <header>
、 <main>
、 <footer>
のランドマークと<h1>
で構成されています。 カスタムpage
の省略形を使用すると、その構造をすばやく作成できます。
"snippets": { "page": "header>h1^main+footer{${0:©}}" }
page
+ Enter / Tabは、次のマークアップを作成します。
<header> <h1></h1> </header> <main></main> <footer>©</footer>
その略語はかなり長いので、それをより小さなビットに分解しましょう。
壊す
<header>
要素と子<h1>
を作成します。
header>h1
上に移動して<header>
のレベルに戻り、 <main>
<footer>
を作成します。
^main+footer
<footer>
内の最後のタブストップを設定し、デフォルトのテキストを©
に設定します。
{${0:©}}
ナビゲーション
省略形nav
は、デフォルトで<nav>
の開始タグと終了タグを作成するだけですが、通常必要なのは、ネストされた<ul>
、 <li>
要素とリンク( <a>
)を持つ<nav>
です。 ページに複数の<nav>
要素がある場合は、たとえばaria-label
を使用して、それらにもラベルを付ける必要があります。
"nav": "nav[aria-label='${1:Main}']>ul>(li>a[aria-current='page']{${2:Current Page}})+(li*3>a{${0:Another Page}})"
それはワイルドに見えるので、もう一度分解してみましょう。
壊す
aria-label
属性とネストされた<ul>
を持つ<nav>
要素から始めます。 ${1:Main}
は、属性に「Main」というテキストを入力し、カーソルを属性値に移動して作成時に強調表示することにより、属性値にタブストップを作成します。
nav[aria-label='${1:Main}']>ul
次に、ネストされたリンクを持つ4つのリストアイテムを作成します。 最初の項目は、 aria-current="page"
を使用してアクティブなページをマークするため、特別です。 別のタブストップを作成し、リンクに「現在のページ」というテキストを入力します。
(li>a[aria-current='page']>{${2:Current Page}})
最後に、リンクとリンクテキスト「別のページ」を含む3つのリストアイテムを追加します。
(li*3>a>{${0:Another Page}})
私たちの適応の前に、私たちはこれを手に入れました:
<-- Before: nav + TAB/Enter --> <nav></nav>
今、私たちはこれを手に入れます:
<-- After: nav + TAB/Enter --> <nav aria-label="Main"> <ul> <li><a href="" aria-current="page">Current Page</a></li> <li><a href="">Another Page</a></li> <li><a href="">Another Page</a></li> <li><a href="">Another Page</a></li> </ul> </nav>
スタイル
デフォルトstyle
の省略形は、 <style>
の開始タグと終了タグのみを作成しますが、通常、 <style>
要素を使用する場合は、何かをすばやくテストまたはデバッグしたいので、これを行います。
<style>
タグにいくつかのデフォルトルールを追加しましょう。
"style": "style>{\\* { box-sizing: border-box; \\}}+{\n${1:*}:focus \\{${2: outline: 2px solid red; }\\} }+{\n${0}}"
壊す
一部の文字(たとえば、 $
、 *
、 {
、または}
)は、 \\
を使用してエスケープする必要があります。
style>{\\* { box-sizing: border-box; \\}}
\n
改行を作成し、 ${1:*}
は最初のタブストップをセレクター*
に配置します。
{\n${1:*}:focus \\{${2: outline: 2px solid red; }\\}}
- 前:
<style><style>
- 後:
<style> * { box-sizing: border-box; }
*:focus { outline: 2px solid red; } </style>
了解しました。十分なウォーミングアップです。 複雑なスニペットを作成しましょう。 最初は、ボイラープレート用に1つのスニペットを作成したかったのですが、さまざまなニーズに対応する3つの略語を作成しました。
- 小さい
- 中くらい
- 満杯
ボイラープレートスモール
これは簡単なデモの定型文であり、次のように作成されます。
- 基本的なサイト構造、
-
viewport
メタタグ、 - ページタイトル、
-
<style>
要素、 -
<h1>
。
{ "!": "{<!DOCTYPE html>}+html[lang=${1}${lang}]>(head>meta:utf+meta:vp+{}+title{${2:New document}}+{}+style)+body>(h1>{${3: New Document}})+{${0}}" }
壊す
doctypeの文字列:
{<!DOCTYPE html>}
lang
属性を持つ<html>
要素。 lang
属性の値は、VSコード設定([コード]→[設定]→[設定])で変更できる変数です。
html[lang=${1}${lang}]
VS Code設定で「emmet変数」を検索し、 lang
変数を変更することで、ページのデフォルトの自然言語を変更できます。 ここにカスタム変数を追加することもできます。
<head>
には、 charset
メタタグ、 viewport
メタタグ、 <title>
、および<style>
タグが含まれます。 {}
は新しい行を作成します。
(head>meta:utf+meta:vp+{}+title{${2:New document}}+{}+style)
これが私たちに何を与えるかを最初に簡単に見てみましょう。
<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>New document</title> </head> </html>
見た目は問題ありませんが、 meta:utf
の省略形はHTMLでcharset
を定義する古い方法を作成し、 meta:vp
はviewport
に別の設定を使用しないため必要のない2つのタブストップを作成します。
先に進む前に、これらのスニペットを上書きしましょう。
{ "meta:vp": "meta[name=viewport content='width=device-width, initial-scale=1']", "meta:utf": "meta[charset=${charset}]" }
最後になりましたが、 <body>
要素、デフォルトのテキストを含む<h1>
、その後に最後のタブストップが続きます。
body>(h1>{${3: New Document}})+{${0}}
最終的な定型文:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>New document</title> <style> * { box-sizing: border-box; } *:focus { outline: 2px solid red; } </style> </head> <body> <h1> New Document</h1> </body> </html>
私にとって、これは完璧な最小限のデバッグ設定です。
ボイラープレートミディアム
最初のボイラープレートは簡単なデモにのみ使用しますが、2番目のボイラープレートは複雑なページに使用できます。 スニペットは以下を作成します。
- 基本的なサイト構造、
-
viewport
メタタグ、 - ページタイトル、
-
.no-js
/.js
クラス、 - 外部画面と印刷スタイルシート、
-
description
とtheme-color
メタタグ、 - ページ構造。
{ "!!": "{<!DOCTYPE html>}+html[lang=${1}${lang}].no-js>{<!-- TODO: Check lang attribute --> }+(head>meta:utf+meta:vp+{}+title{${1: Change me}}+{}+(script[type=\"module\"]>{document.documentElement.classList.replace('no-js', 'js');})+{}+link:css+link:print+{}+meta[name=\"description\"][content=\"${2: Change me (up to ~155 characters)}\"]+{<!-- TODO: Change page description --> }+meta[name=\"theme-color\"][content=\"${2:#FF00FF}\"])+body>page" }
ええ、私は知っています、それはぎこちないように見えます。 それを分析しましょう。
壊す
doctype
とroot要素は最初の例と似ていますが、追加no-js
クラスと、必要に応じてlang
属性を変更するように通知するコメントがあります。
{<!DOCTYPE html>}+html[lang=${1}${lang}].no-js>{ }
TODOハイライト拡張機能はコメントを本当にポップにします。
<head>
には、 charset
メタタグ、 viewport
メタタグ、 <title>
が含まれます。 {}
は新しい行を作成します。
(head>meta:utf+meta:vp+{}+title{${1: Change me}}+{}
JavaScriptの行を含むスクリプト。 JSモジュールサポートでマスタードをカットしています。 ブラウザがJavaScriptモジュールをサポートしている場合、それは最新のJavaScript(モジュール、ES 6構文、フェッチなど)をサポートしているブラウザであることを意味します。 私はほとんどのJSをこれらのブラウザーにのみ出荷し、JavaScriptがアクティブなときにコンポーネントのスタイルが異なる場合は、CSSでjs
クラスを使用します。
(script[type=\"module\"]>{document.documentElement.classList.replace('no-js', 'js');})+{}
2つの<link>
要素。 最初のリンクはメインスタイルシートにリンクし、2番目のリンクは印刷スタイルシートにリンクします。
link:css+link:print+{}
ページの説明:
meta[name=\"description\"\][content=\"${2: Change me (up to ~155 characters)}\"]+{ }
theme-color
メタタグ:
meta[name=\"theme-color\"\][content=\"${2:#FF00FF}\"])
body要素と基本的なページ構造:
body>page
最終的な定型文は次のようになります。
<!DOCTYPE html> <html lang="en" class="no-js"> <!-- TODO: Check lang attribute --> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title> Change me</title> <script type="module"> document.documentElement.classList.replace('no-js', 'js'); </script> <link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="print.css" media="print"> <meta name="description" content=" Change me (up to ~155 characters)"> <!-- TODO: Change page description --> <meta name="theme-color" content="#FF00FF"> </head> <body> <header> <h1></h1> </header> <main></main> <footer>©</footer> </body> </html>
フルボイラープレート
完全なボイラープレートは、2番目のボイラープレートに似ています。 違いは、追加のmeta
とscript
タグです。
スニペットは以下を作成します。
- 基本的なサイト構造、
-
viewport
メタタグ、 - ページタイトル、
-
js
/no-js
クラス、 - 外部画面と印刷スタイルシート、
-
description
とオープングラフメタタグ、 -
theme-color
メタタグ、 - 正規の
<link>
タグ、 - ファビコンタグ、
- ページ構造、
- <
script>
タグ。
{ "!!!": "{<!DOCTYPE html>}+html[lang=${1}${lang}].no-js>{<!-- TODO: Check lang attribute --> }+(head>meta:utf+meta:vp+{}+title{${1: Change me}}+{}+(script[type=\"module\"]>{document.documentElement.classList.replace('no-js', 'js');})+{}+link:css+link:print+{}+meta[property=\"og:title\"][content=\"${1: Change me}\"]+meta[name=\"description\"][content=\"${2: Change me (up to ~155 characters)}\"]+meta[property=\"og:description\"][content=\"${2: Change me (up to ~155 characters)}\"]+meta[property=\"og:image\"][content=\"${1:https://}\"]+meta[property=\"og:locale\"][content=\"${1:en_GB}\"]+meta[property=\"og:type\"][content=\"${1:website}\"]+meta[name=\"twitter:card\"][content=\"${1:summary_large_image}\"]+meta[property=\"og:url\"][content=\"${1:https://}\"]+{<!-- TODO: Change social media stuff --> }+{}+link[rel=\"canonical\"][href=\"${1:https://}\"]+{<!-- TODO: Change canonical link --> }+{}+link[rel=\"icon\"][href=\"${1:/favicon.ico}\"]+link[rel=\"icon\"][href=\"${1:/favicon.svg}\"][type=\"image/svg+xml\"]+link[rel=\"apple-touch-icon\"][href=\"${1:/apple-touch-icon.png}\"]+link[rel=\"manifest\"][href=\"${1:/my.webmanifest}\"]+{}+meta[name=\"theme-color\"][content=\"${2:#FF00FF}\"])+body>page+{}+script:src[type=\"module\"]" }
この信じられないほど長いスニペットはこれを作成します:
<!DOCTYPE html> <html lang="en" class="no-js"> <!-- TODO: Check lang attribute --> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title> Change me</title> <script type="module"> document.documentElement.classList.replace('no-js', 'js'); </script> <link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="print.css" media="print"> <meta property="og:title" content=" Change me"> <meta name="description" content=" Change me (up to ~155 characters)"> <meta property="og:description" content=" Change me (up to ~155 characters)"> <meta property="og:image" content="https://"> <meta property="og:locale" content="en_GB"> <meta property="og:type" content="website"> <meta name="twitter:card" content="summary_large_image"> <meta property="og:url" content="https://"> <!-- TODO: Change social media stuff --> <link rel="canonical" href="https://"> <!-- TODO: Change canonical link --> <link rel="icon" href="/favicon.ico"> <link rel="icon" href="/favicon.svg" type="image/svg+xml"> <link rel="apple-touch-icon" href="/apple-touch-icon.png"> <link rel="manifest" href="/my.webmanifest"> <meta name="theme-color" content="#FF00FF"> </head> <body> <header> <h1></h1> </header> <main></main> <footer>©</footer> <script src="" type="module"></script> </body> </html>
カスタムCSSスニペット
完全を期すために、ここに私が使用しているCSSスニペットのいくつかを示します。
デバッグ
このスニペットは、カスタムオフセットを使用して5pxの赤いアウトラインを作成します。
"debug": "outline: 5px solid red;\noutline-offset: -5px;"
センタリング
display
をフレックスに設定し、その子アイテムを中央に配置するスニペット。
"center": "display: flex;\njustify-content: center;\nalign-items: center;"
粘着性
position
プロパティをsticky
に設定し、 top
とleft
のプロパティに2つのタブストップを設定します。
"sticky": "position: sticky;\ntop: ${1:0};\nleft: ${2:0};"
ユーザースニペット
この記事の冒頭で、VSCodeはカスタムスニペットも提供していると述べました。 Emmetスニペットとの違いは、省略形を使用できないことですが、タブストップを定義して内部変数を使用することもできます。
ユーザースニペットを最大限に活用する方法は、別の記事のトピックになる可能性がありますが、これが私が定義したカスタムCSSスニペットの例です。
"Visually hidden": { "prefix": "vh", "body": [ ".u-vh {", " position: absolute;\n white-space: nowrap;\n width: 1px;\n height: 1px;\n overflow: hidden;\n border: 0;\n padding: 0;\n clip: rect(0 0 0 0);\n clip-path: inset(50%);\n margin: -1px;", "}" ], "description": "A utility class for screen reader accessible hiding." }
このスニペットは、CSSルールを作成するだけでなく、 vh
と入力してEnterキーまたはTabキーを押すと宣言ブロック全体を作成します。
.u-vh { position: absolute; white-space: nowrap; width: 1px; height: 1px; overflow: hidden; border: 0; padding: 0; clip: rect(0 0 0 0); clip-path: inset(50%); margin: -1px; }
最後の言葉
これらのスニペットの作成には時間がかかりますが、Emmetを個人の好みに合わせてカスタマイズし、反復的なタスクを自動化し、長期的に時間を節約できるため、努力する価値があります。
使用しているスニペットを確認したいので、コメントで共有してください。 私の設定を使用したい場合は、GitHubで私の最終的なsnippets.jsonを見つけることができます。
資力
- デフォルトのCSSEmmetスニペット
- デフォルトのHTMLEmmetスニペット
- エメットチートシート
- VSCodeドキュメントのEmmet