DEV Community

Cover image for Extending our CSS-in-JS to support style-component syntax
Late Night Coder
Late Night Coder

Posted on

Extending our CSS-in-JS to support style-component syntax

In the previous post, we made our css emotion like function and in this blog post, we are going to extend our css function to support the following style-components syntax.

const Button = styled('button')(
  {
    backgroundColor:  "blue",
    color: "white"
  }
)
Enter fullscreen mode Exit fullscreen mode

A few things to note when exploring the API are:

// On breaking into parts: 
const Button = // <-- Part: 3
styled('button') // <-- Part: 1
({ backgroundColor: 'blue' }) // <-- Part: 2

Enter fullscreen mode Exit fullscreen mode
  • Part 1: The styled function takes the tagName that has to be created i.e
 styled('button') <-- 1

// is equivalent to

<button>
Enter fullscreen mode Exit fullscreen mode
  • Part 2: The styled(tagName) returns a function that accepts style-object which will be used to style this tagName element.
({ backgroundColor: "blue" }) <-- Part 2

// is converted to 

css({ backgroundColor: "blue" }) 

// and passed to the component as

<button className={css(...)} />
Enter fullscreen mode Exit fullscreen mode
  • The complete call returns a React component Button that renders a button with a given style.

Rendering a button using style-component like syntax

From the above points, we can write a rough husk of our styled function

// Part 1: styled('button'): element of type tagName to render
function styled(tagName) { 
  // Part 2: style('button')({ color: 'white' }) takes in the style object and applies these styles to `tagName=button` component

  return function applyStyles(styleObject) { 
      // Part 3: `Button` react component 
      return function Component(props) { 
          // ...styling and element creation... 
          // Mark: 1
      }
  }
}
Enter fullscreen mode Exit fullscreen mode

Now in place Mark: 1 we need to do the following:

  • Create an element using React.createElement of type tagName
  • Pass style-object into css function to generate name, as props may already contain some className so compose these className together.
// continue from Mark: 1

const clonedProps = clone(props);
// a copy of props is required as by default react makes props immutable
// and if we want to modify any props we need to make a copy for our use

// compute a className for styleObject
const generatedClassName = css(styleObject);

// compose className 
const className = generatedClassName + props.className ? + ` ${props.className}` : '';

// reassign composed className
clonedProps.className = className;

// create element of type `tagName` with props = `clonedProps` and `style=generateClassName`
const element = React.createElement(tagName, clonedProps);

// The `element` is of type `tagName` and of `styles=styleObject` this is one we want to render

return element;
Enter fullscreen mode Exit fullscreen mode

That is what the style-components version of our CSS-in-JS library looks like. clone function can be as simple as:

const clone = (obj) => Object.assign({}, obj);
Enter fullscreen mode Exit fullscreen mode

More reads on the CSS-in-JS:

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

SurveyJS custom survey software

JavaScript Form Builder UI Component

Generate dynamic JSON-driven forms directly in your JavaScript app (Angular, React, Vue.js, jQuery) with a fully customizable drag-and-drop form builder. Easily integrate with any backend system and retain full ownership over your data, with no user or form submission limits.

Learn more

AWS GenAI LIVE!

GenAI LIVE! is a dynamic live-streamed show exploring how AWS and our partners are helping organizations unlock real value with generative AI.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️