Styling React Components Using glamorous

💄 glamorous is a lightweight library for CSS-in-JS with a simple API that’s similar to styled-components’ and that makes use of glamor under the hood. Two of the main differences compared to styled-components is the use of JavaScript object literals and an additional API that allows to use DOM elements directly without creating additional named components.

Let’s go over how to use glamorous to give our components some style.

Installation

To get started, you’ll need a few packages: glamorous, glamor and prop-types:

$ npm install glamorous glamor prop-types

# or, using Yarn
$ yarn add glamorous glamor prop-types

Then, all you have to do to start using it is to import the default export from the library:

SomeComponent.js

import glamorous from 'glamorous';

// ...

Basic Usage

You create a glamorous component and give it some style using the name of any DOM element and providing an object literal with CSS property names (camel-cased) and values:

import React from 'react';
import glamorous from 'glamorous';

const Box = glamorous.div({
  background: 'pink',
  marginTop: 30, // defaults to pixels
  padding: '2rem 3rem'
});

const MyComponent = () => {
  return (
    <Box>
      <h1>A title inside a pink box! 🌸</h1>
    </Box>
  );
};

export default MyComponent;

Props

You can access props passed-in to a glamorous component using a callback function as the second argument when creating the component:

import React from 'react';
import glamorous from 'glamorous';

const Box = glamorous.div(
  {
    marginTop: 30, // defaults to pixels
    padding: '2rem 3rem'
  },
  props => ({
    background: props.bg
  })
);

const MyComponent = () => {
  return (
    <Box bg="purple">
      <h1>A title inside a purple box! 🌸</h1>
    </Box>
  );
};

export default MyComponent;

Media queries, pseudo-elements & pseudo-classes

Media queries using glamorous is just as easy really:

// ...

const Box = glamorous.div({
  maxWidth: '60%',
  background: 'antiquewhite',
  margin: '1rem auto',
  padding: '2rem 3rem',
  ['@media (max-width: 600px)']: {
    maxWidth: '90%',
    background: 'lightseagreen'
  }
});

// ...

And likewise for pseudo-elements and pseudo-classes:

// ...

const Box = glamorous.div({
  maxWidth: '60%',
  background: 'antiquewhite',
  margin: '1rem auto',
  padding: '2rem 3rem',
  transition: 'background .3s',
  [':hover']: {
    background: 'lightseagreen'
  },
  [':before']: {
    content: '"Hello"',
    background: 'pink',
    padding: '.5rem 1rem'
  }
});

// ...

Notice the use of double quotes inside the single quotes for the :before pseudo-element. That syntax is important for the pseudo-element to work correctly.

Alternative Usage

For simpler and smaller components, you can also use an alternative API where you import components that correspond to a specific DOM element and use them directly. This way you avoid having to come up with a bunch of names for your glamorous components:

import React from 'react';
import { Div, H1 } from 'glamorous';

const MyComponent = () => {
  return (
    <Div background="antiquewhite" margin="1rem auto" maxWidth="60%">
      <H1 className="card-title" borderBottom="2px solid purple">
        A title inside an antique white box! 🌸
      </H1>
    </Div>
  );
};

glamorous is smart enough to distinguish between native element attributes and style props. With the above example, the card-title class will be added to the element as an additional class on top of the one generated by glamorous for the border-bottom style.

Theming

You can make use of glamorous’ ThemeProvider component to provide theme information that will be made available to all the components down the tree.

For example, here’s how you would provide a theme from the App component:

App.js

import React, { Component } from 'react';
import { ThemeProvider } from 'glamorous';

import Card from './Card';

const theme = {
  default: {
    background: '#f3f3f3',
    color: '#525252'
  },
  dark: {
    background: '#231919',
    color: '#FFDABC'
  }
};

class App extends Component {
  state = {
    currentTheme: 'default'
  };

  handleClick = () => {
    this.setState(state => ({
      currentTheme: state.currentTheme === 'default' ? 'dark' : 'default'
    }));
  };

  render() {
    const currentTheme = this.state.currentTheme;

    return (
      <ThemeProvider theme={theme[currentTheme]}>
        <React.Fragment>
          <Card />
          <Card />
          <button onClick={this.handleClick}>Toggle theme</button>
        </React.Fragment>
      </ThemeProvider>
    );
  }
}

export default App;

The button’s onClick handler toggles between our two themes and the ThemeProvider’s children components will automatically have access to the theme data.

You can access the theme from the props passed-in to the callback when creating a glamorous component:

Card.js

import React from 'react';
import glamorous from 'glamorous';

const Box = glamorous.div(
  {
    maxWidth: '60%',
    margin: '1rem auto',
    padding: '2rem 3rem'
  },
  ({ theme }) => ({
    background: theme.background,
    color: theme.color
  })
);

const MyComponent = () => {
  return (
    <Box>
      <h1>A title inside a pink box! 🌸</h1>
    </Box>
  );
};

export default MyComponent;

Global Styling

glamorous doesn’t bother itself with global styling and instead you can revert to glamor’s css.global to inject some global styles into your apps:

App.js

// ...other imports
import { css } from 'glamor';

css.global('html, body', {
  background: '#f3f3f3',
  margin: 0
});

// ...

🤓 And that's it for our little intro to glamorous. Refer to the official docs for more advanced use cases.

  Tweet It

🕵 Search Results

🔎 Searching...