npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@k9kbdev/roblox-css

v0.1.1

Published

CSS-to-Roblox UI translation middleware — write web-style props, get native Roblox primitives

Readme

roblox-css

Write CSS. Get Roblox UI.

License: LGPL-3.0

A CSS-to-Roblox UI translation middleware for roblox-ts. Write familiar web-style style props and get native Roblox engine primitives (UDim2, UICorner, UIListLayout, etc.) automatically.

What Problem Does This Solve?

Building UI in Roblox requires manually wiring up UDim2 sizes, parenting constraint instances (UICorner, UIPadding, UIListLayout), and juggling imperative property sets. roblox-css lets you write this instead:

import { Box, Text, webStyle } from "roblox-css";

const card = webStyle({
  width: "200px",
  height: "auto",
  padding: "16px",
  borderRadius: "12px",
  backgroundColor: "#1a1a2e",
  display: "flex",
  flexDirection: "column",
  gap: "8px",
});

// In your component:
<Box style={card}>
  <Text style={webStyle({ color: "white", fontSize: "18px" })}>
    Hello, Roblox!
  </Text>
</Box>

The webStyle() function translates CSS properties into Roblox instance properties and child constraint elements. The wrapper components (Box, Text, Button, etc.) spread the result onto native Roblox instances.

Installation

npm install roblox-css

Peer Dependencies

Required:

  • @rbxts/react (>=17.0.0)

Optional (only needed for motion primitives):

  • @rbxts/ripple (>=0.8.0)
  • @rbxts/services

Rojo Configuration

Add roblox-css to your Rojo project file:

{
  "ReplicatedStorage": {
    "roblox-css": {
      "$path": "node_modules/roblox-css/src"
    }
  }
}

Primitives

| Component | HTML Equivalent | Roblox Instance | |:---|:---|:---| | <Box> | <div> | <frame> | | <Text> | <span> / <p> | <textlabel> | | <Button> | <button> | <textbutton> | | <Image> | <img> | <imagelabel> | | <Input> | <input> | <textbox> | | <ScrollBox> | <div style="overflow:auto"> | <scrollingframe> |

HTML-Like Aliases

For developers who prefer a more familiar web API, we export capitalized HTML element aliases that map directly to our base primitives.

| Alias Component | Underlying Primitive | Default Styling | |:---|:---|:---| | <Div> | <Box> | None | | <Span> | <InlineText> | None | | <P> | <Text> | fontSize: 16 | | <H1> | <Text> | fontSize: 32, fontWeight: "bold" | | <H2> | <Text> | fontSize: 24, fontWeight: "bold" | | <H3> | <Text> | fontSize: 18, fontWeight: "bold" |

Note: Due to TypeScript JSX constraints, you MUST use the capitalized versions (e.g. <Div> instead of <div>). Lowercase tags attempt to construct literal Roblox Instance classes that do not exist.

Motion Primitives

Declarative, variant-driven animation (inspired by Framer Motion):

| Component | Animates | |:---|:---| | <MotionBox> | <frame> | | <MotionText> | <textlabel> | | <MotionButton> | <textbutton> | | <MotionImage> | <imagelabel> | | <MotionUIScale> | <uiscale> |

import { MotionBox, webStyle } from "roblox-css";

<MotionBox
  style={webStyle({ width: "100px", height: "100px" })}
  animate={isHovered ? "hover" : "idle"}
  variants={{
    idle: { backgroundColor: "#1a1a2e", width: "100px" },
    hover: { backgroundColor: "#e94560", width: "120px" },
  }}
  transition={new TweenInfo(0.3, Enum.EasingStyle.Quad)}
/>

Requires @rbxts/ripple peer dependency.

Supported CSS Properties

Layout

| CSS Property | Roblox Mapping | |:---|:---| | width, height | Size (UDim2) | | minWidth, maxWidth, minHeight, maxHeight | UISizeConstraint | | display: "flex" | UIListLayout | | display: "grid" | UIGridLayout | | flexDirection | UIListLayout.FillDirection | | justifyContent | UIListLayout.HorizontalAlignment / VerticalAlignment | | alignItems | UIListLayout.HorizontalAlignment / VerticalAlignment | | gap | UIListLayout.Padding | | flexWrap | UIListLayout.Wraps | | order | LayoutOrder |

Spacing

| CSS Property | Roblox Mapping | |:---|:---| | padding (shorthand) | UIPadding (all sides) | | paddingTop/Right/Bottom/Left | UIPadding (individual) |

Visual

| CSS Property | Roblox Mapping | |:---|:---| | backgroundColor | BackgroundColor3 + BackgroundTransparency | | color | TextColor3 + TextTransparency | | opacity | BackgroundTransparency / ImageTransparency | | borderRadius | UICorner | | border (shorthand) | BorderSizePixel + BorderColor3 (style keywords like solid are optional) | | boxShadow | 9-slice ImageLabel overlay | | background: "linear-gradient(...)" | UIGradient |

Typography

| CSS Property | Roblox Mapping | |:---|:---| | fontSize | TextSize | | fontWeight | FontFace.Weight | | fontFamily | FontFace.Family | | fontStyle | FontFace.Style | | textAlign | TextXAlignment | | textVerticalAlign | TextYAlignment | | lineHeight | LineHeight | | textDecoration | Rich text <u> / <s> tags | | textTransform | Component-level string transform | | wordBreak | Zero-width space injection | | whiteSpace | TextWrapped | | textOverflow | TextTruncate | | richText | RichText (auto-enabled if HTML tags detected) |

Other

| CSS Property | Roblox Mapping | |:---|:---| | overflow: "scroll" | ScrollingEnabled | | objectFit | ScaleType | | cursor | Not supported in Roblox | | visibility | Visible | | rotation | Rotation | | zIndex | ZIndex | | aspectRatio | UIAspectRatioConstraint | | autoSize / width: "auto" | AutomaticSize |

Color Formats

roblox-css supports all standard CSS color formats:

  • Hex: #ff0000, #f00, #ff000080
  • RGB: rgb(255, 0, 0), rgba(255, 0, 0, 0.5)
  • HSL: hsl(0, 100%, 50%), hsla(0, 100%, 50%, 0.5)
  • Named: All 148 CSS named colors (red, cornflowerblue, rebeccapurple, etc.)
  • Roblox Color3: Pass Color3 instances directly

Dimension Formats

  • Pixels: "100px" or 100 (bare number = pixels)
  • Percentage: "50%"UDim scale component
  • Viewport: "100vw", "50vh" → viewport-relative
  • Calc: "calc(100% - 20px)"
  • Auto: "auto"AutomaticSize

Type Safety

roblox-css uses TypeScript branded types to prevent bypassing the middleware at compile time:

// ✅ This works — value produced by webStyle()
const style = webStyle({ width: "100px" });
<Box style={style} />

// ❌ This fails at compile time — raw object rejected
const fake = { props: { Size: UDim2.fromOffset(100, 0) }, children: [] };
<Box style={fake} />  // Type error: missing branded symbol

Four branded types enforce this: WebStyleResult, ParsedDimension, ParsedColor, PaddingValues.

Architecture

See docs/ARCHITECTURE.md for the full architectural deep-dive.

CSSProperties → webStyle() → { props, children }
                   │
        ┌──────────┼──────────┐
        ▼          ▼          ▼
   colorParser  dimParser  gradientParser
        │          │          │
        ▼          ▼          ▼
     Color3     UDim/UDim2  UIGradient
        │          │          │
        └──────────┼──────────┘
                   ▼
           WebStyleResult (branded)
                   │
                   ▼
          <Box style={result} />
                   │
           ┌───────┼───────┐
           ▼               ▼
     props spread    constraint children
     on <frame>      (UICorner, UIPadding, ...)

Running Tests

Tests run natively inside Roblox Studio using @rbxts/jest:

  1. Build: npx rbxtsc
  2. Open test-runner.project.json in Roblox Studio via Rojo
  3. Run the Jest test plugin

Test coverage: 1,419 assertions across 24 spec files covering every parser, primitive, and motion component.

Contributing

See CONTRIBUTING.md.

License

LGPL-3.0-only — see LICENSE, COPYING, and COPYING.LESSER.

You may use roblox-css in proprietary projects without releasing your project's source code. However, any modifications to roblox-css itself must be released under LGPL-3.0.