Skip to main content
rbx-css maps CSS font properties to Roblox Font objects, combining font family, weight, and style into a single FontFace property.

Font family

CSS font families map to Roblox font asset paths.

Built-in fonts

input.css
.text-gotham {
  font-family: 'Gotham', sans-serif;
}

.text-roboto {
  font-family: 'Roboto', sans-serif;
}

.text-mono {
  font-family: monospace;
}
output.luau
rule1:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/GothamSSm.json"
))

rule2:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/Roboto.json"
))

rule3:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/RobotoMono.json"
))

Font family mapping table

CSS font-familyRoblox Font AssetNotes
gotham, gothamssmGothamSSmRoblox default UI font
builder sansBuilderSansRoblox’s branded font
source sans proSourceSansProOpen-source alternative
robotoRobotoGoogle’s font
montserratMontserratPopular web font
monospace (generic)RobotoMonoMonospace fallback
sans-serif (generic)GothamSSmSans-serif fallback
serif (generic)MerriweatherSerif fallback

Custom fonts

For fonts not in the mapping table, rbx-css assumes they exist in the Roblox fonts directory:
input.css
.text-custom {
  font-family: 'MyCustomFont';
}
output.luau
-- Assumes font exists at this path
rule:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/MyCustomFont.json"
))
Unknown font families emit a warning. Make sure the font exists in your Roblox project or use one of the built-in fonts.

Font weight

CSS font weights map to Roblox Enum.FontWeight values.

Numeric weights

input.css
.thin {
  font-weight: 100;
}

.regular {
  font-weight: 400;
}

.bold {
  font-weight: 700;
}

.black {
  font-weight: 900;
}
output.luau
rule1:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/GothamSSm.json",
  Enum.FontWeight.Thin
))

rule2:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/GothamSSm.json",
  Enum.FontWeight.Regular
))

rule3:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/GothamSSm.json",
  Enum.FontWeight.Bold
))

rule4:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/GothamSSm.json",
  Enum.FontWeight.Heavy
))

Named weights

input.css
.text {
  font-weight: normal;
  font-weight: bold;
  font-weight: lighter;
}
output.luau
-- 'normal' maps to Regular
rule:SetProperty("FontFace", Font.new(family, Enum.FontWeight.Regular))

-- 'bold' maps to Bold
rule:SetProperty("FontFace", Font.new(family, Enum.FontWeight.Bold))

-- 'lighter' / 'bolder' treated as Regular
rule:SetProperty("FontFace", Font.new(family, Enum.FontWeight.Regular))

Weight mapping table

CSS font-weightRoblox Enum.FontWeight
100, thinThin
200, extra-lightExtraLight
300, lightLight
400, normalRegular
500, mediumMedium
600, semi-boldSemiBold
700, boldBold
800, extra-boldExtraBold
900, blackHeavy

Font style

CSS font styles map to Roblox Enum.FontStyle values.
input.css
.normal {
  font-style: normal;
}

.italic {
  font-style: italic;
}
output.luau
rule1:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/GothamSSm.json",
  Enum.FontWeight.Regular,
  Enum.FontStyle.Normal
))

rule2:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/GothamSSm.json",
  Enum.FontWeight.Regular,
  Enum.FontStyle.Italic
))
CSS font-styleRoblox Enum.FontStyle
normalNormal
italicItalic
obliqueItalic (approximated)

Combined font properties

Font family, weight, and style are combined into a single FontFace property:
input.css
.heading {
  font-family: 'Gotham', sans-serif;
  font-weight: 700;
  font-style: italic;
}
output.luau
rule:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/GothamSSm.json",
  Enum.FontWeight.Bold,
  Enum.FontStyle.Italic
))

Shorthand font property

The CSS font shorthand is supported (parsed by lightningcss):
input.css
.text {
  font: italic 700 16px 'Gotham', sans-serif;
}
output.luau
-- Equivalent to:
rule:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/GothamSSm.json",
  Enum.FontWeight.Bold,
  Enum.FontStyle.Italic
))
rule:SetProperty("TextSize", 16)

Font size

Font size is a separate property from FontFace. See Properties - Font size.
input.css
.text {
  font-family: 'Gotham';
  font-size: 18px;
}
output.luau
rule:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/GothamSSm.json"
))
rule:SetProperty("TextSize", 18)

Font fallbacks

CSS font stacks (comma-separated lists) are evaluated left-to-right. rbx-css uses the first recognized font:
input.css
.text {
  font-family: 'CustomFont', 'Gotham', sans-serif;
}
output.luau
-- If 'CustomFont' is unknown, falls back to 'Gotham'
rule:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/GothamSSm.json"
))
-- Or if CustomFont is valid:
rule:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/CustomFont.json"
))
rbx-css picks the first font it recognizes in the stack. It doesn’t generate fallback logic at runtime like browsers do.

CSS variables for fonts

Font family tokens can be defined with CSS custom properties:
input.css
:root {
  --font-heading: 'Gotham';
  --font-body: 'Roboto';
}

.heading {
  font-family: var(--font-heading);
  font-weight: 700;
}

.body {
  font-family: var(--font-body);
}
output.luau
-- Token attributes
sheet:SetAttribute("font-heading", Font.new(
  "rbxasset://fonts/families/GothamSSm.json"
))
sheet:SetAttribute("font-body", Font.new(
  "rbxasset://fonts/families/Roboto.json"
))

-- Rules using tokens
rule1:SetProperty("FontFace", "$font-heading")
-- Note: weight is applied separately if specified in the rule

rule2:SetProperty("FontFace", "$font-body")

Unsupported font features

CSS PropertyReason
font-variantNo small-caps or variant support
font-stretchNo condensed/expanded support
font-kerningNo kerning control
font-feature-settingsNo OpenType feature access
@font-faceUse Roblox font assets instead

Font asset structure

Roblox font assets are JSON files defining font metadata:
-- rbxasset://fonts/families/GothamSSm.json structure:
{
  name = "Gotham SSm",
  faces = {
    { name = "Regular", weight = 400, style = "normal", ... },
    { name = "Bold", weight = 700, style = "normal", ... },
    { name = "Italic", weight = 400, style = "italic", ... },
    ...
  }
}
The Font.new() constructor selects the appropriate face based on weight and style.

Complete example

input.css
:root {
  --font-display: 'Gotham';
}

.heading {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 32px;
  font-style: normal;
}

.subheading {
  font-family: 'Source Sans Pro', sans-serif;
  font-weight: 600;
  font-size: 24px;
}

.body {
  font-family: 'Roboto', sans-serif;
  font-weight: 400;
  font-size: 16px;
  line-height: 1.5;
}

.code {
  font-family: monospace;
  font-size: 14px;
}
output.luau
-- Token
sheet:SetAttribute("font-display", Font.new(
  "rbxasset://fonts/families/GothamSSm.json"
))

-- .heading
rule1:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/GothamSSm.json",
  Enum.FontWeight.ExtraBold,
  Enum.FontStyle.Normal
))
rule1:SetProperty("TextSize", 32)

-- .subheading
rule2:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/SourceSansPro.json",
  Enum.FontWeight.SemiBold
))
rule2:SetProperty("TextSize", 24)

-- .body
rule3:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/Roboto.json",
  Enum.FontWeight.Regular
))
rule3:SetProperty("TextSize", 16)
rule3:SetProperty("LineHeight", 1.5)

-- .code
rule4:SetProperty("FontFace", Font.new(
  "rbxasset://fonts/families/RobotoMono.json"
))
rule4:SetProperty("TextSize", 14)

Build docs developers (and LLMs) love