26
votes

I'm using styled-components to build my components. All style properties which accept custom values are reused throughout my components (as it should be). With that in mind, I'd like to use some sort of global variables so that updates will propagate to all components without needing to update each style individually.

Something like this:

// Variables.js

var fontSizeMedium = 16px;

// Section.js

const Section = styled.section`
  font-size: ${fontSizeMedium};
`;

// Button.js

const Button = styled.button`
  font-size: ${fontSizeMedium};
`;

// Label.js

const Label = styled.span`
  font-size: ${fontSizeMedium};
`;

I guess I'm getting the syntax wrong though? Also, I know global variables are not recommended in Javascript land, but in design land reusing styles across components is an absolute must. What are the trade-offs here?

3

3 Answers

38
votes

Wrapping a <ThemeProvider> around your application may help:

https://www.styled-components.com/docs/advanced#theming

const theme = {
  fontColour: 'purple'
}

render() {
  return (
    <ThemeProvider theme={theme}>
      <MyApplication />
    </ThemeProvider>
  )
}

That will give all child styled-components access to the theme like so:

const MyApplication = styled.section`
  color: ${props => props.theme.fontColour}
`

Or

const MyFancyButton = styled.button`
  background: ${props => props.theme.fontColour}
`

Or access the theme via https://www.styled-components.com/docs/advanced#getting-the-theme-without-styled-components

33
votes

I eventually figured this out, so here's how you can do it, at least if using React.

You need to define the variables in one file and export them.

// Variables.js

export const FONTSIZE_5 = '20px';

Then you need to import those variables into each component file.

// Button.js

import * as palette from './Variables.js';

Then you can use the variables in your styled-components like this:

const Button = styled.button`
  font-size: ${palette.FONTSIZE_5};
`;
1
votes

Your final solution works for 2 two reasons:

  1. Simply declaring a variable in a file does not attach it to the global scope for the entire app, so other files are unaware of it unless imported in.
  2. 16px is not a valid value. It needed to either be wrapped in quotes to make it a string (like you did with '20px'), or the px needed to be removed.

I ran into a similar situation, except I needed my variables to be numbers instead of strings, and this also works:

const CELL_SIZE = 12;
const ROWS = 7;
const CELL_GAP = 3;

const BannerGrid = styled.div`
  display: grid;
  grid-template-columns: repeat(auto-fit, ${CELL_SIZE}px);
  grid-template-rows: repeat(${ROWS}, ${CELL_SIZE}px);
  grid-column-gap: ${CELL_GAP}px;
  grid-row-gap: ${CELL_GAP}px;
  grid-auto-flow: column;
`;