7 Ways to Inherit Styles Using Styled Components | by Jennifer Fu | Jun, 2022

An in-depth look at styled-components coding techniques

Image by author

styled-components is a popular library to style React applications, with over four million weekly downloads. It adopts the CSS-in-JS approach, which bundles each JavaScript component with all its belonging CSS rules and dependencies. Combined with code splitting, it only loads the least amount of code necessary.

In styled-components, CSS styles are written as custom React components. It is easy to track which components are unused or undefined during compilation. It improves code manageability, comparing class names or other ways. Since it is CSS in JavaScript, it enables dynamic styling with programming capability.

In a previous article, we have introduced what styled-components is and how to use it. We have been using styled-components for a number of years, and often, we create components extending from the existing components. In this article, we are going to explore how to inherit/share styles using styled components.

We use Create React App as a base to explore styled-components. The following command creates a React project:

% npx create-react-app react-styled-components
% cd react-styled-components

Set up styled-components:

npm i styled-components

styled-components becomes part of dependencies in package.json:

We modify src/App.js to use styled-components.

  • At line 1, styled is imported from styled-components. styled is the default export, used to create the styled.tagname helper method to transform the styling from JavaScript to the actual CSS rules.
  • At lines 3–8, the styled component, Containerextends the styles of div. It contains CSS properties of the flex layout.
  • At lines 10–23, the styled component, BlueItemextends the styles of div. It contains CSS properties of the blue component.
  • At lines 25–38, the styled component,GreenItemextends the styles of div. It contains CSS properties of the green component.
  • At lines 40–53, the styled component,OvalItemextends the styles of div. It contains CSS properties of the oval component.
  • These styled components are used to build a React app at lines 57–61.
  • Execute npm startand we see the following UI in the browser.
A blue item, a green item, and a oval item — with proper styling
Image by author

The code works. However, there are a number of duplicated properties among BlueItem, GreenItemand OvalItem.

We should try to inherit/share similar styles.

Some CSS properties can be inherited by child elements, by default, or by setting the value to inherit. This CSS property list shows the following properties are inherited by default: azimuth, border-collapse, border-spacing, caption-side, color, cursor, direction, elevation, empty-cells, font-family, font-size, font-style, font-variant, font-weight, font, letter-spacing, line-height, list-style-image, list-style-position, list-style-type, list-style, orphans, pitch-range, pitch, quotes, richness, speak-header, speak-numeral, speak-punctuation, speak, speech-rate, stress, text-align, text-indent, text-transform, visibility, voice-family, volume, white-space, widowsand word-spacing.

Among our duplicated properties, the font property is inherited by default. It can be moved up to the parent, Containerto save a few lines (line 6 in the code below):

Execute npm startand it works.

Now, we modify these items to extend from buttoninstead of div (lines 1, 15, and 29 in code below):

Execute npm start. The font property is no longer inherited.

A blue item, a green item, and a oval item — without font styling
Image by author

It is because most form elements, such as, button, input, textareaand selectdo not inherit the font* properties by default.

Luckily, there is the as prop that can render a styled component as if it is the specified element. It will work properly if we specify button as div in the code below on lines 56, 57, and 58:

Without the as prop, we have to explicitly set the font property to inherit.

The following code works too, with the font property set to inherit at lines 12, 23, and 34. Also, for a button, there is no need to specify these properties: display, align-items, justify-contentand box-sizing.

There is a helper function, createGlobalStylewhich can create shared styles at the topmost level for the whole app.

Here is src/App.js:

  • At line 1, createGlobalStyle is imported, along with styled.
  • At lines 52–54, GlobalStyle is generated with the helper function, createGlobalStyle. Globally, font is set to 20px Arial.
  • At line 58, GlobalStyle is set for the app.
  • Execute npm startand it works.

If we change items to extend from button, all the problems and solutions are the same as configuring shared styles at the parent level. The only difference is that global is the topmost parent for the whole app.

For our example, three items differ slightly from each other. We can extend the new one from the existing one, and only specify changes.

Here is src/App.js:

  • At lines 21–25, the styled component, GreenItemextends BlueItem with additional properties.
  • At lines 27–29, the styled component, OvalItemextends GreenItem with an additional property.
  • Execute npm startand it works.

For better design, we should have defined a BaseItem, which contains common styles only. Then, BlueItem, GreenItemand OvalItem extend from BaseItem.

We did not do it “the proper way” for two reasons:

  1. Show that the sub-styled components can overwrite the base styles.
  2. Save some lines of code with fewer components.

Instead of extending styled components, we can compose css props to achieve the same styles. There is a helper function, csswhich generates CSS properties from a template literal with interpolations.

Here is src/App.js:

  • At line 1, css is imported, along with styled.
  • At lines 10–19, the css template literal, blueItemgenerates CSS properties that are used at line 34.
  • At lines 21–25, the css template literal, greenItemgenerates additional CSS properties. blueItem and greenItem are composed and used at line 35.
  • At lines 27–29, the css template literal, ovalItemgenerates the additional CSS property. blueItem, greenItemand ovalItem are composed and used at line 36.
  • Execute npm startand it does not work properly.
A blue item, a green item, and a oval item — without styling
Image by author

What happened?

The css prop is not button‘s attribute. In order to make it work, babel-plugin-styled-components need to be used to turn any element with css into a styled component.

After styled-components is installed, babel-plugin-styled-components and babel-plugin-macros come with it in package-lock.json.

All we need to do is to import items from the macro directory:

import styled, { css, keyframes } from 'styled-components/macro';

Want to try another solution with babel-plugin-styled-components?

Execute npm run ejectand add Babel plugin (line 5 in code below) to the ejected package.json.

Either way, it works as expected.

A blue item, a green item, and a oval item — with proper styling
Image by author

Alternatively, the compositions can be done in the template literals (lines 22 and 29 in code below):

We can pass a function to interpolate the styled component’s template literal and use it to compute the style value.

There are multiple ways to define interpolate props. Here is an example that sets props to fontStyle, colorand borderRadius:

  • At lines 10–19, the styled component, Itemtakes the props, fontStyle, colorand borderRadius. font-style (line 14), color (line 15), border (line 17), and border-radius (line 18) adapt the values ​​based on the props.
  • Execute npm startand it works.

Here is an example that sets props to itemType:

  • At lines 10–21, the styled component, Itemtakes the prop, itemType. font-style (lines 14–25), color (line 16), border (lines 18–19), and border-radius (line 20) adapt the values ​​based on itemType.
  • Execute npm startand it works.

In the above code, we have configured color as follows:

What if we want to make ovalItem to be purple? The multiple ternary operations would make the code hard to read.

the helper function, csscan be used to compute CSS props.

Here is src/App.js:

  • At line 1, css is imported, along with styled.

Instead of using the function to generate each property value, we use it to compute CSS props (lines 17–22, lines 24–29, and lines 31–36).

Execute npm startand we see the following UI in the browser.

A blue item, a green item, and a oval item — with proper styling
Image by author

Alternatively, the interpolate function can be defined outside using the css helper (lines 10–33 in code below).

styled-components Optionally supports writing CSS as JavaScript objects, instead of strings. This makes it easy and useful to manipulate objects.

Here is src/App.js:

  • At lines 10–19, the styled object, blueItemObjectis defined.
  • At line 21, the styled component, BlueItemis created from blueItemObject.
  • At lines 23–28, the styled object, greenItemObjectis defined by blueItemObject and additional props.
  • At line 30, the styled component, GreenItemis created from greenItemObject.
  • At lines 32–37, the styled object, ovalItemObjectis defined by greenItemObject and additional props.
  • At line 39, the styled component, OvalItemis created from ovalItemObject.
  • Execute npm startand it works properly.

styled-components is a popular library to style React applications. It is widely adopted by React projects. Frequently, it is needed to create components extending from the existing components. We have explored seven ways how to inherit/share styles using styled components.

Thanks for reading.

Hopefully, some ways are useful for your projects.

Leave a Comment