Extending Emmet and VS Code — and discovering 415 CSS properties
Tags: javascript, webdev, showdev, css
Published: 2022-10-07 09:14:12

I use Emmet everyday. You might too, without even knowing — it's built-in to VS Code!
When you type `bdrs`, Emmet magically transforms that to `border-radius`. Etcetera.

**It saves you a lot of typing.**

But that’s not the only thing, I use Emmet for. I like to name my *custom properties* with **component-name** + **emmet-abbrevaiation**, so the property for `border-radius` for a component called “hero”, will be `--hero-bdrs`. It keeps the custom property-names short and concise.

Unforunately, Emmet isn't updated regularly — for instance, none of the **logical properties** that are now available in all browsers, are available in Emmet. 

In fact, there are almost **200 properties** missing. Luckily, we can easily extend Emmet.

----------
# Data

First, we need some data. Grab Emmet's [css.json](https://github.com/emmetio/emmet/blob/master/snippets/css.json), and MDN's [properties.json](https://github.com/mdn/data/tree/main/css/properties.json).
Place these files locally. We'll use a `Promise.all` to grab the array of files (we might need more later, so this is a safe way to do it):

```js
Promise.all(
  urls.map((url, index) => fetch(url)
    .then(r => r.json())
    .then(json => {
      const key = urls[index].split('.')[0];
      data[key] = json;
    })
    .catch(error => ({ error, url }))
  )
).then(() => {
  // Stuff here ...
})
```

Now, we have access to the data as `data.emmet` and `data.properties`.
The data in `data.properties` is our "master data", as this is a list of **all** CSS properties.
For the Emmet-data, we need to filter out all the "extra stuff" that Emmet provides, and only treat the data which matches a CSS property directly. In other words: we need to filter the data **and** remove old, rendundant stuff like `border-bottom-image` and `overflow-style`:

```js
const emmetMap = new Map();
for (const [key, value] of Object.entries(data.emmet)) {
  const [subkey, subvalue] = value.split(':')
  if (data.properties.hasOwnProperty(subkey)) {
    if (!emmetMap.has(subkey)) emmetMap.set(subkey, key);

  }
  else {
    delete data.emmet[key];
  }
}
```

Next, we iterate all CSS properties, and check, if it has a matching Emmet-entry. If not, we'll create our own Emmet-abbreviation based on the property-name.

For that, we split the key by `-`, so `padding-inline-end` becomes:
`['padding', 'inline', 'end']`

If the array has a `length` greater than 0, we'll grab the first letter of each entry, so we'll end up with `pie`. Yummy, that's a good abbreviation for `padding-inline-end`!

If the array does **not** have a length, we'll use the 3 first chars instead:
`key.slice(0, 3)`

Before we use the new key, we'll have to check if it exists already:

```js
const values = Array.from(emmetMap.values());
if (values.includes(emmetKey)) { ... }
```

If the key **does** exist already, we'll output it to the `console`. 
So ... we get 14 keys that exist already:


- **ac** accent-color
- **bdb** box-decoration-break
- **bd** box-direction
- **cp** clip-path
- **fs** font-smooth
- **fs** font-synthesis
- **mb** margin-block
- **mt** margin-trim
- **mb** mask-border
- **mr** mask-repeat
- **mt** mask-type
- **ml** max-lines
- **pb** padding-block
- **ta** touch-action

We **could** write some clever code to generate an alternative Emmet-key, but for such small amount, let's just change them manually, and add them to `emmet.json`:

```js
"acc": "accent-color",
"bodb": "box-decoration-break",
"bxd": "box-direction",
"clp": "clip-path",
"fsmo": "font-smooth",
"fsy": "font-synthesis",
"mab": "margin-block",
"mat": "margin-trim",
"msb": "mask-border",
"msr": "mask-repeat",
"mty": "mask-type",
"mal": "max-lines",
"pab": "padding-block",
"toa": "touch-action"
```

Let's run the code again, making sure there are **no unknown keys**.
Finally, if it's a **new** Emmet-key, we'll update `data.emmet` with the new entry:

`data.emmet[emmetKey] = key`

And in `data.properties`, we add a new `emmet`-entry per property:

`data.properties[key].emmet = emmetKey`

----------

Let's log the data, and see what we've accomplished:

```
console.log(data.properties)
console.log(data.emmet)
```

Now, just right-click on the object in Dev Tools, and chose "Copy object". You can also use a [console-script](https://codepo8.github.io/dearconsole/) to accomplish this. Paste it in your favourite editor (probably VS Code!) and save it.

----------

## Extending VS Code

… And speaking of VS Code. Let’s look into how we can extend the [Emmet-implementation](https://code.visualstudio.com/docs/editor/emmet), so it can use all the new abbreviations, we've created.

Rename the file to `snippets.json` and add some wrapper objects around the list of properties:

```
{
  "css": {
    "snippets": {
      "at": "animation-timeline",
      "all": "all",
      "ar": "aspect-ratio",
... etc ...
```

I had to add some entries to `settings.json` in VS Code, in order for it to recognize the new Emmet-snippets:

```js
"emmet.triggerExpansionOnTab": true,
"files.associations": {"*css": "css"},
"emmet.useInlineCompletions": true,
"emmet.extensionsPath": [
  "path-to-snippets.json"
]
```

Now, type `pie` and hit `Tab`:


![The new Emmet-snippet in action](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cgfv8wdixjvfq4ixbxlw.gif)

## Repo

I’ve added all the code and the new `snippets.json` in this repo:

https://github.com/madsstoumann/emmet-vscode

The greatest surprise of this project, was learning there are **415 CSS Properties!**

----------

## Complete Emmet CSS List

And here's the complete, updated list of Emmet abbreviations for CSS properties:

| Emmet   | Property                    |
| ------- | --------------------------- |
| acc     | accent-color                |
| ac      | align-content               |
| ai      | align-items                 |
| as      | align-self                  |
| at      | align-tracks                |
| all     | all                         |
| anim    | animation                   |
| animdel | animation-delay             |
| animdir | animation-direction         |
| animdur | animation-duration          |
| animfm  | animation-fill-mode         |
| animic  | animation-iteration-count   |
| animn   | animation-name              |
| animps  | animation-play-state        |
| animtf  | animation-timing-function   |
| at      | animation-timeline          |
| ap      | appearance                  |
| ar      | aspect-ratio                |
| azi     | azimuth                     |
| bf      | backdrop-filter             |
| bfv     | backface-visibility         |
| bg      | background                  |
| bga     | background-attachment       |
| bbm     | background-blend-mode       |
| bgcp    | background-clip             |
| bgc     | background-color            |
| bgi     | background-image            |
| bgo     | background-origin           |
| bgp     | background-position         |
| bgpx    | background-position-x       |
| bgpy    | background-position-y       |
| bgr     | background-repeat           |
| bgsz    | background-size             |
| bo      | block-overflow              |
| bs      | block-size                  |
| bd      | border                      |
| bb      | border-block                |
| bbc     | border-block-color          |
| bbs     | border-block-style          |
| bbw     | border-block-width          |
| bbe     | border-block-end            |
| bbec    | border-block-end-color      |
| bbes    | border-block-end-style      |
| bbew    | border-block-end-width      |
| bbs     | border-block-start          |
| bbsc    | border-block-start-color    |
| bbss    | border-block-start-style    |
| bbsw    | border-block-start-width    |
| bdb     | border-bottom               |
| bdbc    | border-bottom-color         |
| bdblrs  | border-bottom-left-radius   |
| bdbrrs  | border-bottom-right-radius  |
| bdbs    | border-bottom-style         |
| bdbw    | border-bottom-width         |
| bdcl    | border-collapse             |
| bdc     | border-color                |
| beer    | border-end-end-radius       |
| besr    | border-end-start-radius     |
| bdi     | border-image                |
| bio     | border-image-outset         |
| bir     | border-image-repeat         |
| bis     | border-image-slice          |
| bis     | border-image-source         |
| biw     | border-image-width          |
| bi      | border-inline               |
| bie     | border-inline-end           |
| bic     | border-inline-color         |
| bis     | border-inline-style         |
| biw     | border-inline-width         |
| biec    | border-inline-end-color     |
| bies    | border-inline-end-style     |
| biew    | border-inline-end-width     |
| bis     | border-inline-start         |
| bisc    | border-inline-start-color   |
| biss    | border-inline-start-style   |
| bisw    | border-inline-start-width   |
| bdl     | border-left                 |
| bdlc    | border-left-color           |
| bdls    | border-left-style           |
| bdlw    | border-left-width           |
| bdrs    | border-radius               |
| bdr     | border-right                |
| bdrc    | border-right-color          |
| bdrst   | border-right-style          |
| bdrw    | border-right-width          |
| bdsp    | border-spacing              |
| bser    | border-start-end-radius     |
| bssr    | border-start-start-radius   |
| bds     | border-style                |
| bdt     | border-top                  |
| bdtc    | border-top-color            |
| bdtlrs  | border-top-left-radius      |
| bdtrrs  | border-top-right-radius     |
| bdts    | border-top-style            |
| bdtw    | border-top-width            |
| bdw     | border-width                |
| b       | bottom                      |
| ba      | box-align                   |
| bodb    | box-decoration-break        |
| bxd     | box-direction               |
| bf      | box-flex                    |
| bfg     | box-flex-group              |
| bl      | box-lines                   |
| bog     | box-ordinal-group           |
| bo      | box-orient                  |
| bp      | box-pack                    |
| bxsh    | box-shadow                  |
| bxsz    | box-sizing                  |
| ba      | break-after                 |
| bb      | break-before                |
| bi      | break-inside                |
| cps     | caption-side                |
| cc      | caret-color                 |
| cl      | clear                       |
| cp      | clip                        |
| clp     | clip-path                   |
| c       | color                       |
| pca     | print-color-adjust          |
| cs      | color-scheme                |
| colmc   | column-count                |
| colmf   | column-fill                 |
| colmg   | column-gap                  |
| colmr   | column-rule                 |
| colmrc  | column-rule-color           |
| colmrs  | column-rule-style           |
| colmrw  | column-rule-width           |
| colms   | column-span                 |
| colmw   | column-width                |
| colm    | columns                     |
| con     | contain                     |
| cnt     | content                     |
| cv      | content-visibility          |
| coi     | counter-increment           |
| cor     | counter-reset               |
| cs      | counter-set                 |
| cur     | cursor                      |
| dir     | direction                   |
| d       | display                     |
| ec      | empty-cells                 |
| fil     | filter                      |
| fx      | flex                        |
| fxb     | flex-basis                  |
| fxd     | flex-direction              |
| fxf     | flex-flow                   |
| fxg     | flex-grow                   |
| fxsh    | flex-shrink                 |
| fxw     | flex-wrap                   |
| fl      | float                       |
| f       | font                        |
| ff      | font-family                 |
| ffs     | font-feature-settings       |
| fk      | font-kerning                |
| flo     | font-language-override      |
| fos     | font-optical-sizing         |
| fvs     | font-variation-settings     |
| fsz     | font-size                   |
| fsza    | font-size-adjust            |
| fsmo    | font-smooth                 |
| fst     | font-stretch                |
| fs      | font-style                  |
| fsy     | font-synthesis              |
| fv      | font-variant                |
| fva     | font-variant-alternates     |
| fvc     | font-variant-caps           |
| fvea    | font-variant-east-asian     |
| fvl     | font-variant-ligatures      |
| fvn     | font-variant-numeric        |
| fvp     | font-variant-position       |
| fw      | font-weight                 |
| fca     | forced-color-adjust         |
| gap     | gap                         |
| gd      | grid                        |
| ga      | grid-area                   |
| gac     | grid-auto-columns           |
| gaf     | grid-auto-flow              |
| gar     | grid-auto-rows              |
| gc      | grid-column                 |
| gce     | grid-column-end             |
| gcg     | grid-column-gap             |
| gcs     | grid-column-start           |
| gg      | grid-gap                    |
| gr      | grid-row                    |
| gre     | grid-row-end                |
| grg     | grid-row-gap                |
| grs     | grid-row-start              |
| gt      | grid-template               |
| gta     | grid-template-areas         |
| gtc     | grid-template-columns       |
| gtr     | grid-template-rows          |
| hp      | hanging-punctuation         |
| h       | height                      |
| hc      | hyphenate-character         |
| hyp     | hyphens                     |
| io      | image-orientation           |
| ir      | image-rendering             |
| ir      | image-resolution            |
| im      | ime-mode                    |
| il      | initial-letter              |
| ila     | initial-letter-align        |
| is      | inline-size                 |
| is      | input-security              |
| ins     | inset                       |
| ib      | inset-block                 |
| ibe     | inset-block-end             |
| ibs     | inset-block-start           |
| ii      | inset-inline                |
| iie     | inset-inline-end            |
| iis     | inset-inline-start          |
| iso     | isolation                   |
| jc      | justify-content             |
| ji      | justify-items               |
| js      | justify-self                |
| jt      | justify-tracks              |
| l       | left                        |
| lts     | letter-spacing              |
| lb      | line-break                  |
| lc      | line-clamp                  |
| lh      | line-height                 |
| lhs     | line-height-step            |
| lis     | list-style                  |
| lisi    | list-style-image            |
| lisp    | list-style-position         |
| list    | list-style-type             |
| m       | margin                      |
| mab     | margin-block                |
| mbe     | margin-block-end            |
| mbs     | margin-block-start          |
| mb      | margin-bottom               |
| mi      | margin-inline               |
| mie     | margin-inline-end           |
| mis     | margin-inline-start         |
| ml      | margin-left                 |
| mr      | margin-right                |
| mt      | margin-top                  |
| mat     | margin-trim                 |
| mas     | mask                        |
| msb     | mask-border                 |
| mbm     | mask-border-mode            |
| mbo     | mask-border-outset          |
| mbr     | mask-border-repeat          |
| mbs     | mask-border-slice           |
| mbs     | mask-border-source          |
| mbw     | mask-border-width           |
| mc      | mask-clip                   |
| mc      | mask-composite              |
| mi      | mask-image                  |
| mm      | mask-mode                   |
| mo      | mask-origin                 |
| mp      | mask-position               |
| msr     | mask-repeat                 |
| ms      | mask-size                   |
| mty     | mask-type                   |
| maf     | masonry-auto-flow           |
| ms      | math-style                  |
| mbs     | max-block-size              |
| mah     | max-height                  |
| mis     | max-inline-size             |
| mal     | max-lines                   |
| maw     | max-width                   |
| mbs     | min-block-size              |
| mih     | min-height                  |
| mis     | min-inline-size             |
| miw     | min-width                   |
| mbm     | mix-blend-mode              |
| of      | object-fit                  |
| op      | object-position             |
| off     | offset                      |
| oa      | offset-anchor               |
| od      | offset-distance             |
| op      | offset-path                 |
| op      | offset-position             |
| or      | offset-rotate               |
| op      | opa                         |
| ord     | order                       |
| orp     | orphans                     |
| ol      | outline                     |
| olc     | outline-color               |
| olo     | outline-offset              |
| ols     | outline-style               |
| ow      | outline-width               |
| ov      | overflow                    |
| oa      | overflow-anchor             |
| ob      | overflow-block              |
| ocb     | overflow-clip-box           |
| ocm     | overflow-clip-margin        |
| oi      | overflow-inline             |
| ow      | overflow-wrap               |
| ovx     | overflow-x                  |
| ovy     | overflow-y                  |
| ob      | overscroll-behavior         |
| obb     | overscroll-behavior-block   |
| obi     | overscroll-behavior-inline  |
| obx     | overscroll-behavior-x       |
| oby     | overscroll-behavior-y       |
| p       | padding                     |
| pab     | padding-block               |
| pbe     | padding-block-end           |
| pbs     | padding-block-start         |
| pb      | padding-bottom              |
| pi      | padding-inline              |
| pie     | padding-inline-end          |
| pis     | padding-inline-start        |
| pl      | padding-left                |
| pr      | padding-right               |
| pt      | padding-top                 |
| pgba    | page-break-after            |
| pgbb    | page-break-before           |
| pgbi    | page-break-inside           |
| po      | paint-order                 |
| per     | perspective                 |
| po      | perspective-origin          |
| pc      | place-content               |
| pi      | place-items                 |
| ps      | place-self                  |
| pe      | pointer-events              |
| pos     | position                    |
| q       | quotes                      |
| rsz     | resize                      |
| r       | right                       |
| rot     | rotate                      |
| rg      | row-gap                     |
| ra      | ruby-align                  |
| rm      | ruby-merge                  |
| rp      | ruby-position               |
| sca     | scale                       |
| sc      | scrollbar-color             |
| sg      | scrollbar-gutter            |
| sw      | scrollbar-width             |
| sb      | scroll-behavior             |
| sm      | scroll-margin               |
| smb     | scroll-margin-block         |
| smbs    | scroll-margin-block-start   |
| smbe    | scroll-margin-block-end     |
| smb     | scroll-margin-bottom        |
| smi     | scroll-margin-inline        |
| smis    | scroll-margin-inline-start  |
| smie    | scroll-margin-inline-end    |
| sml     | scroll-margin-left          |
| smr     | scroll-margin-right         |
| smt     | scroll-margin-top           |
| sp      | scroll-padding              |
| spb     | scroll-padding-block        |
| spbs    | scroll-padding-block-start  |
| spbe    | scroll-padding-block-end    |
| spb     | scroll-padding-bottom       |
| spi     | scroll-padding-inline       |
| spis    | scroll-padding-inline-start |
| spie    | scroll-padding-inline-end   |
| spl     | scroll-padding-left         |
| spr     | scroll-padding-right        |
| spt     | scroll-padding-top          |
| ssa     | scroll-snap-align           |
| ssc     | scroll-snap-coordinate      |
| ssd     | scroll-snap-destination     |
| sspx    | scroll-snap-points-x        |
| sspy    | scroll-snap-points-y        |
| sss     | scroll-snap-stop            |
| sst     | scroll-snap-type            |
| sstx    | scroll-snap-type-x          |
| ssty    | scroll-snap-type-y          |
| sit     | shape-image-threshold       |
| sm      | shape-margin                |
| so      | shape-outside               |
| ts      | tab-size                    |
| tbl     | table-layout                |
| ta      | text-align                  |
| tal     | text-align-last             |
| tcu     | text-combine-upright        |
| td      | text-decoration             |
| tdc     | text-decoration-color       |
| tdl     | text-decoration-line        |
| tds     | text-decoration-skip        |
| tdsi    | text-decoration-skip-ink    |
| tds     | text-decoration-style       |
| tdt     | text-decoration-thickness   |
| te      | text-emphasis               |
| tec     | text-emphasis-color         |
| tep     | text-emphasis-position      |
| tes     | text-emphasis-style         |
| ti      | text-indent                 |
| tj      | text-justify                |
| to      | text-orientation            |
| tov     | text-overflow               |
| tr      | text-rendering              |
| tsh     | text-shadow                 |
| tsa     | text-size-adjust            |
| tt      | text-transform              |
| tuo     | text-underline-offset       |
| tup     | text-underline-position     |
| t       | top                         |
| toa     | touch-action                |
| trf     | transform                   |
| tb      | transform-box               |
| trfo    | transform-origin            |
| trfs    | transform-style             |
| trs     | transition                  |
| trsde   | transition-delay            |
| trsdu   | transition-duration         |
| trsp    | transition-property         |
| trstf   | transition-timing-function  |
| tra     | translate                   |
| ub      | unicode-bidi                |
| us      | user-select                 |
| va      | vertical-align              |
| v       | visibility                  |
| whs     | white-space                 |
| wid     | widows                      |
| w       | width                       |
| wc      | will-change                 |
| wob     | word-break                  |
| wos     | word-spacing                |
| wow     | word-wrap                   |
| wm      | writing-mode                |
| z       | z-index                     |
| zom     | zoom                        |