Logo
< Back to home

Styled components

The standard setup for styling React apps, if you've used create-react-app, is importing .css files. Which seems to be a bit prehistoric when css preprocessors are now widely mainstream. It is possible to extend the create-react-app setup to use preprocessors, however using styled components allows you to write JS within your styles. This means that styling can be applied based on props that the component receives, and preprocessor mixins, functions, placeholders can be written with standard JS functions. Stlyed components also allows nesting of selectors and use of the parent selector ‘&’.

Defining and using a styled component

const StyledButton = styled.button`
	padding: 10px;
	background: #333;
	color: #fff;
`;
const Button = ({ text }) => (
	<StyledButton>{text}</StyledButton>
);

Using props

To access the props you are writing a function within the styles which gets passed the argument props from the styled component <StyledButton />

const StyledButton = styled.button`
	padding: 10px;
	background: ${props => props.primary ? '#aa2330' : '#333'};
	color: #fff;
`;

Extending styles

If you want to create a component with a few changes to the original component, for instance overriding the button color, then you can call extend on the component.

const StyledButton = styled.button`
	padding: 10px;
	background: #333;
	color: #fff;
`;

const GreenButton = StyledButton.extend`
	background: #769620;
`;

Note: The extend function can only be used on styled components, other components would need to use the syntax styled(Comp).

You can also use the styles on a different tag, for instance converted a button to an anchor tag.

const Link = StyledButton.withComponent('a');

It also also possible to style a styled component from another styled component, for example, if you want to have a full width button within a form.

const StyledFrom = styled.form`
	${StyledButton} {
		width: 100%;
	}
`;

Note: This cannot be used with non styled components unless they are wrapped with styled(Comp).

Different approaches to using styled components

There are at least a couple of different ways you can used styled components: one styled component per exported component with nested selectors or separate styled componets for each element with styles, or a mix between the two.

// Styled component outer wrapper only
const StyledSection = styled.div`
	/* ... */
	.side-image {
		/* ... */
		img {
			/* ... */
		}
	}
	.text {
		/* ... */
	}
`;

const Section = () => (
	<StyledSection>
		<div className="side-image"><img src="image.jpg" alt="" /></div>
		<div className="text">Some text</div>
	</StyledSection>
);


// Separate styled components
const StyledSection = styled.div`/* ... */`;
const SideImage = styled.div`/* ... */`;
const Image = styled.img`/* ... */`;

const Section = () => (
	<StyledSection>
		<SideImage><img src="image.jpg" alt="" /></SideImage>
		<Image>Some text</Image>
	</StyledSection>
);
			

The advantage of using separatate styled components is it makes the styles more reusable so they can be used in another component. It helps with levels of specifity, if you were to overwrite some styling for a component nested in another.

// Overriding styled component outer wrapper only
const Promo = styled.div`
	${StyledSection} {
		.side-image {
			img {
				/* ... */
			}
		}
	}
`;


// Overriding separate styled components
const Promo = styled.div`
	${Image} {
		/* ... */
	}
`;
			

It also breaks up the styles into smaller chunks improving readability and helps to prevent issues with styles not appearing as a className has been mispelt because React will throw an error to tell you that the component you have reference does not exist.

When using third party plugins it can be difficult control the output of the HTML and apply styled components. Then to style the nested elements you would wrap it all in a styled component and use css selectors to style the component.