AniUI Academy

Serialise a style object to CSS text

easyDOM & Utilities+150 XPPractice

Server renderers, email builders and canvas-to-HTML exporters all need to print a style object as real CSS text. Two decisions define the behaviour: which numbers get px, and which entries are dropped.

Implement styleObjectToCss(style). Walk the object's own keys in insertion order. Skip any entry whose value is null, undefined or the empty string "". Convert each remaining key from camelCase to kebab-case by replacing each uppercase letter with a - and its lowercase form; a key beginning with -- is a custom property and is used exactly as written.

A numeric value has px appended, except for the five unitless properties opacity, zIndex, fontWeight, lineHeight and flexGrow, which are printed as the bare number. This applies to 0 too, so marginTop: 0 prints as margin-top: 0px. Any other value is printed with String(value).

Each declaration is printed as name: value; — one space after the colon and a trailing semicolon, including on the last one — and declarations are joined by a single space. An object with nothing to print returns the empty string "".

Arguments

styleRecord<string, string | number | null | undefined>
A React-style object whose keys are camelCase CSS properties (or --custom properties) and whose values are strings, numbers, or null/undefined to drop.

Returns

string — CSS text as a single line of name: value; declarations joined by a space. "" for an empty object.

Examples

styleObjectToCss({ color: "red" });
// => "color: red;"

A single declaration ends with a trailing semicolon.

styleObjectToCss({ fontSize: 14, lineHeight: 1.5 });
// => "font-size: 14px; line-height: 1.5;"

Numbers get px except for the handful of unitless properties.

styleObjectToCss({ color: null, display: undefined, width: "", height: "10px" });
// => "height: 10px;"

null, undefined and "" entries are dropped.

What it has to do

  • Convert camelCase keys to kebab-case, leaving --custom properties as written.
  • Append px to numeric values except for opacity, zIndex, fontWeight, lineHeight and flexGrow.
  • Skip entries whose value is null, undefined or "".
  • Print every declaration as name: value; and join them with a single space.
  • Return "" for an empty object.

Notes

  • The unitless list here is a trimmed version of React's internal isUnitlessNumber list — the ones users actually set in practice. React carries a much longer list for cases like flex, order and columnCount.
  • 0 still gets px because CSS lint rules let you drop units from zeros but 0px is never wrong; printing a bare 0 would turn line-height: 0 into something browsers interpret differently from a length.

Stuck? The javascript course covers everything this challenge needs.

Try it yourself
Loading playground...
5 tests · +150 XP

Discussion

Sign in to post
Sign in to join the conversation.Sign in

No comments yet. Be the first to say something.