Themes

  • Use an abstraction layer such as react-with-styles that enables theming. react-with-styles gives us things like withStyles(), ThemedStyleSheet, and css() which are used in some of the examples in this document.

    Why? It is useful to have a set of shared variables for styling your components. Using an abstraction layer makes this more convenient. Additionally, this can help prevent your components from being tightly coupled to any particular underlying implementation, which gives you more freedom.

  • Define colors only in themes.

    1. // bad
    2. export default withStyles(() => ({
    3. chuckNorris: {
    4. color: '#bada55',
    5. },
    6. }))(MyComponent);
    7. // good
    8. export default withStyles(({ color }) => ({
    9. chuckNorris: {
    10. color: color.badass,
    11. },
    12. }))(MyComponent);
  • Define fonts only in themes.

    1. // bad
    2. export default withStyles(() => ({
    3. towerOfPisa: {
    4. fontStyle: 'italic',
    5. },
    6. }))(MyComponent);
    7. // good
    8. export default withStyles(({ font }) => ({
    9. towerOfPisa: {
    10. fontStyle: font.italic,
    11. },
    12. }))(MyComponent);
  • Define fonts as sets of related styles.

    1. // bad
    2. export default withStyles(() => ({
    3. towerOfPisa: {
    4. fontFamily: 'Italiana, "Times New Roman", serif',
    5. fontSize: '2em',
    6. fontStyle: 'italic',
    7. lineHeight: 1.5,
    8. },
    9. }))(MyComponent);
    10. // good
    11. export default withStyles(({ font }) => ({
    12. towerOfPisa: {
    13. ...font.italian,
    14. },
    15. }))(MyComponent);
  • Define base grid units in theme (either as a value or a function that takes a multiplier).

    1. // bad
    2. export default withStyles(() => ({
    3. rip: {
    4. bottom: '-6912px', // 6 feet
    5. },
    6. }))(MyComponent);
    7. // good
    8. export default withStyles(({ units }) => ({
    9. rip: {
    10. bottom: units(864), // 6 feet, assuming our unit is 8px
    11. },
    12. }))(MyComponent);
    13. // good
    14. export default withStyles(({ unit }) => ({
    15. rip: {
    16. bottom: 864 * unit, // 6 feet, assuming our unit is 8px
    17. },
    18. }))(MyComponent);
  • Define media queries only in themes.

    ```js
    // bad
    export default withStyles(() => ({
    container: {

    1. width: '100%',
    2. '@media (max-width: 1047px)': {
    3. width: '50%',
    4. },

    },
    }))(MyComponent);

    // good
    export default withStyles(({ breakpoint }) => ({
    container: {

    1. width: '100%',
  1. [breakpoint.medium]: {
  2. width: '50%',
  3. },
  4. },
  5. }))(MyComponent);
  6. ```
  • Define tricky fallback properties in themes.

    Why? Many CSS-in-JavaScript implementations merge style objects together which makes specifying fallbacks for the same property (e.g. display) a little tricky. To keep the approach unified, put these fallbacks in the theme.

    ```js
    // bad
    export default withStyles(() => ({
    .muscles {

    1. display: 'flex',

    },

    .muscles_fallback {

    1. 'display ': 'table',

    },
    }))(MyComponent);

    // good
    export default withStyles(({ fallbacks }) => ({
    .muscles {

    1. display: 'flex',

    },

    .muscles_fallback {

  1. [fallbacks.display]: 'table',
  2. },
  3. }))(MyComponent);
  4. // good
  5. export default withStyles(({ fallback }) => ({
  6. .muscles {
  7. display: 'flex',
  8. },
  9. .muscles_fallback {
  10. [fallback('display')]: 'table',
  11. },
  12. }))(MyComponent);
  13. ```
  • Create as few custom themes as possible. Many applications may only have one theme.

  • Namespace custom theme settings under a nested object with a unique and descriptive key.

    1. // bad
    2. ThemedStyleSheet.registerTheme('mySection', {
    3. mySectionPrimaryColor: 'green',
    4. });
    5. // good
    6. ThemedStyleSheet.registerTheme('mySection', {
    7. mySection: {
    8. primaryColor: 'green',
    9. },
    10. });

CSS puns adapted from Saijo George.