Skip to content


Repository files navigation


Atomic CSS-in-JS with a featherweight runtime

npm Language grade: JavaScript Travis (.com)


Design systems embrace a component-oriented mindset. Inspired by Tailwind CSS, utility classes provide reusable styles with no unwanted side-effects. However, they have to be generated upfront.

Atomicity generalizes the former concept by instantiating style rules on demand. Serving as a solid foundation for constraint-based layouts, atomic CSS-in-JS has come to fluorish at scale.

Key features

  • 🎳 Support for shorthand properties
  • 🍱 Reliable pseudo selector ordering
  • 🔐 Type safety with autocompletion
  • 🦖 Auto-prefixing and fallback values
  • 📚 Embedded JSDoc reference
  • 🐾 Negligible runtime footprint
  • 💫 Works without a framework

Getting started

Install the library with a package manager of choice, e.g.:

npm install otion

Additionally, configure frameworks as shown below:


The following demo covers a wide range of use-cases.

As a core function, css returns a space-separated string of unique class names. Each property–value pair is only injected once to the library-managed style sheet.

Please refer to the core package manual for further information.

import { css, keyframes } from "otion";

// Animation keyframes are lazily initialized
const pulse = keyframes({
  from: { opacity: 1 },
  to: { opacity: 0 }

// Use of JSX is optional, as the solution is framework-agnostic
function Component() {
  return (
      <p className={css({ color: "blue" })}>I am blue</p>
          color: "blue",
          ":hover": {
            animation: `${pulse} 3s infinite alternate`
        I am also blue, reusing the CSS class injected by my sibling
          color: "blue",
          "@media": {
            "(min-width: 768px)": {
              color: "orange"
        I am orange if your viewport is wider than 768px

Is this ready for production?

The project is marked with a '0.Y.Z' version until thorough automatic tests are written for it. However, existing functionality should be safe to use.

If you decide to give otion a try, module aliasing may help migrating between CSS-in-JS libraries:

/* package.json */
  "devDependencies": {
    "emotion": "npm:otion@^X.Y.Z" // Could also be done in reverse

Please bear in mind that while the APIs of otion and Emotion are similar, they're not totally interchangeable. For example, custom selectors and conditional group rules have no type-safe syntax in Emotion.


Thanks goes to these wonderful people (emoji key):

Kristóf Poduszló

🚧 💻 📖 💡 🤔 🚇


🐛 🤔

Katja Lutz

🐛 🤔

Mark Kvetny


Jared Palmer


Tiago Souza

📖 📦 💡 💻

Eddy Wilson

🤔 🐛

Samuel Hobl


Juho Vepsäläinen


Daniel Emod Kovacs


This project follows the all-contributors specification. Contributions of any kind welcome!


The project's name is an ode to Emotion, an extensive CSS-in-JS runtime. Similar libraries had great impact on the initial development process, including but not limited to:

  • Styled Components, with its thoroughly tested approaches
  • Styletron, for openly discussing the caveats of atomic styling
  • glamor, by its simplistic and comprehensible implementation

The logo's ocean emoji is courtesy of Twemoji.