Skip to content

Instantly share code, notes, and snippets.

@kof kof/StyledButton.js

Last active Mar 22, 2017
What would you like to do?
Styled Primitive Components with JSS
import injectSheet, {jss} from 'react-jss'
export function createStyled(options) {
const sheet = jss.createStyleSheet(null, options)
return function styled(tag, style) {
const {className} = sheet.addRule(Math.random(), style)
const StyledComponent = props => createElement(tag, {className, ...props})
return injectSheet(sheet)(StyledComponent)
export const styled = createStyled()
import {styled} from 'react-jss-components'
const RedButton = styled('button', {
color: 'red'
<RedButton>Click me</RedButton>

This comment has been minimized.

Copy link
Owner Author

kof commented Oct 21, 2016

The idea (pseudo code) is to create styled primitive components, similar to but using jss.


This comment has been minimized.

Copy link
Owner Author

kof commented Oct 22, 2016

Interesting observations about this approach:

  • No HOC around the entire user component, which means public API of user component remains untouched.
  • When styled components are created at the top level of a module (same like import statements), JSS only creates virtual rules. All rules get rendered when a first primitive is about to render. It is a buffering for free.
  • There are 2 options, use one global styled() function or create it for every file or user component with createStyled(). If first option is used, all rules for all primitives are virtually created and will render in one style tag once first primitive renders. If using the second option, styles are separated on per-component/file basis and will render also when a first primitive of that component renders.

This comment has been minimized.

Copy link
Owner Author

kof commented Oct 22, 2016

Good point by @nathanmarks:
For SSR we need to detect when a new request comes in. We can achieve that by wrapping the entire application into a JssProvider and either setting something on a context that tells our component that new request was created or provider creates a new jss instance and we just use it within the styled() fn.


This comment has been minimized.

Copy link

sergeysova commented Mar 22, 2017

Work example:

import React, { PropTypes } from 'react'
import cn from 'classnames'

const domElements = ['a', 'button', 'div', 'span', 'h1'] // etc

export default function createStyledJss(injectSheet) {
  const styledJss = (tag, name, styles) => {
    const themedStyles = { [name]: styles() }
    const sheetInjector = injectSheet(themedStyles)

    const component = ({ sheet, classes, className, ...props }) => (
      React.createElement(tag, { ...props, className: cn(classes[name], className) })
    const styledComponent = sheetInjector(component)
    styledComponent.displayName = name

    return styledComponent

  domElements.forEach(tag => {
    styledJss[tag] = styledJss.bind(null, tag)

  return styledJss


// app/styled.js

import { create as createJss } from 'jss'
import { create as createInjectSheet } from 'react-jss'
import presetDefault from 'jss-preset-default'
import createStyledJss from 'jss-styled'

export const jss = createJss()


export const injectSheet = createInjectSheet(jss)
export default createStyledJss(injectSheet)

// app/components/button.js

import React from 'react'
import styled from '../styled'

const Button = styled.button('Button', () => ({
  backgroundColor: 'black',
  padding: 20,
  color: 'white',

export default Button
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.