Style at the speed of thought. A CSS framework whose utility class names are official Emmet abbreviations.
If you already write Emmet in your editor, you already know the class names. df is display: flex. p16 is padding: 16px. fsz16 is font-size: 16px. No invented vocabulary.
Grid layout is the one exception: Emmet has no container / row / col snippets, so the grid follows Bootstrap 5.
- Emmet-native names: Class names are verified against
[email protected]. Where the old sheet used a made-up name, the official abbreviation is now canonical; the old name is kept as a comma alias when it does not steal a real Emmet snippet. - Literal numbers:
p4ispadding: 4px, the same CSS Emmet emits. Not a 0.25rem design scale. - Bootstrap grid:
.container→.row→.col-*/.col-md-6, plus offsets, row-cols, and gutters. - Typeable responsive suffix:
df-md,col-md-6(Emmet markup cannot type@in a class). Legacydf@md/col@md-6still work. - Utilities win:
@layer reset, tokens, layout, components, animations, utilities. - No JS runtime. LightningCSS build.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./dist/emmetify.min.css">
<title>Emmetify</title>
</head>
<body class="p16">
<main class="container">
<div class="row g-4">
<div class="col-12 col-md-6 col-lg-4">
<h1 class="fsz30 fw700 c">Welcome to Emmetify</h1>
<p class="fsz16 c-g mt8">Type Emmet. Get CSS.</p>
</div>
<div class="col-12 col-md-6 col-lg-4">
<div class="p16 bgc bdrs8 c-w tac">Sidebar</div>
</div>
</div>
</main>
</body>
</html>git clone https://github.com/Patchmonk/Emmetify.git
cd Emmetify
npm install
npm run buildnpm run build— full sheet, grid-only (dist/emmetify.grid.min.css), anddist/parts/*.min.css(one file per module)npm run build -- --only=reset,tokens,grid— extra mix →dist/emmetify.custom.cssnpm run build -- --px=8,16,24,32— add extra px sizes (Emmetp32= 32px)npm run write-framework— regenerate utility CSS from official Emmet rules (optional)npm run watch— rebuild on change
Ground truth is [email protected] stylesheet expansion.
- Property + number = px (exactly what Emmet emits)
p4→padding: 4pxfsz16/fz16→font-size: 16pxm-8→margin: -8px(leading hyphen = negative)
- Keyword values concatenate (colon forms are not valid class names)
- Cheat sheet
jc:sb→ classjcsb td:n→tdn,bds:ds→bdsds,fxw:w→fxww
- Cheat sheet
- Auto is
-am-a→margin: auto- Centering:
m0-a→margin: 0 auto
Neverma-0— that is Emmetmax-width: 0.
- Responsive:
-sm|-md|-lg|-xl|-xxlsuffix, Bootstrap 5 breakpoints. Legacy@bpis aliased.
| Class | Official meaning | What people guess | Use instead |
|---|---|---|---|
fxw |
flex-wrap: nowrap |
wrap | fxww |
fxwr |
flex-wrap: wrap |
wrap-reverse | fxwwre |
fxn / fx-n |
flex: nowrap |
flex:none | fxnone |
jcsa |
justify-content: start |
space-around | jcspar |
jcse |
justify-content: stretch |
space-evenly | jcsev |
ais |
align-items: start |
stretch | aiste |
posst |
position: static |
sticky | pos-sticky |
tal |
text-align-last: left |
text-align:left | ta / ta-l |
bn |
bottom: none |
border:none | bdn |
bds |
border-style: none |
solid | bdss |
bs |
block-size |
border-style | bdss |
mw100p |
min-width: 100% |
max-width | maw100p |
zi10 |
not z-index | z-index: 10 | z10 |
cg |
column-gap |
cursor:grab | cur-grab |
pe / pe4 |
padding-inline-end |
pointer-events | pointer-events-none (pe-n kept as extra) |
wa |
width: auto |
word-break:all | wobba |
g4 |
gap: 4px |
Bootstrap gutter | row gutters are g-4 (hyphen) |
g-4 |
Bootstrap gutter 1.5rem | Emmet gap: -4px |
use g4 for gap |
us-a |
user-select: auto |
all | us-all |
ovs |
overflow-style: scrollbar |
overflow:scroll | ov-s |
animdel100 |
animation-delay: 100px |
100ms | animdel100ms |
ord1 |
Emmet emits order: 1px |
order:1 | class ord1 is unitless order: 1 (CSS-correct) |
| Suffix | Min-width |
|---|---|
| (none) | 0 (mobile-first) |
-sm |
576px |
-md |
768px |
-lg |
992px |
-xl |
1200px |
-xxl |
1400px |
Examples: df-md, d-none-lg, col-sm-6, col-md-4, offset-lg-2.
Emmet has no grid-class snippets. This is framework convention.
<div class="container">
<div class="row g-4">
<div class="col-12 col-md-6 col-lg-4">Column 1</div>
<div class="col-12 col-md-6 col-lg-4">Column 2</div>
<div class="col-12 col-lg-4">Column 3</div>
</div>
</div>| Class | Role |
|---|---|
.container |
Centered, max-width steps 540 → 720 → 960 → 1140 → 1320 |
.container-fluid / .container-f |
100% width |
.container-{sm|md|lg|xl|xxl} |
100% until that breakpoint, then follows the container |
.row |
Flex wrap, negative margin = gutter |
.col |
Equal flex columns |
.col-auto |
Hug content |
.col-{1–12} |
12-column span |
.col-{bp}-{1–12} |
Span from that breakpoint up |
.offset-{0–11} / .offset-{bp}-{0–11} |
Left offset |
.row-cols-{1–6} / .row-cols-{bp}-{n} |
Equal columns per row |
.g-0….g-5 / .gx-* / .gy-* |
Gutters (--gutter-0…--gutter-5) |
Children of .row are selected with .row > * (not [class*="col"], which also matched trs-col).
Legacy col@md-6 is aliased to col-md-6.
| Class | CSS |
|---|---|
dn / d-none |
display: none |
db / d-block |
display: block |
di / d-inline |
display: inline |
dib / d-ib |
display: inline-block |
df / d-flex |
display: flex |
dif / d-if |
display: inline-flex |
dg / d-grid |
display: grid |
dig |
display: inline-grid |
dt dtc dtr dli dc |
table / table-cell / table-row / list-item / contents |
d-flex and d-none are themselves valid Emmet (d-flex → display: flex).
| Class | CSS |
|---|---|
fxdr / fxdc / fxdrr / fxdcr |
direction row / column / reverses |
fxww |
wrap |
fxwn / fxw |
nowrap |
fxwwre |
wrap-reverse |
aic aifs aife aib ais aie aiste |
align-items |
jcc jcsb jcspar jcsev jcfs jcfe |
justify-content |
fxg0 fxg1 fxsh0 fxsh1 |
grow / shrink |
fx1 fx-a fxnone |
flex 1 / auto / none |
g0…g160 cg* rg* |
gap / column-gap / row-gap in px |
Scale (px): 0 1 2 3 4 5 6 7 8 10 12 14 16 20 24 32 36 40 48 64 80 96 128 160.
| Pattern | Meaning |
|---|---|
m* mt* mr* mb* ml* |
margin |
p* pt* pr* pb* pl* |
padding |
mbs mbe mis mie / pbs pbe pis pie |
logical (Emmet) |
pe4 |
padding-inline-end: 4px (same as pie4) |
m-a mt-a mla mra |
auto |
m0-a |
margin: 0 auto |
p16-0 / p0-16 |
padding: 16px 0 / 0 16px |
mx* my* px* py* |
axis extras (not Emmet; kept so old markup still works) |
| Class | CSS |
|---|---|
fsz16 / fz16 |
font-size: 16px (fz is the Emmet 1 cheat-sheet alias) |
fw100…fw900 fwn fwb |
weight |
fsn fsi (fi alias) |
font-style |
ffss / ff-sans ffm / ff-mono ffs |
sans / mono / serif |
lh1 lh1.5 lh150p |
line-height |
lts* (ls* alias) |
letter-spacing |
ta ta-l tac tar taj ta-start ta-end |
text-align |
tal |
text-align-last: left |
ttu ttl ttc ttn |
text-transform |
tdn tdu tdo tdl |
text-decoration |
whsn whsnw whsp whspw whspl |
white-space |
wobba wobka wobn wowbw |
word-break / word-wrap |
tove tovc |
text-overflow |
.truncate .lc-2….lc-5 |
extras (no Emmet snippet) |
| Class | CSS |
|---|---|
bd / bd1…bd8 |
1–8px solid gray-300 (unified; bd1 is no longer gray-200) |
bdn |
border: none |
bdt* bdr* bdb* bdl* |
per side (bt* / bb* legacy) |
bdc* (bc* alias) |
border-color |
bdw* (bw* alias) |
border-width |
bdss bdsds bdsdt bdsdb |
solid / dashed / dotted / double |
bdrs4 (br4 alias) |
border-radius: 4px |
bdrs50p |
50% |
bdtlrs0 bdtrrs0 bdblrs0 bdbrrs0 |
corners |
bgc* c* |
background-color / color (token extras -suc -warn -dng) |
bgszcv bgszct bgsza |
background-size cover / contain / auto |
cur / curp / cu |
cursor: pointer |
cur-grab |
cursor: grab |
op0 op1 op.5 |
opacity 0 / 1 / 0.5 (legacy op50 = 0.5 still works) |
ovh ova ov-s ovv |
overflow |
bxshn bxsh-sm… |
box-shadow |
z0 z10 z-modal |
z-index (zi* alias) |
posa posr posf poss pos-sticky |
position |
trft trftx trfty |
translate centering (tf-* alias) |
.img-fluid, .media, .avatar / -sm -md -lg -xl, objf-*, objp-*, ar16-9 etc., .anim-fade-in and the other named keyframe helpers.
Animation longhands that are Emmet: animdel100ms, animdur300ms, animtfe, animici, animpsp, …
Type:
div.container.py16>div.df.aic.jcsb.p16.bgc.bdrs8.c-w.trs>div.df.aic.g8>img.avatar-md.ar1-1.objf-c[src="avatar.jpg"]+div>h3.fsz18.fw700.c-b{Jane Doe}+p.fsz14.c-g{Product Designer}^^button.cu.p8.px16.bgc-w.c.bdrs4.fw600.trs-col{Connect}
py16 / px16 / avatar-md / objf-c / ar1-1 are kept extras (no Emmet snippet). Everything else is official Emmet.
emmetify/
├── emmetify.css /* @layer + imports */
├── core/
│ ├── reset.css
│ └── tokens.css
├── utilities/
│ ├── display.css
│ ├── position.css
│ ├── sizing.css
│ ├── flexbox.css
│ ├── grid.css /* Bootstrap grid (layout layer) */
│ ├── spacing.css
│ ├── typography.css
│ ├── borders.css
│ └── effects.css
├── components/
│ └── media.css
└── modules/
└── animations.css
scripts/write-framework.mjs regenerates the utility sheets from the Emmet ruleset so scales stay complete.
- Every audited mismatch renamed to the official abbreviation.
- Old names kept as aliases unless they collide with a real Emmet snippet (those take the official meaning).
- Numeric utilities emit px, matching Emmet.
- Bootstrap 5 grid, containers, gutters, xxl columns,
row-cols,.row > *. - Responsive
*-md(and legacy@md). @layerutilities last..cgis only column-gap; grab iscur-grab.bd/bd1/bd2share gray-300.- Missing sizes used in docs (
w40,h160,fsz13,lh1.6,op80,px20, …) are included. - Source maps are emitted next to the CSS.
MIT © Emmetify CSS