36

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 Answers 3

52

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};
`;
Sign up to request clarification or add additional context in comments.

2 Comments

Isn't this just for static theming though? With this solution, you can't really render on a change to the variable. I'd go with @Ricardinho 's answer as this allows you to update the theme dynamically; through an actual object.
I agree in most cases that using the <ThemeProvider> is the best way. In some cases (ex. defining responsive breakpoints), it seems static variables could be helpful. In most cases though, you get a lot more power using the <ThemeProvider> (ex. light/dark mode switching, customizing elements at deeper levels using nested ThemeProvider, etc)
51

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

1 Comment

This should be an accepted answer. If you want to have an scss like variables in styled components then you should use theme object which holds all your global settings and pass it to <ThemeProvider> wrapper.
5

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;
`;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.