SkillAgentSearch skills...

Cssobj

Runtime CSS manager, Turn CSS into dynamic JS module, Stylesheet CRUD (Create, Read, Update, Delete) in CSSOM, name space (local) class names

Install / Use

/learn @cssobj/Cssobj
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<img align="right" title="cssobj logo" alt="cssobj logo" align="bottom" src="https://avatars0.githubusercontent.com/u/20465580?v=3&s=132" border="30" hspace="0" vspace="20">

CSSOBJ Join the chat at https://gitter.im/css-in-js/cssobj

Runtime CSS manager, Turn CSS into dynamic JS module, Stylesheet [CRUD][] (Create, Read, Update, Delete) in CSSOM, Solve common problems of CSS-in-JS.

Usage - Wiki - API - Demo - React - Babel

Build Status npm Coverage Status dependencies Status Standard - JavaScript Style Guide

Install:

npm

npm install cssobj  # the lib

# When use Babel
npm install babel-plugin-transform-cssobj

# When **NOT** use Babel, install the converter
npm install -g cssobj-converter

browser

<script src="https://unpkg.com/cssobj"></script>

Usage

First see this SIMPLE DEMO

In the example, cssobj will create <style> tag in HEAD, render CSS rules inside

import cssobj from 'cssobj'

const obj = {
  div: {
    backgroundColor: 'yellow',
    color: 'red',
    // simulate 50vh in CSS3
    height: () => window.innerHeight/2 + 'px'
  }
}
const result = cssobj(obj)

// dynamic update height when resize
window.onresize = () => result.update()

The rendered CSS (height is dynamically set to 50% of window height)

div { background-color: yellow; color: red; height: 600px; }

If you read the code, you've learned the API already:

Only One top level method: cssobj( obj, [config] ), all other things using result.someMethods, that's all, really.

Stylesheet CRUD

The power of cssobj is CSS CRUD (Create, Read, Update, Delete), dynamically change above CSS, see below:

1. Update property values

You want to change color to 'blue'


// using static value:
obj.div.color = 'blue'
result.update()  // color is now 'blue'


// using function as value:
obj.div.color = function(v){
  return randomColor()
}
result.update()  // color is now random

2. Delete/Remove properties

You want to remove backgroundColor

It's just work as you expected:


delete obj.div.backgroundColor
result.update()

3. Create/Add new properties

You want to add 'float' and 'clear'

It's just work as you expected:

obj.div.float = 'left'
obj.div.clear = 'both'
result.update()

4. Create/Add new rules

You want to add ':after' rule, and div span rule

obj.div['&:after'] = { fontSize:'10px', content:'"---"' }
obj.div.span = { fontSize: '18px' }
result.update()

5. Update/Replace rules

You want to replace the whole rule

obj.div.span = { color: 'green', fontSize: '20px' }
result.update()

All the above can use function instead

obj.div.span = function() {
  return { color: randomColor(), fontSize: currentSize + 'px' }
}
result.update()

6. Delete/Remove rules

You want to remove div span rule

delete obj.div.span
result.update()

7. Read a rule

Although cssobj can manage everything, you read the rule in stylesheet manually

const rule = result.root.children.div.omRule[0]
// => CSSStyleRule
rule.color = 'red'

8. Delete/Destroy cssobj

Currently, cssobj don't provide result.destroy() or similar method, you should manually destroy things:

// remove <style> tag
result.cssdom.parentNode.removeChild(el)
// GC result
result = null

Think of this: one cssobj instance === A <style> tag with rules <kbd>+</kbd> A manager from JS

At-Rules

All @-rules work as expected, and @media can be nested at any level:

cssobj({
  '.nav':{
    width: '1024px',
    '@media print': {
      display: 'none'
    }
  }
})

Above will hide .nav when print.

You can emit any @media rule by cssom.media option:

const result = cssobj({
  '.nav':{
    width: '1024px',
    '@media print': {
      color: 'red'
    }
  }
}, { cssom: { media:'' } })

result.config.cssom.media = 'print'
result.update()

Above will switch to print view, with below CSS:

nav {width: 1024px;}
nav {color: red;}

Then switch back:

result.config.cssom.media = ''
result.update()
cssobj({
  '@keyframes changeColor': {
    '0%': { backgroundColor: 'green' },
    '100%': { backgroundColor: 'yellow' }
  },
  '.nav': {
    backgroundColor: 'red',
    animation: '5s infinite changeColor'
  }
})

Notice above @keyframes, it have to be in top level of your source object, aka cannot be nested into .nav, that is different from @media rule, which allow nested at any level, or nested into another @media:

cssobj({
  h3:{
    color: 'blue',
    '@media (min-width: 400px)': {
      color: 'red',
      '@media (max-width: 500px)': {
          color: 'green'
      }
    },
    '@media (min-width: 500px)': {
      color: 'purple'
    }
  }
})

Above, what's the color will be? You can take a try and see what's the final CSS will be.

There's a hidden JS Bin...

Localize class names

Passing local: true as option, cssobj will add a random name space into all class names, this is called localize:

const result = cssobj(
  {
    '.nav': {color: 'red'}
  },
  { local: true }
)

Rendered CSS:

.nav_1lwyllh4_ {color: red;}

You can get this name space using result.space, or using below methods:

// As HTML class attribute
result.mapClass('nav active')  // [string] 'nav_1lwyllh4_ active_1lwyllh4_'

// As CSS selector
result.mapSel('.nav li.item')  // [string] '.nav_1lwyllh4_ li.item_1lwyllh4_'

React

You can use react-cssobj with React, like below:

import React from 'react'
import ReactCSS from 'react-cssobj'

const {css, mapClass} = ReactCSS({
  '.app': {
    background: 'red'
  }
})

export default class App extends React.Component {
  render(){
    return mapClass (<div className = 'app'>App</div>)
  }
}

Work Flow with Babel, See also Without Babel Version

If use Babel, recommended the babel-plugin-transform-cssobj

// create <style> in <head>, insert CSS rules, random namespace: _1jkhrb92_

// The babel-plugin only transform: CSSOBJ `text`

const result = CSSOBJ `
---
# cssobj config
local: true
plugins:
  - default-unit: px
---
// SCSS style (nested)
.nav {
  color: blue;
  height: 100;

  // font-size is a function
  .item { color: red; font-size: ${v => v.raw ? v.raw + 1 : 12} }

  // nested @media
  @media (max-width: 800px) {
    color: #333;
    // & = parent selector = .nav
    &:active {
      color: #666;
    }
  }

}
`
const html = result.mapClass(<ul class='nav'><li class='item active'>ITEM</li></ul>)
// <ul class="nav_1jkhrb92_"><li class="item_1jkhrb92_ active_1jkhrb92_"></li></ul>

Rendered result as below:

import cssobj from "cssobj";
import cssobj_plugin_default_unit from "cssobj-plugin-default-unit";
const result = cssobj({
  '.nav': {
    color: 'blue',
    height: 100,
    '.item': {
      color: 'red',
      fontSize: v => v.raw ? v.raw + 1 : 12
    },
    '@media (max-width: 800px)': {
      color: '#333',
      '&:active': {
        color: '#666'
      }
    }
  }
}, {
  local: true,
  plugins: [cssobj_plugin_default_unit('px')]
});

const html = <ul class={result.mapClass('nav')}><li class={result.mapClass('item active')}></li></ul>

For this first time render, all class names add a random suffix _1jkhrb92_, the font-size is 12px, the <style> tag which cssobj created now contains:

.nav_1jkhrb92_ { color: blue; height: 100px; }
.nav_1jkhrb92_ .item_1jkhrb92_ { color: red; font-size: 12px; }
@media (max-width: 800px) {
  .nav_1jkhrb92_ { color: rgb(51, 51, 51); }
  .nav_1jkhrb92_:active { color: rgb(102, 102, 102); }
}

Update CSS Value

Since we already have a function as the value:

fontSize: v => v.raw ? v.raw + 1 : 12

  • the value (===v.raw) initialised with 12 (default-unit plugin will add px when rendering, that is v.cooked === 12px)

  • each call of the function will increase font-size by 1

So, just need call result.update, the function invoked, stylesheet updated, a

View on GitHub
GitHub Stars272
CategoryDevelopment
Updated2mo ago
Forks13

Languages

JavaScript

Security Score

100/100

Audited on Jan 8, 2026

No findings