DEV Community

Cover image for FSCSS Shorthands: the full reference (1.2.5+)
FSCSS for FSCSS tutorial

Posted on Originally published at fscss.devtem.org

FSCSS Shorthands: the full reference (1.2.5+)

FSCSS 1.2.5 adds property shorthands: compile-time rewrites that turn short property names into standard longhand CSS before the stylesheet ever reaches the browser. No runtime cost for these names in production, since a compiled build just ships plain CSS.

This is the reference version: every shorthand group, what it expands to, and the processing order the compiler applies. For the story behind the release.

npm install fscss@1.2.5
Enter fullscreen mode Exit fullscreen mode
<script src="https://cdn.jsdelivr.net/npm/fscss@1.2.5/runtime.min.js" defer></script>
Enter fullscreen mode Exit fullscreen mode

ESM build: https://cdn.jsdelivr.net/npm/fscss@1.2.5/esm.min.js

Everything below is optional helpers. Longhand CSS is always valid inside an FSCSS file, shorthands just save you from typing the same pair of properties over and over.

Processing order

The compiler expands shorthands in a fixed order, which matters when a name could be read two ways:

  1. Side-scoped blocks (top| ... |)
  2. Axis and size
  3. Aliases and layout helpers
  4. Border and radius
  5. Background
  6. ratio-fit()

Longer, more specific names win over shorter ones. scroll-mx resolves before the plain mx, bg-size resolves before the plain size.

Quick example

FSCSS:

.card {
  stack: 12px;
  px: 16px;
  py: 14px;
  rounded: 12px;
  bg: #12121a;
  border-x: 1px solid rgba(255,255,255,.08);
  shadow: 0 8px 24px rgba(0,0,0,.35);
  max-w: 360px;
}

.card h3 {
  fs: 1.1rem;
  fw: 600;
  m: 0;
}
Enter fullscreen mode Exit fullscreen mode

Compiles to:

.card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-left: 16px;
  padding-right: 16px;
  padding-top: 14px;
  padding-bottom: 14px;
  border-radius: 12px;
  background: #12121a;
  border-left: 1px solid rgba(255,255,255,.08);
  border-right: 1px solid rgba(255,255,255,.08);
  box-shadow: 0 8px 24px rgba(0,0,0,.35);
  max-width: 360px;
}
.card h3 {
  font-size: 1.1rem;
  font-weight: 600;
  margin: 0;
}
Enter fullscreen mode Exit fullscreen mode

One stack: plus a handful of two-letter properties replaces nine lines of longhand.

Axis & spacing

Shorthand Expands to
inset-x / inset-y left+right / top+bottom
margin-x / mx margin-left + margin-right
margin-y / my margin-top + margin-bottom
padding-x / px padding-left + padding-right
padding-y / py padding-top + padding-bottom
gap-x / gap-y column-gap / row-gap
scroll-mx · scroll-my · scroll-px · scroll-py scroll-margin / scroll-padding axes
safe-x · safe-y · inset-safe padding/inset using env(safe-area-inset-*)
.overlay-side {
  pos: absolute;
  inset-x: 45px;  /* left + right only, top/bottom untouched */
  top: 0;
  h: 4px;
}
Enter fullscreen mode Exit fullscreen mode

That last point is the reason inset-x exists at all: inset: auto 45px sets all four sides, there's no native shorthand that means "left and right only, leave the rest alone."

Size

Shorthand Expands to
w / h width / height
min-w · max-w · min-h · max-h min/max width/height
size: A width: A; height: A
size: A B width: A; height: B
min-size / max-size same one- or two-value pattern
.icon  { size: 24px; }
.panel { size: 100% 200px; max-w: 480px; }
.thumb { min-size: 48px; max-size: 120px 80px; }
Enter fullscreen mode Exit fullscreen mode
.icon  { width: 24px; height: 24px; }
.panel { width: 100%; height: 200px; max-width: 480px; }
.thumb { min-width: 48px; min-height: 48px; max-width: 120px; max-height: 80px; }
Enter fullscreen mode Exit fullscreen mode

Property aliases

Single-property renames, not axis pairs:

m mt mb ml mr · p pt pb pl pr · fs fw ff lh ls · ta td tt ws tsh · ov ovx ovy · z op cur pe us pos · jc ai ac ji js as pi · fdir fwrap grow shrink basis · trans anim tf fil · shadow aspect obj-fit obj-pos

.title {
  fs: 1.25rem;
  fw: 700;
  lh: 1.2;
  ta: center;
}
Enter fullscreen mode Exit fullscreen mode

Layout helpers

Helper Result
center: x / y / other flex justify / align, or grid place-items center
stack: G / hstack: G column/row flex with that gap
fill / fill: fixed absolute or fixed, inset 0
abs-center absolute, inset 0, margin auto
truncate / line-clamp: N single-line ellipsis / multi-line clamp
cols / rows grid, a number becomes repeat(N, 1fr)
auto-fit: MIN repeat(auto-fit, minmax(MIN, 1fr))
glass: BLUR / ring: W backdrop-filter blur / box-shadow ring

Place, origin, object

  • place-x expands to justify-content plus justify-items
  • place-y expands to align-content plus align-items
  • origin-x / origin-y set an axis of transform-origin
  • object-x / object-y set an axis of object-position

Side-scoped blocks

A side block rewrites every known property inside it (padding, margin, border, border-width/style/color, inset, offset, paired border-radius corners) to apply to just that side:

.card {
  top| padding: 8px; border-width: 1px; |
  left| margin: 12px; |
}
Enter fullscreen mode Exit fullscreen mode

Supported sides: top, bottom, left, right, block-start, block-end, inline-start, inline-end.

Border & radius

  • border-x / border-y set a full border on left+right or top+bottom
  • border-t border-b border-l border-r for a single side
  • bw / bw-x / bw-t ... for border-width
  • bs-* for border-style, bc-* for border-color
  • rounded / radius for border-radius
  • rounded-t/b/l/r, rounded-tl and the other corners, radius-top and friends

Background

  • bg expands to background
  • bg-x / bg-y expand to background-position-x/y
  • bg-size-x / bg-size-y set a partial background-size
  • bg-color bg-image bg-repeat bg-pos bg-attachment bg-clip bg-origin bg-size map straight to their longhand names

ratio-fit()

.media-frame > img {
  inset: ratio-fit(16 / 9);
  obj-fit: cover;
}
Enter fullscreen mode Exit fullscreen mode

Expands into absolute positioning, inset: 0, margin: auto, aspect-ratio, and width/height caps that use container-query units, so the box holds its ratio while staying inside whatever it's placed in. The exact formula tracks the compiler implementation, so treat the expansion above as the shape rather than a byte-for-byte guarantee.

Seen in a real file

Template

body {
  ff: 'Inter', system-ui, sans-serif;
  bg: #e8eaf0;
  min-h: 100vh;
  center: both;
  gap: 40px;
  py: 40px;
  px: 20px;
  fwrap: wrap;
}

.icon-btn {
  size: 32px;
  rounded: 10px;
  bg: rgba(255,255,255,0.06);
  center: both;
}

.loan-card {
  mx: 22px;
  mb: 18px;
  rounded: 16px;
  px: 16px;
  py: 14px;
  hstack: 12px;
  ai: center;
}
Enter fullscreen mode Exit fullscreen mode

Full template: st-core.fscss / templates / budget-app.

Notes

  • Shorthands are optional. Longhand CSS is always valid in the same file.
  • Works through both the CLI and the browser runtime, but production should compile ahead of time rather than ship the runtime.
  • Older value-multiplexing helpers like %2() and %3() are unaffected and still work alongside 1.2.5 shorthands.
  • Full backward compatibility: nothing from pre-1.2.5 syntax breaks.

Tooling

The FSCSS VS Code extension highlights .fscss/.xfscss files, ships snippets for @define, @import, arrays and others, and adds an FSCSS: Compile command with compile-on-save. It needs the compiler installed separately (npm install -g fscss or as a project dependency), the extension itself just drives it.

Links

Top comments (0)