VS 코드에서 사용자 지정 Emmet 조각 만들기

게시 됨: 2022-03-10
빠른 요약 ↬ 이 기사에서 Manuel은 왜 Emmet이 HTML 및 CSS 작성에 가장 좋아하는 생산성 도구 중 하나인지, 그리고 Visual Studio Code에서 사용자 지정 Emmet 스니펫을 생성하여 프런트 엔드 워크플로를 더욱 개선하는 방법을 설명합니다.

올해 초, 나는 새로운 웹 프로젝트를 시작할 때 사용하는 HTML 상용구를 내 블로그에 한 줄 한 줄 설명과 함께 공유했습니다. 내가 만드는 모든 웹사이트에서 주로 사용하는 대부분의 <head> 태그와 속성 모음입니다. 최근까지는 필요할 때마다 상용구를 복사하여 붙여넣었지만, 내가 선택한 편집기인 VS Code에 스니펫으로 추가하여 워크플로를 개선하기로 결정했습니다.

다음은 내가 만든 사용자 정의 스니펫의 빠른 데모입니다.

Visual Studio Code의 조각 및 약어

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의 기존 스니펫을 덮어쓰려면 다음 단계가 필요합니다.

  1. snippets.json 파일을 만들고 이 기본 JSON 구조를 추가하고 하드 디스크의 어딘가에 저장합니다.
     { "html": { "snippets": { } }, "css": { "snippets": { } } }
  2. VS Code 설정(Code → Preferences → Settings)을 열고 "Emmet Extensions Path"를 검색합니다.
  3. "항목 추가"를 클릭하고 이전에 생성한 snippets.json 파일을 저장한 폴더의 경로를 입력하고 "확인"을 누릅니다.

그게 다야 이제 htmlcss 개체에 속성을 추가하여 스니펫을 만들 준비가 되었습니다. 여기서 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> 내에서 마지막 탭 정지를 설정하고 기본 텍스트를 &copy 로 설정하십시오.

 {${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}})

마지막으로 링크와 링크 텍스트 "다른 페이지"가 ​​있는 세 개의 목록 항목을 더 추가합니다.

 (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. 작은
  2. 중간
  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 html>}

lang 속성이 있는 <html> 요소. lang 속성의 값은 VS 코드 설정(코드 → 기본 설정 → 설정)에서 변경할 수 있는 변수입니다.

 html[lang=${1}${lang}]

VS 코드 설정에서 "emmet 변수"를 검색하고 lang 변수를 변경하여 페이지의 기본 자연어를 변경할 수 있습니다. 여기에 사용자 정의 변수를 추가할 수도 있습니다.

VS Code에는 2개의 기본 변수가 있습니다. lang은 en으로 설정되고 charset은 UTF-8로 설정됩니다.

<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:vpviewport 에 대해 다른 설정을 사용하지 않기 때문에 필요하지 않은 두 개의 탭 정지를 생성합니다.

계속 진행하기 전에 이 스니펫을 덮어쓰자.

 { "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>

저에게는 이것이 완벽한 최소 디버깅 설정입니다.

상용구 매체

첫 번째 상용구는 빠른 데모에만 사용하지만 두 번째 상용구는 복잡한 페이지에 사용할 수 있습니다. 스니펫은 다음을 생성합니다.

  • 기본 사이트 구조,
  • viewport 메타 태그,
  • 페이지 제목,
  • .no-js / .js 클래스,
  • 외부 화면 및 인쇄 스타일시트,
  • descriptiontheme-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 Highlight 확장은 댓글을 정말 돋보이게 합니다.

확장 프로그램은 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');})+{}

두 개의 <link> 요소; 첫 번째는 기본 스타일시트에 대한 링크이고 두 번째는 인쇄 스타일시트에 대한 링크입니다.

 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>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>

완전한 상용구

전체 상용구는 두 번째 상용구와 유사합니다. 차이점은 추가 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 으로 설정합니다. topleft 속성에 두 개의 탭 정지가 있습니다.

 "sticky": "position: sticky;\ntop: ${1:0};\nleft: ${2:0};" 
div 요소에 적용된 3가지 CSS 스니펫 모두의 데모입니다.

사용자 스니펫

이 기사의 시작 부분에서 VS Code가 사용자 지정 스니펫도 제공한다고 언급했습니다. 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을 찾을 수 있습니다.

자원

  • 기본 CSS Emmet 스니펫
  • 기본 HTML Emmet 스니펫
  • 에밋 치트 시트
  • VS Code 문서의 Emmet