Skip to content

Object Styles to Template Literals — Numio

Rewrites css({...}) and styled.x({...}) object styles into tagged template literals for styled-components, Emotion or Linaria. camelCase keys become kebab-case, numbers get px except unitless properties, and JS expressions become ${} interpolations.

Migrating Emotion or Glamor object styles to styled-components or Linaria, which expect template literal CSS.

Object Styles

Template Literal

When to use it

  • Migrating Emotion or Glamor object styles to styled-components or Linaria, which expect template literal CSS.
  • Converting a styled(Component)({...}) definition into template syntax so it can be read and edited as normal CSS.

How to use

  1. Paste JavaScript or TypeScript (JSX/TSX allowed) that calls css({...}), styled.tag({...}) or styled(Component)({...}) into the Object Styles editor.
  2. In Settings, keep "Transpile css tags" and "Transpile styled tags" on, or turn one off to leave those calls unchanged; a warning banner shows when one is off.
  3. Copy the Template Literal panel. Code outside the converted calls is kept but reformatted by Prettier.

Object styles (JavaScript or TypeScript)

const Button = styled.button({
  padding: 8,
  fontSize: '14px',
  backgroundColor: theme.primary,
  '&:hover': {
    opacity: 0.8,
  },
})

const card = css({
  display: 'flex',
  marginTop: 16,
})

Tagged template literal

const Button = styled.button`
  padding: 8px;
  font-size: 14px;
  background-color: ${theme.primary};

  &:hover {
    opacity: 0.8;
  }
`
const card = css`
  display: flex;
  margin-top: 16px;
`

Details and limitations

Conversion runs in your browser: a Web Worker applies babel-plugin-object-styles-to-template with Babel standalone (parsing TypeScript syntax when plain JavaScript fails), and the result is formatted by Prettier without semicolons.

Only calls with a single plain object argument are converted. styled("div")(obj, props => ...) with a function or several arguments, and css([...]) arrays, are left as they are.

Unitless properties such as zIndex, lineHeight and opacity keep bare numbers; other numbers get px. Array values are not expanded and become an interpolation like ${[0, 4]}.

Prettier also normalises the untouched code, for example single quotes become double quotes.

FAQ

Which call names are recognised?

The plugin transforms css(...) and styled calls: styled.button(...), styled("div")(...) and styled(Link)(...). Other functions with object arguments, such as someFn({ color: 'red' }), are not changed.

How are variables and theme values handled?

Any non-literal value, such as theme.primary or colors.white, is kept as a JavaScript expression inside ${...} in the template, so it still resolves at runtime.

Are nested selectors like &:hover supported?

Yes. A nested object under a key such as '&:hover' becomes a nested block in the template, separated from the parent declarations by a blank line.

Does it work with TypeScript?

Yes. If the code does not parse as JavaScript, it is parsed again with Babel's TypeScript syntax. Types are kept: interfaces stay, and styled.button<Props>({...}) becomes styled.button<Props>`...`.

Specifications and references