This site runs best with JavaScript enabled.

Introducing glamorous πŸ’„

Software Engineer, React Training, Testing JavaScript Training

The glamorous logo, shamelessly inspired (with permission) by styled-components


A styled-components πŸ’… and jsxstyle inspired solution for styling βš›οΈ React Components from PayPal

I was building something for my product at PayPal (blog post maybe forthcoming) and got tired of writing components like this:

1const styles = glamor.css({
2 fontSize: 20,
3 textAlign: 'center',
4})
5function MyStyledDiv({className = '', ...rest}) {
6 return <div className={`${styles} ${className}`} {...rest} />
7}

So I decided to try out styled-components because the hype-train was strong πŸš‚. I REALLY liked it:

It allowed me to write that same component like this:

1const MyStyledDiv = styled.div`
2 font-size: 20px;
3 text-align: center;
4`

Making composable components that carry their styling with them was just superΒ awesome.

Unfortunately, I hit a wall when I realized that there isn't currently a solution for right-to-left conversion (like CSSJanus or rtl-css-js) and that's a hard requirement for what I'm building. I also had some issues with the size of styled-components at the time (note that you can transpile away a lot of the size if you're willing to give up some dynamic capabilities, which I was unwilling to do).

So after evaluating a bunch of other solutions and trying to enhance existing solutions to be what I wanted them to be, I decided to create my own.

Enter glamorous πŸ’„!

paypal/glamorous

glamorous is React component styling solved with an elegant (inspired) API, small footprint (<5kb gzipped), and great performance (via glamor). It has a very similar API to styled-components and uses similar tools under the hood (glamor). The benefits being:

Let's get a quick look at what a glamorous component looks like:

1// Create a <Title> react component that renders an <h1> which is
2// centered, palevioletred and sized at 1.5em
3const Title = glamorous.h1({
4 fontSize: '1.5em',
5 textAlign: 'center',
6 color: 'palevioletred',
7})
8
9// Create a <Wrapper> react component that renders a <section> with
10// some padding and a papayawhip background
11const Wrapper = glamorous.section({
12 padding: '4em',
13 background: 'papayawhip',
14})
15
16function App() {
17 return (
18 <Wrapper>
19 <Title>Hello World, this is my first glamorous component!</Title>
20 </Wrapper>
21 )
22}

(thanks to styled-components for the example inspiration).

The beauty of glamorous is that all of the cool things you can do with glamor, you can do with glamorous. Here are a few examples:

pseudoclasses

1const MyLink = glamorous.a({
2 ':hover': {
3 color: 'red',
4 },
5})

child-selectors (the escape hatch you should rarely use, but is nice to have)

1const MyDiv = glamorous.div({
2 display: 'block',
3 '& .bold': {fontWeight: 'bold'},
4 '& .one': {color: 'blue'},
5 ':hover .two': {color: 'red'},
6})
7
8const ui = (
9 <MyDiv>
10 <div className="one bold">is blue-bold!</div>
11 <div className="two">hover red!</div>
12 </MyDiv>
13)

media queries

1const MyResponsiveDiv = glamorous.div({
2 width: '100%',
3 padding: 20,
4 '[@media](http://twitter.com/media "Twitter profile for @media")(min-width: 400px)': {
5 width: '85%',
6 padding: 0,
7 },
8})

animations

1import {css} from 'glamor' // or require or whatever...
2
3const bounce = css.keyframes({
4 '0%': {transform: 'scale(1)', opacity: 0.3},
5 '55%': {transform: 'scale(1.2)', opacity: 1},
6 '100%': {transform: 'scale(1)', opacity: 0.3},
7})
8
9const MyBouncyDiv = glamorous.div({
10 animation: `${bounce} 1s infinite`,
11 width: 50,
12 height: 50,
13 backgroundColor: 'red',
14})

theming

With the new ThemeProvider (recently added by Alessandro Arnodo), glamorous also supports theming:

1const Title = glamorous.h1(
2 {
3 fontSize: '10px',
4 },
5 (props, theme) => ({
6 color: theme.main.color,
7 }),
8)
9
10// use <ThemeProvider> to pass theme down the tree
11const ui1 = (
12 <ThemeProvider theme={theme}>
13 <Title>Hello!</Title>
14 </ThemeProvider>
15)
16
17// it is possible to nest themes
18// inner themes will be merged with outers
19const ui2 = (
20 <ThemeProvider theme={theme}>
21 <div>
22 <Title>Hello!</Title>
23 <ThemeProvider theme={secondaryTheme}>
24 {/\* this will be blue */}
25 <Title>Hello from here!</Title>
26 </ThemeProvider>
27 </div>
28 </ThemeProvider>
29)

And if you need global styles, you can just use glamor to do that (you can do this with styled-components as well). And there many other cool things you can do with glamor (including Server Side Rendering)!

Another great feature of glamorous is it will merge glamor class names together automatically for you. Learn more about that here.


In addition to the styled-components inspired API, glamorous exposes a jsxstyle inspired API. Sometimes, you don’t want to give something a name because naming things is hard. Especially with this stuff, you wind up with names like Container and Wrapper and who knows which is which!? So, if you find that something doesn’t really need a name, then don’t give it one!

1const {Div, A} = glamorous
2
3function App() {
4 return (
5 <Div textAlign="center" color="red">
6 <A
7 href="[https://brave.com/](https://brave.com)"
8 textDecoration="none"
9 color="darkorange"
10 textShadow="1px 1px 2px orange"
11 >
12 Browse faster and safer with Brave.
13 </A>
14 <div>It's fast, fun, and safe!</div>
15 </Div>
16 )
17}

(fun tip: this works too: <glamorous.Div>JSX!!</glamorous.Div>)


Oh, and just for fun, all this excitement around CSS Grid got you salivating? It’s trivially supported by glamorous:

1// Example inspired by
2// [http://gridbyexample.com/examples/example12/](http://gridbyexample.com/examples/example12)
3const MyGrid = glamorous.div({
4 margin: 'auto',
5 backgroundColor: '#fff',
6 color: '#444',
7 // You can use [@supports](http://twitter.com/supports "Twitter profile for @supports") with glamor!
8 // So you can use [@supports](http://twitter.com/supports "Twitter profile for @supports") with glamorous as well!
9 '[@supports](http://twitter.com/supports "Twitter profile for @supports") (display: grid)': {
10 display: 'grid',
11 gridGap: 10,
12 gridTemplateAreas: `
13 "....... header header"
14 "sidebar content content"
15 "footer footer footer"
16 `,
17 },
18})
19
20const Box = glamorous.div({
21 backgroundColor: '#444',
22 color: '#fff',
23 borderRadius: 5,
24 padding: 10,
25 fontSize: '150%',
26})
27
28const HeaderFooter = glamorous(Box)({
29 backgroundColor: '#999',
30})
31
32function App() {
33 return (
34 <MyGrid>
35 <HeaderFooter css={{gridArea: 'header'}}>Header</HeaderFooter>
36 <Box css={{gridArea: 'sidebar'}}>Sidebar</Box>
37 <Box css={{gridArea: 'content'}}>
38 Content
39 <br />
40 More content than we had before so this column is now quite tall.
41 </Box>
42 <HeaderFooter css={{gridArea: 'footer'}}>Footer</HeaderFooter>
43 </MyGrid>
44 )
45}

And you get:

0

Example inspired by http://gridbyexample.com/examples/example12/

I hope you enjoy glamorous πŸ’„ 🌟 πŸ‘€!

See you around on twitter: @glamorousCSS and @kentcdods

With ❀️ from PayPal (we’re hiring!)

Discuss on Twitter β€’ Edit post on GitHub

Share article
loading relevant upcoming workshops...
Kent C. Dodds

Kent C. Dodds is a JavaScript software engineer and teacher. He's taught hundreds of thousands of people how to make the world a better place with quality software development tools and practices. He lives with his wife and four kids in Utah.