cssfontparser
cssfontparser parses a CSS font shorthand string into a plain object with style, variant, weight, numeric pixel size, numeric pixel line height, and an array of font families. It can resolve em and percentage sizes against a parent font string, convert physical units using a supplied DPI, handle inherit, and serialize its result through toString(). The implementation is a dependency-free CommonJS module built around one regular expression and a module-level cache, with a grammar much narrower than a browser's current CSS parser.
cssfontparser is compact compatibility code, not a current CSS parser. Keep it for controlled legacy inputs, but choose a maintained CSS grammar tool when correctness, isolation of results, modern syntax, or typed modules matter.
Use it if
- You maintain code already built around cssfontparser's exact object shape and pixel conversion rules
- Your input is a controlled, old-style font shorthand containing simple ASCII family names
- You need em or percentage size resolution against one explicitly supplied parent shorthand
- A dependency-free CommonJS parser around 1.1 KB gzipped is more important than full CSS grammar coverage
- You parse untrusted or current CSS: the regex does not cover var(), calc(), CSS-wide keywords beyond inherit, system font keywords, escaped identifiers, global families added after CSS 2, or many valid Unicode family names
- You need active package maintenance: version 1.2.1 was published in May 2015, and the only default-branch commits since then added license files in 2022 rather than parser changes
- You cannot tolerate shared mutable results: a module-level cache returns the same object for repeated inputs, so changing a result can change what later callers receive
- You need TypeScript, ESM, or browser packaging metadata: the package offers only a CommonJS main file with no declarations, export map, or module build
- You need browser-accurate relative units: em and percentage sizes require a parent string, ex is accepted by the regex but has no conversion case, and rem, ch, viewport units, and modern functions are unsupported
Setup reality
Install with npm install cssfontparser and call the CommonJS default function. There are no dependencies, native builds, peer requirements, credentials, or config files. The parser accepts up to three positional arguments: the shorthand, an optional parent shorthand, and DPI, which defaults to 96. The parent is not a computed-style object; it must itself be a string this parser can understand. Without a parent, em and percentage sizes remain undefined even though the function can still return an object with a family. Physical units are converted to pixels with the DPI value, while unitless line-height is multiplied by the parsed font size. The narrow regular expression is the main surprise. Family text is limited largely to ASCII letters, spaces, hyphens, commas, and quotes; CSS functions, variables, escaped identifiers, digits in family names, and much modern syntax can fail. Invalid input usually returns undefined or null, so check the result before reading it. More importantly, results are cached and reused by reference. Treat them as immutable or clone the enumerable fields and family array before passing them to code that mutates data. The non-enumerable toString method closes over values assembled during parsing; changing fields after parsing does not reliably update serialized output. Serialization also normalizes generic family names, quotes names containing spaces, converts sizes to px, and omits normal or numeric 400 weight, so it is not a source-preserving formatter.
Patterns
Parse a basic font shorthandparse-font-shorthand
const parseFont = require('cssfontparser');
const font = parseFont('italic small-caps 700 16px/1.5 Georgia, serif');
// { style: 'italic', variant: 'small-caps', weight: '700',
// size: 16, lineHeight: 24, family: ['Georgia', 'serif'] }The result's toString method is non-enumerable, so deep equality and JSON output show only the data fields.
Check parsing before reading fieldsguard-invalid-input
const parsed = parseFont(input);
if (!parsed || typeof parsed.size !== 'number' || !parsed.family) {
throw new TypeError(`Unsupported font shorthand: ${input}`);
}Invalid syntax can return null or undefined, while a relative size without a parent can produce an object whose size is undefined.
Resolve em against a parent fontresolve-em-size
const child = parseFont('1.5em sans-serif', '16px serif');
// child.size === 24The second argument must be another shorthand string. Passing a numeric parent size or computed-style object is unsupported.
Resolve a percentage font sizeresolve-percent-size
const child = parseFont('75% Arial, sans-serif', '20px serif');
// child.size === 15Without the parent shorthand, the percentage cannot resolve and size is left undefined rather than causing the entire parse to fail.
Convert points using an explicit DPIconvert-physical-units
const printFont = parseFont('12pt serif', null, 192);
// printFont.size === 32DPI defaults to 96 when omitted. px ignores DPI, while pt, pc, mm, cm, and in use it for conversion.
Resolve unitless line-heightcompute-line-height
const font = parseFont('16px/1.25 Arial, sans-serif');
// font.lineHeight === 20A unitless line-height is multiplied by the parsed size. Unit-bearing line-height is converted through the same numeric helper as size.
Resolve the inherit shorthandinherit-parent-font
const inherited = parseFont('inherit', 'italic 14px Georgia, serif');
// { style: 'italic', size: 14, family: ['Georgia', 'serif'] }parseFont('inherit') without a parent returns undefined. The returned object is the cached parent parse result, not a clone.
Serialize the normalized resultserialize-normalized-font
const font = parseFont('italic 400 12px/2 Unknown Font, SANS-SERIF');
font.toString();
// italic 12px/24px "Unknown Font", sans-serifSerialization normalizes and converts values; it does not reproduce the source. Weight 400 is omitted and multiword families are quoted.
Clone a result before changing itavoid-cache-mutation
const parsed = parseFont('16px Arial, sans-serif');
const editable = {
...parsed,
family: parsed.family.slice(),
};
editable.size = 18;Repeated parses with the same input, parent, and DPI return the same cached object. Mutating parsed directly can affect later callers.
Recognize the built-in generic family setinspect-generic-families
const { generics } = require('cssfontparser');
if (generics[family.toLowerCase()]) {
console.log('classic generic family');
}The exported table contains only serif, sans-serif, cursive, fantasy, and monospace. Newer CSS generic families are absent.
Build output after editing parsed fieldsserialize-edited-copy
const parsed = parseFont('16px Arial, sans-serif');
const size = 18;
const family = parsed.family.map((name) =>
name.includes(' ') ? `"${name}"` : name
).join(', ');
const css = `${size}px ${family}`;Do not rely on parsed.toString() after changing parsed.size or other scalar fields because its output was assembled during the original parse.
Read the parsed family fallback orderparse-family-list
const { family } = parseFont('14px "Open Sans", Arial, sans-serif');
for (const candidate of family) {
console.log(candidate);
}Quotes are stripped later during serialization, but the parser's family array behavior is regex-driven and not a complete CSS string-token parser. Test unusual family names before relying on it.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| css-font-parser | npm | You specifically need a newer package dedicated to parsing the CSS font value |
| postcss-value-parser | npm | You need a maintained low-level value AST and will interpret font shorthand grammar yourself |
| css-tree | npm | You need spec-aware CSS parsing, validation, walking, and generation beyond one shorthand |