Skip to main content

Converting CSS to a JS Object: The React Inline Style Guide

Turn CSS declarations into a React inline style object the right way — camelCase keys, vendor prefixes, quoted vs bare numbers, custom properties, and batch conversion.

Published By 李雷
#css #react #jsx #frontend #converter

Converting CSS to a JS Object: The React Inline Style Guide

If you have ever pasted a designer's CSS into a React component and watched half the rules silently vanish, you already know the trap. React does not accept CSS strings in its style prop. It wants a JavaScript object, and the keys of that object follow rules that are close enough to CSS to fool you and different enough to break you. This guide walks through exactly how a CSS declaration becomes a JS style object, where hand conversion goes wrong, and how to do a whole block at once.

Why React inline styles are objects, not strings

When you write <div style={{ color: 'red' }}>, React reads those keys off a JavaScript object and assigns them to the element's style DOM API. That API exposes properties by their IDL names, which are camelCase: backgroundColor, not background-color. The browser's element.style.backgroundColor = 'blue' works; element.style['background-color'] does too on the raw DOM, but React only maps the camelCase names. Hand React a key with a hyphen in it and it treats the string as an unknown custom property, sets nothing, and throws no error. The style just never applies.

The object form is not React being awkward for its own sake. It is the same shape the DOM has always used, plus a few conveniences: React appends px to bare numbers on length properties, and it knows which properties are unit-less. That payoff only lands if every key and value is in the exact shape React expects, which is the whole reason a converter earns its keep.

The camelCase rule, hyphen by hyphen

The core transformation is mechanical: split the property name on each hyphen, then uppercase the first letter of every segment after the first.

  • background-colorbackgroundColor
  • font-sizefontSize
  • border-top-left-radiusborderTopLeftRadius

Long multi-word properties are where people slip, because by the time you have typed borderTopLeftRadius by hand for the fifth property you will eventually write borderTopleftRadius and not notice. A tool splits on every hyphen with no fatigue, so the four-segment names land exactly right. This is also the single most common reason a "correct-looking" inline style does nothing: a key left as 'background-color' is read as a literal custom string and quietly ignored.

Vendor prefixes and the -ms- exception

Vendor-prefixed properties follow a rule that trips up even people who know the camelCase basics. A leading dash is dropped and the first segment is capitalised:

  • -webkit-box-shadowWebkitBoxShadow
  • -moz-user-selectMozUserSelect

Then there is the one exception worth burning into memory. The Microsoft prefix stays lowercase in React: -ms-flex becomes msFlex, not MsFlex. Every other prefix capitalises its first segment, so the natural instinct is to write MsFlex by analogy — and the rule is dropped with no warning. This asymmetry exists because React mirrors how the DOM exposes the ms-prefixed properties, and it is exactly the kind of detail a converter should bake in so you never have to remember it under deadline.

Quoted strings vs bare numbers

The other half of the job is values. React treats a bare number on a length property as pixels, so width: 100 renders as 100px. That is fine when you mean pixels and a footgun when you copied 100% and dropped the unit. The split is:

  • Values that carry a unit stay quoted strings: '14px', '50%', '1.5rem'.
  • Properties React treats as unit-less emit bare numbers even by default: zIndex, lineHeight, opacity, flexGrow.

A lineHeight of 1.5 should be the number 1.5, not '1.5', because React multiplies a unit-less line-height against the font size. A quoted '100' width is invalid. Getting this matrix right by hand for a dozen properties is tedious, and a TypeScript project punishes the mistakes with a wall of red squiggles where CSSProperties wants a number and you handed it a string. Speaking of units, when a designer's spec mixes px and rem and you want to normalise before converting, a quick pass through the px ↔ rem converter settles the values first so the style object reads consistently.

A real input and output

Here is a card snippet straight from a design handoff, selector and all:

.card {
  background-color: #0b1020;
  padding: 12px 16px;
  border-top-left-radius: 8px;
  -webkit-box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
  line-height: 1.5;
  z-index: 10;
  --brand: #06e6d7;
}

Converted to a React style object, with bare numbers enabled, that becomes:

const style = {
  backgroundColor: '#0b1020',
  padding: '12px 16px',
  borderTopLeftRadius: '8px',
  WebkitBoxShadow: '0 2px 8px rgba(0, 0, 0, 0.4)',
  lineHeight: 1.5,
  zIndex: 10,
  '--brand': '#06e6d7',
};

Notice the four distinct decisions in one block: the selector and braces are stripped, every key is camelCased, -webkit- becomes Webkit, lineHeight and zIndex come out as bare numbers while the rgba(...) shadow stays a quoted string, and the custom property --brand keeps its dashes as a quoted string key because --brand is not a valid bare JavaScript identifier. React passes custom properties through to the DOM untouched, so your var(--brand) references still resolve at runtime.

Batch conversion without choking on messy input

I do this conversion constantly, and the failure mode is never the simple cases — it is the messy paste. A semicolon inside url(a;b) looks like a declaration separator. A comma inside rgb(0, 0, 0) looks like a value list boundary. A trailing !important and a stray comment from DevTools sit there waiting to break a naive split. The first time I tried to script this myself with a plain .split(';'), the very first gradient with a url() in it shredded the output. The parser behind the CSS to Style Object tool is paren- and string-aware, so those semicolons and commas stay inside their function calls, !important is stripped, comments are removed, and text with no colon is skipped rather than throwing.

For batch work, the practical flow is: paste a whole rule with its selector and let the tool pull declarations out of the brace block; if you paste several rule blocks it converts the first and tells you how many it found, so you feed the rest one at a time. A plain declaration list copied straight from the DevTools Styles pane works the same way. Because the input round-trips through a shareable URL, you can drop a converted snippet into a sandbox or hand it to a teammate without re-typing anything.

According to the React DOM elements documentation on the MDN-aligned style attribute, inline styles in React are passed as objects with camelCased keys, and a number value is interpreted as pixels for properties that take a length — the exact behaviour every rule above encodes.

When inline objects are the right call

Inline style objects are not a styling strategy for a whole app; for that you want a stylesheet, CSS modules, or a CSS-in-JS layer. They shine for the dynamic, per-instance cases: a value computed from props, a token mirrored into JS for a preview surface, a quick prototype reproducing a layout you found in the wild, or migrating a legacy stringified style into something CSSProperties can type-check. In all of those, the bottleneck is the conversion grunt work, and that is precisely the part worth automating so you can spend your attention on the component, not on remembering that ms stays lowercase.


Made by Toolora · Updated 2026-06-13