Creazione di frammenti Emmet personalizzati in VS Code
Pubblicato: 2022-03-10 All'inizio di quest'anno, ho condiviso lo standard HTML che mi piace usare quando inizio nuovi progetti web con spiegazioni riga per riga sul mio blog. È una raccolta di tag e attributi principalmente <head> che di solito utilizzo su ogni sito Web che creo. Fino a poco tempo, copiavo e incollavo semplicemente il boilerplate ogni volta che ne avevo bisogno, ma ho deciso di migliorare il mio flusso di lavoro aggiungendolo come snippet a VS Code, l'editor di mia scelta.
Snippet e abbreviazioni nel codice di Visual Studio
VS Code è integrato con frammenti utente personalizzati e frammenti e abbreviazioni HTML e CSS forniti da Emmet.
Ad esempio, se digiti p>a{Sign Up} in un documento HTML e premi Invio o Tab , Emmet lo trasformerà nel seguente markup:
<p><a href="">Sign Up</a></p>Nota : visita i documenti di Emmet per imparare a usare la sintassi delle abbreviazioni.
Se abbiamo bisogno regolarmente di questa specifica abbreviazione, possiamo salvarla come snippet per migliorare ulteriormente il nostro flusso di lavoro.
{ "html": { "snippets": { "signup": "p>a{Sign Up}" } } } Ora possiamo digitare signup e premere Invio o Tab e otterremo lo stesso risultato. Spiegherò come creare frammenti nella prossima sezione.
Emmet viene fornito con un sacco di frammenti di codice HTML per impostazione predefinita. Ad esempio, ! crea la struttura di base di un documento 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>È fantastico, ma se vogliamo adattare questo snippet rimuovendo o aggiungendo elementi e attributi, dobbiamo sovrascriverlo e creare il nostro snippet.
Creazione e sovrascrittura di frammenti
Se vogliamo creare i nostri frammenti di Emmet o sovrascrivere quelli esistenti in VS Code, sono necessari i seguenti passaggi:
- Crea un file snippets.json , aggiungi questa struttura JSON di base e salvala da qualche parte sul tuo disco rigido.
{ "html": { "snippets": { } }, "css": { "snippets": { } } } - Apri le impostazioni del codice VS (Codice → Preferenze → Impostazioni) e cerca "Percorso estensioni Emmet".

- Fai clic su "Aggiungi elemento", inserisci il percorso della cartella in cui hai salvato il file snippets.json che hai creato in precedenza e premi "OK".

Questo è tutto. Ora siamo pronti per creare snippet aggiungendo proprietà agli oggetti html e css dove la key è il nome dello snippet e il value un'abbreviazione o una stringa.
Alcuni dei miei frammenti HTML personalizzati
Prima di approfondire la creazione di snippet e mostrarti come ho creato uno snippet per il mio boilerplate HTML, scaldiamoci prima con alcuni piccoli ma utili snippet che ho creato.
Caricamento pigro
Fuori dagli schemi, c'è un'abbreviazione img , ma non ce n'è per le immagini caricate pigramente. Possiamo utilizzare l'abbreviazione predefinita e aggiungere semplicemente gli attributi aggiuntivi e i valori degli attributi di cui abbiamo bisogno tra parentesi quadre.
{ "html": { "snippets": { "img:l": "img[width height loading='lazy']" } } } img:l + Invio / Tab ora crea il seguente markup:
<img src="" alt="" width="" height="" loading="lazy">Pagina
La maggior parte delle pagine che creo sono costituite da <header> , <main> e <footer> punti di riferimento e da un <h1> . L'abbreviazione della page personalizzata mi consente di creare rapidamente quella struttura.
"snippets": { "page": "header>h1^main+footer{${0:©}}" } page + Invio / Tab crea il seguente markup:
<header> <h1></h1> </header> <main></main> <footer>©</footer>Quell'abbreviazione è piuttosto lunga, quindi scomponiamola in parti più piccole.
Guasto
Crea un elemento <header> e un figlio <h1> .
header>h1 Spostati in alto, torna al livello di <header> e crea un <footer> che segua <main> .
^main+footer Imposta il punto di tabulazione finale all'interno del <footer> e imposta il testo predefinito su © .
{${0:©}}Navigazione
L'abbreviazione nav crea solo un tag di inizio e fine <nav> per impostazione predefinita, ma quello di cui di solito ho bisogno è un <nav> con <ul> , <li> elementi e collegamenti nidificati ( <a> ). Se ci sono più elementi <nav> su una pagina, dovrebbero anche essere etichettati, ad esempio usando aria-label .
"nav": "nav[aria-label='${1:Main}']>ul>(li>a[aria-current='page']{${2:Current Page}})+(li*3>a{${0:Another Page}})"Sembra selvaggio, quindi analizziamolo di nuovo.
Guasto
Iniziamo con un elemento <nav> con un attributo aria-label e un <ul> annidato. ${1:Main} popola l'attributo con il testo "Principale" e crea un punto di tabulazione sul valore dell'attributo spostando il cursore su di esso ed evidenziandolo al momento della creazione.
nav[aria-label='${1:Main}']>ul Quindi creiamo quattro voci di elenco con collegamenti nidificati. Il primo elemento è speciale perché contrassegna la pagina attiva usando aria-current="page" . Creiamo un altro punto di tabulazione e popola il collegamento con il testo "Pagina corrente".
(li>a[aria-current='page']>{${2:Current Page}})Infine, aggiungiamo altre tre voci di elenco con collegamenti e il testo del collegamento "Un'altra pagina".
(li*3>a>{${0:Another Page}})Prima dei nostri adattamenti, abbiamo ottenuto questo:
<-- Before: nav + TAB/Enter --> <nav></nav>Ora otteniamo questo:
<-- 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>Stile
L'abbreviazione di style predefinita crea solo il tag di inizio e fine <style> , ma di solito quando utilizzo l'elemento <style> lo faccio perché voglio testare o eseguire rapidamente il debug di qualcosa.
Aggiungiamo alcune regole predefinite al tag <style> :
"style": "style>{\\* { box-sizing: border-box; \\}}+{\n${1:*}:focus \\{${2: outline: 2px solid red; }\\} }+{\n${0}}"Guasto
Alcuni caratteri (ad esempio $ , * , { o } ) devono essere sottoposti a escape utilizzando \\ .
style>{\\* { box-sizing: border-box; \\}} \n crea un'interruzione di riga e ${1:*} posiziona la prima tabulazione sul selettore * .
{\n${1:*}:focus \\{${2: outline: 2px solid red; }\\}}- Prima :
<style><style> - Dopo :
<style> * { box-sizing: border-box; }
*:focus { outline: 2px solid red; } </style>
Va bene, abbastanza riscaldamento. Creiamo frammenti complessi. All'inizio volevo creare un singolo snippet per il mio boilerplate, ma ho creato tre abbreviazioni che soddisfano esigenze diverse.
- Piccolo
- medio
- Completo
Piastra Caldaia Piccola
Questo è un boilerplate per demo veloci, crea quanto segue:
- Struttura di base del sito,
- meta tag
viewport, - Titolo della pagina,
- elemento
<style>, - A
<h1>.
{ "!": "{<!DOCTYPE html>}+html[lang=${1}${lang}]>(head>meta:utf+meta:vp+{}+title{${2:New document}}+{}+style)+body>(h1>{${3: New Document}})+{${0}}" }Guasto
Una stringa con il doctype:
{<!DOCTYPE html>} L'elemento <html> con un attributo lang . Il valore dell'attributo lang è una variabile che puoi modificare nelle impostazioni del codice VS (Codice → Preferenze → Impostazioni).
html[lang=${1}${lang}] Puoi modificare la lingua naturale predefinita della pagina cercando "variabili emmet" nelle impostazioni di VS Code e modificando la variabile lang . Puoi anche aggiungere le tue variabili personalizzate qui.

Il <head> include il meta tag charset , il meta tag viewport , il tag <title> e <style> . {} crea una nuova riga.
(head>meta:utf+meta:vp+{}+title{${2:New document}}+{}+style)Diamo una prima rapida occhiata a ciò che questo ci offre.
<!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> Sembra a posto, ma l'abbreviazione meta:utf crea il vecchio modo in HTML per definire il charset e meta:vp crea due tabulazioni di cui non ho bisogno perché non uso mai un'impostazione diversa per il viewport .

Sovrascriviamo questi frammenti prima di andare avanti.
{ "meta:vp": "meta[name=viewport content='width=device-width, initial-scale=1']", "meta:utf": "meta[charset=${charset}]" } Ultimo ma non meno importante, l'elemento <body> , un <h1> con testo predefinito, seguito dal punto di tabulazione finale.
body>(h1>{${3: New Document}})+{${0}}La targa finale:
<!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>Per me, questa è la configurazione di debug minima perfetta.
Caldaia media
Mentre utilizzo il primo boilerplate solo per demo veloci, il secondo boilerplate può essere utilizzato per pagine complesse. Lo snippet crea quanto segue:
- Struttura di base del sito,
- meta tag
viewport, - Titolo della pagina,
- classi
.no-js/.js, - Schermi esterni e fogli di stile di stampa,
-
descriptione meta tagtheme-color, - Struttura della pagina.
{ "!!": "{<!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" }Sì, lo so, sembra incomprensibile. Analizziamolo.
Guasto
Il doctype e l'elemento root sono come nel primo esempio, ma con una classe no-js aggiuntiva e un commento che mi ricorda di cambiare l'attributo lang , se necessario.
{<!DOCTYPE html>}+html[lang=${1}${lang}].no-js>{ }L'estensione TODO Highlight rende il commento davvero pop.

Il <head> include il meta tag charset , il meta tag viewport , <title> . {} crea una nuova riga.
(head>meta:utf+meta:vp+{}+title{${1: Change me}}+{} Uno script con una riga di JavaScript. Sto tagliando la senape al supporto del modulo JS. Se un browser supporta moduli JavaScript, significa che è un browser che supporta JavaScript moderno (ad esempio moduli, sintassi ES 6, fetch e così via). Spedisco la maggior parte dei JS solo a questi browser e utilizzo la classe js in CSS, se lo stile di un componente è diverso, quando JavaScript è attivo.
(script[type=\"module\"]>{document.documentElement.classList.replace('no-js', 'js');})+{} Due elementi <link> ; il primo si collega al foglio di stile principale e il secondo a un foglio di stile di stampa.
link:css+link:print+{}La descrizione della pagina:
meta[name=\"description\"\][content=\"${2: Change me (up to ~155 characters)}\"]+{ } Il meta tag theme-color :
meta[name=\"theme-color\"\][content=\"${2:#FF00FF}\"])L'elemento body e la struttura di base della pagina:
body>pageIl boilerplate finale si presenta così:
<!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>Piastra Caldaia Piena
Il boilerplate completo è simile al secondo boilerplate; le differenze sono meta tag aggiuntivi e un tag script .
Lo snippet crea quanto segue:
- Struttura di base del sito,
- meta tag
viewport, - Titolo della pagina,
- classi
js/no-js, - Schermi esterni e fogli di stile di stampa,
-
descriptione meta tag del grafico aperto, - meta tag
theme-color, - canonico
<link>tag, - tag Favicon,
- struttura della pagina,
- tag <
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\"]" }Questo frammento incredibilmente lungo crea questo:
<!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>Snippet CSS personalizzati
Per completezza, ecco alcuni dei frammenti CSS che sto usando.
Debug
Questo frammento crea un contorno rosso di 5px con un offset personalizzato.
"debug": "outline: 5px solid red;\noutline-offset: -5px;"Centraggio
Uno snippet che imposta la display su flex e centra gli elementi figlio.
"center": "display: flex;\njustify-content: center;\nalign-items: center;"Appiccicoso
Imposta la proprietà position su sticky , con due punti di tabulazione nella proprietà in top e a left .
"sticky": "position: sticky;\ntop: ${1:0};\nleft: ${2:0};" div .Snippet utente
All'inizio di questo articolo, ho menzionato che VS Code fornisce anche frammenti personalizzati. La differenza rispetto ai frammenti di Emmet è che non puoi utilizzare abbreviazioni, ma puoi anche definire punti di tabulazione e utilizzare variabili interne.
Come ottenere il meglio dagli snippet utente potrebbe essere un argomento per un altro articolo, ma ecco un esempio di uno snippet CSS personalizzato che ho definito:
"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." } Questo snippet non crea solo regole CSS, ma un intero blocco di dichiarazione quando vh e premiamo Invio o 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; }Parole finali
Ci vuole del tempo per creare questi frammenti, ma ne vale la pena perché puoi personalizzare Emmet in base alle tue preferenze personali, automatizzare le attività ripetitive e risparmiare tempo a lungo termine.
Mi piacerebbe vedere quali snippet usi, quindi condividili con noi nei commenti. Se vuoi usare le mie impostazioni, puoi trovare il mio snippets.json finale su GitHub.
Risorse
- Snippet CSS Emmet predefiniti
- Snippet HTML Emmet predefiniti
- Cheat sheet di Emmet
- Emmet nei documenti VS Code
