Theme Styling with the sx Prop
Enhance your component flexibility while sticking to your design principles.
As React components become the building blocks of our application, styling them becomes a crucial part of our development. Scaling these styles as our codebase grows is critical – balancing modularity, performance, and developer experience.
Today, there are many ways to apply styles to your React, just to name a few popular methods:
Let's take a closer look at a CSS-in-JS approach used by Theme UI which provides amazing developer ergonomics while respecting design constraints.
A quick setup
The up-coming examples assume a project that has already been set up with Theme UI. To set up a project with Theme UI:
- Install the Theme UI package with
npm i theme-ui - Wrap your application with thepassing in the
ThemeProviderobject as a proptheme - See the Getting Started section for more details
The sx prop
Theme UI introduces a powerful styling feature, the sx prop. This prop lets you style elements inline using values from your theme.
You can add the
sx
/** @jsx jsx */
jsx
theme-ui
/** @jsx jsx */ import { jsx } from 'theme-ui'; export default (props) => ( <div {...props} sx={{ // values referencing scales defined in a theme color: 'primary', bg: 'background', fontFamily: 'body', // raw CSS value boxShadow: '0 0 1px 3px rgba(0, 0, 0, .125)', }} /> );
This is a similar method to the Emotion
css
First-class component support
Instead of bringing in all of Theme UI into our project, we can leverage the smaller @theme-ui/css
sx
sx
/** * Simplified modification of the Theme UI Box * http://bit.ly/3pzPiAr */ import styled from '@emotion/styled'; import { css } from '@theme-ui/css'; // Parse the style objects passed via `sx` to the `css(...)` function const sx = (props) => css(props.sx)(props.theme); const Box = styled.div( { boxSizing: 'border-box', margin: 0, minWidth: 0, }, sx, (props) => props.css ); export default Box;
Now, Box has
sx
/** No need to import the theme-ui jsx pragma! */ import Box from './components/Box' export const Card = ({ sx, ...props }) => ( <Box {...props} sx={{ border: '1px solid', borderColor: 'border', borderRadius: "grayLight" p: 3, ...sx }} /> ) export default Card;
Moving the
sx
sx
import styled from '@emotion/styled'; import sx from '../utils/sx'; const Button = styled.button( { appearance: 'none', display: 'inline-block', textAlign: 'center', lineHeight: 'inherit', textDecoration: 'none', fontSize: 'inherit', px: 3, py: 2, color: 'white', bg: 'primary', border: 0, borderRadius: 4, }, sx ); export default Button;
Next steps
This is a simple approach for adding a powerful styling layer to your React components, allowing for flexibility while promoting development within the theme constraints.
I recommend checking out the Theme UI source code on how this technique is taken one step farther in adding theme-based variants, base styles, and hooking in additional prop conveniences from Styled System.
You can expand on this technique by using your foundational
Box
Subscribe to the newsletter
Be the first to know when I post something new! Thoughts about code, design, startups and other interesting things.