classnames-in-js
A more sane approach to CSS in React (and Preact)
When you love the idea of styled-components
and CSS-in-JS
, but you also kind of hate it.
Heavily inspired by how styled-components and emotion lets us write components, but without having to write CSS in JavaScript.
Usage
Installation
npm i classnames-in-js
gzip size | module | tag-api | safeguards (?) | theme context |
---|
~3kb | classnames-in-js | ✅ | ✅ | ✅ |
~0.5kb | classnames-in-js/lite | ❌ | ❌ | ❌ |
~3kb | classnames-in-js/preact | ✅ | ✅ | ❌ awaiting context api in Preact X |
~0.4kb | classnames-in-js/preact-lite | ❌ | ❌ | ❌ |
Basic usage
import React from 'react'
import ReactDOM from 'react-dom'
import { styled } from 'classnames-in-js'
const Heading = styled('h1', 'heading')
ReactDOM.render(<Heading>Hello</Heading>, document.body)
Integrates with CSS modules
import React from 'react'
import ReactDOM from 'react-dom'
import { styled } from 'classnames-in-js'
import styles from './styles.css'
const Heading = styled('h1', styles.heading)
ReactDOM.render(<Heading>Hello</Heading>, document.body)
Conditionally applying classes
If classnames-in-js
recieves a function as the second argument it will be called with the component props and/or theme.
import React from 'react'
import ReactDOM from 'react-dom'
import { styled } from 'classnames-in-js'
import cx from 'classnames'
import styles from './styles.css'
const Heading = styled('h1', props =>
cx({
[styles.heading]: true,
[styles.headingDark]: props.dark
})
)
ReactDOM.render(<Heading dark>Hello</Heading>, document.body)
Appending and overriding
If a consumer passes a className
prop it will be appended.
import React from 'react'
import ReactDOM from 'react-dom'
import { styled } from 'classnames-in-js'
const Heading = styled('h1', 'heading')
ReactDOM.render(
<Heading className="heading--dark">Hello</Heading>,
document.body
)
import React from 'react'
import ReactDOM from 'react-dom'
import { styled } from 'classnames-in-js'
const Heading = styled('h1', 'heading')
const DarkHeading = styled(Heading, 'heading--dark')
const EvenDarkerHeading = styled(DarkHeading, 'heading--even-darker')
ReactDOM.render(
<>
<Heading>Hello</Heading>
<DarkHeading>Hello</DarkHeading>
<EvenDarkerHeading>Hello</EvenDarkerHeading>
</>,
document.body
)
Theming
import React from 'react'
import ReactDOM from 'react-dom'
import { styled, Theme } from 'classnames-in-js'
const Heading = styled('h1', (props, theme) => `heading heading--${theme}`)
ReactDOM.render(
<Theme.Provider value={'sport'}>
<Heading>Hello</Heading>
</Theme.Provider>,
document.body
)
Tagged template literal API
classnames-in-js
also supports using tagged template literals to construct classes.
If an interpolated value is a function it will be called with the props
and the theme
if present.
import React from 'react'
import ReactDOM from 'react-dom'
import { styled, Theme } from 'classnames-in-js'
const Heading = styled.h1`
heading
${Date.now() === 42 ? 'heading--dark' : ''}
${(props, theme) => `heading--${theme}`}
`
ReactDOM.render(
<Theme.Provider value={'sport'}>
<Heading>Hello</Heading>
</Theme.Provider>,
document.body
)
Preact
import styled from 'classnames-in-js/preact'
Note: classnames-in-js/preact
does not currently support automaticly extracting theming from context or the tagged template literal api. This is on the todo list.
See also
License
MIT.