
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
Imagine React's Stateless Components... but for css. Create a style and then use the HOC pattern to generate variations on those styles

We build our components in hierarchical trees, like nested react components. Why not define their styles in the same way?
When I write CSS, I use it to style a component. A component has properties, and states. Simple enough... but what happens
when we have, say, a .btn style with 7 sizes, 4 colors, and then multiple states like :hover, disabled, etc. They all start conflicting—things
get hard to reason about. That's what's so awesome about react; it makes things very simple.
Lets apply some of the concepts from stateless components && the HOC pattern to building CSS.
disclaimer: all of the following examples are purely hypothetical right now. Although there's already a lot of code written,
cssculptis still in its infancy. This is what it may look like:
import { sculpt, kiln } from 'cssculpt';
import { Color, darken } from 'cssculpt/chroma';
const buttonSculpture = sculpt('.button', (props, node) => {{
color: props.textColor,
/** optional destructuring for appropriate css rules **/
font: {
weight: 500
},
borderRadius: '2px',
border: `1px solid ${darken(props.baseColor, 0.4)}`, // SCSS like utility functions a plenty
/**
* the next line is an example of some shorthand; without a unit (eg: '4px')
* it defaults to px -- and you'll be able configure that default unit
**/
padding: [4, 2],
background: props.baseColor,
'&:hover': { // :pseudo selectors, @atrules welcome
background: darken(props.baseColor, 0.3)
}
});
// render the style with a given set of props
const buttonStyle = kiln.fire(buttonSculpture, {
baseColor: '#ccc',
textColor: Color.black
});
const styleSheet = StyleSheet();
styleSheet.add(buttonStyle);
console.log(styleSheet.getCSS());
Console Output:
{
'.button': {
'color': '#000',
'font-weight': 500,
'border-radius': '2px',
'border': '1px solid #666'
'padding': '4px 2px',
'background': '#ccc',
},
'.button:hover' {
'background': '#808080'
}
}
Nothing revolutionary, so far... Here's where things get interesting.
Normally with css. If we wanted to make a small variation on this, like say a button that was blue, we would have
to manually go through and create new declarations under rules that have more specific selectors;
targeting only a subset eg: .button.button-blue. On the surface that's not that difficult. We've been doing it for
years, you're used to it.
But what about the :hover state? You need to specify a background for .button.button-blue:hover.
Again not that hard, but say you have an entire pallet of colors, and you decide that :hover should be a little darker.
Following the traditional convention, you now have to go back and tweak those values, for every color on the pallet.
That's a pain in the ass. Imagine we could do this:
const colors = { red: '#ff0000', green:'#00ff00', blue: '#0000ff' /** orange, indigo, etc.. */};
const coloredButton = buttonStyle.mold((props, parentProps, node) => {
return node.parent({ ...parentProps, ...props });
});
const colorfulButtons = colors.map((v, k) => {
return coloredButton.recast(`&.button-${k}`, { baseColor: v });
})
Okay, so this is where it starts to get fun. Let me explain what is happening:
buttonStyle.mold() takes one parameter, a callback that looks like:
mold(props: Object, parentProps: Object, node: TreeNode)
props is the object that will be passed when calling coloredButton.recast
parentProps is the props object that was used by kiln.fire to create buttonStyle
node.parent(props: Object) this calls the "render" method we created for
buttonSculpture with sculptNode waaayyyy back at the begining. Its returns a new StyleTree.
So basically we "re-render" the original sculpture, but we merge our new props from recast props into the
original set of props passed by `kiln.fire. This way the rendering logic remains the same, but uses
the new set of values. This is the simplest example of whats possible! Just using a different set of props here; later on
we'll start merging in custom rules and more.
for each color, we compute a new style by calling:
recast(selector: String, props: Object)
We specify a new root selector for this component for each color. They'll look like:
.button.button-red, .button.button-green, etc. But the key part here is: those rendered
variations are diffed against the original buttonStyle and values which are the same are omitted.
And yes, it takes :hover and anything else nested in there into consideration too!
`
So if we spat that out into css, this would be the result
{
/** ...same output from the first example... **/
'.button.button-red': {
'background': '#ff0000',
'border': '1px solid #99000'
},
'.button.button-red:hover': {
'background': '#b30000'
},
'.button.button-green': {
'background': '#ff0000',
'border': '1px solid #009900'
},
'.button.button-green:hover': {
'background': '#00b300'
}
/** ...etc, etc... **/
}
Sure this could be achieved with some complex, temperamental SASS/LESS mixins, but this is just the begining of what cssculpt can accomplished.
Thanks for reading! I'm working hard on this because I think it has the potential to be huge. If you have any feedback at all, please open an issue. This is a pretty ambitious project, so if anyone wanted to join the effort, in any capacity, I would be greatly humbled.
the sky ain't no limit
There's so much that could be added to this, so much that is possible; here's just a few things:
{
.Button {
...buttonStyles
& i.icon {
...iconStyles
^:hover & { // .Button:hover i.icon -- keep dom elements nested in one tree, let them target states on the parent
...iconStylesOnButtonHover
}
}
&:hover {
...buttonHoverStyles
}
}
}
darken()
node.border('1px', Border.Solid, Color.red) in a NodeSculptor (aka that arrow function given to sculpt() and mold() in the examplepostcss support (autoprefixing, and more)react binding via classnames (similar to cssmodules)webkit, gulp, gruntFAQs
Imagine React's Stateless Components... but for css. Create a style and then use the HOC pattern to generate variations on those styles
We found that cssculpt demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.