classname-based css-in-js

css, css-in-js, classname, class, named, style
npm install njss@1.0.8



This module enables classname-based css-in-js.


  • A css rule disallows any other selectors except one class selector and optionally pseudo selectors. (or throws an error in the dev mode)
  • A css rule has a unique classname.
  • A class attribute of a DOM element has only one classname.

I think we have no reason to use css-in-js unless we follow the restrictions. We have to re-use sets of css properties under the javascript overwriting merge rule, not in css weird priority rules.


import njss, {rgb, skew, rem} from 'njss';

    '@keyframes move': {
        '0%': {
            offsetDistance: '0%',
        '100%': {
            offsetDistance: '100%',
    bigDog: {
        color: 'red',
    '@media (orientation: landscape)': {
        bigDog: {
            color: rgb(100, 50, 50, 0.5),
            transform: skew(20,20),
            transition: [1, 'linear'],
            margin: [rem(1), 4, 5, 6],
            '@media (min-width: 1000px)': {
                ':hover': {
                    color: 'blue',
                    ':focus': {
                        color: 'green'


This module does not require something like getClassName(style).

<div class="big-dog">bow-wow</div>


.big-dog{color:red;}@media (orientation: landscape){.big-dog{color:rgb(100, 50, 50, 0.5);transform:skew(20deg, 20deg);transition:1s linear;margin:1rem 4px 5px 6px;}@media (min-width: 1000px){.big-dog:hover{color:blue;}.big-dog:hover:focus{color:green;}}}@keyframes move{0%{offset-distance:0%;}100%{offset-distance:100%;}}


/* in css */
.dog {
    transform: rotate(10deg); /* suppressed */
    transform: translateX(100px); /* has the precedence */
// in js
import njss, { merge, translateX } from 'njss';

const a = {width: 10, height: 1};
const b = {color: 'red', transform: 'rotate(10deg)', width: 100};
const c = {color: 'blue', transform: translateX(100)};

const s = {...a, ...b, ...c }; 
// {height: 1, width:100, color: 'blue', transform: 'translateX(100px)'};

const r = merge(a, b, c); 
// {height: 1, width:100, color: 'blue', transform: 'rotate(10deg) translateX(100px)'};

If you expect r, use merge.

Only transform is supported so far.

Validations in the dev mode

This module validates styles only in the dev mode. If you do not use it in the node environment, you have to execute on your own to force the dev mode. is the opposite.

This module is supposed to validate classname duplications. But it does not. It has to collect classnames in the njss module, but it contradicts live-reloading situations. I do not know any trick to escape live-reloadings.


not implemented

  • For production build, njss-loader collects imported *.css.js files, append them to one global css file(create it if it doesn't exist) and remove .css.js-importing expressions and njss-relevant expressions.

npx njss

not implemented

For server-side rendering

Append njss.toString() to html responses.

`<style>${njss.toString()}</style>` // part of a html string