Skip to content
Style your React components with Hooks
Branch: master
Clone or download
Latest commit 028d1a0 Mar 26, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
example
src Rename to styled-hooks Mar 22, 2019
static Filter Mar 26, 2019
.gitignore 1.0.0 Mar 14, 2019
.prettierrc Add pretter config Mar 20, 2019
CODE_OF_CONDUCT.md
CONTRIBUTING.md Create centered README header, including useful badges. Update projec… Mar 25, 2019
LICENSE 1.0.0 Mar 14, 2019
README.md
package-lock.json Add release script Mar 26, 2019
package.json Release 1.5.3 Mar 26, 2019
tsconfig.json

README.md

Styled Hooks

Style your React components with Hooks

NPM latest published version GZip size Formats: CommonJS, ECMAScript Modules

Table of contents

Getting started

npm install styled-hooks
import { useStyle } from 'styled-hooks';
import React from 'react';
import ReactDOM from 'react-dom';

function Paragraph({ color, ...props }) {
  const cn = useStyle`
    padding: 1rem;
    background-color: yellow;
    color: ${color};
  `;

  return <p className={cn} {...props} />;
}

ReactDOM.render(
  <div>
    <Paragraph color="magenta">I'm magenta</Paragraph>
    <Paragraph color="blue">I'm blue</Paragraph>
  </div>,
  document.getElementById('root')
);

remix button

The rendered page will look like this:

<!-- In <head /> -->
<style>
  .gtXozB {
    padding: 1rem;
    background-color: yellow;
    color: var(--gtXozB-0);
  }
</style>
<style>
  .gqAIHm {
    --gtXozB-0: blue;
  }
</style>
<style>
  .eKigJM {
    --gtxozb-0: magenta;
  }
</style>

<!-- In <div id="root" /> -->
<div>
  <p class="gtXozB gqAIHm">I'm blue</p>
  <p class="gtXozB eKigJM">I'm magenta</p>
</div>

Image of blue and magenta paragraphs with yellow backgrounds

“Wait. Those are CSS Custom Properties. I thought they didn't work everywhere?”

Don't worry! Styled Hooks will render the following in browsers that aren't up to scratch:

<!-- In <head /> -->
<style>
  .efNhRD {
    padding: 1rem;
    background-color: yellow;
    color: blue;
  }
</style>
<style>
  .kGJulO {
    padding: 1rem;
    background-color: yellow;
    color: magenta;
  }
</style>

<!-- In <div id="root" /> -->
<div>
  <p class="efNhRD">I'm blue</p>
  <p class="kGJulO">I'm magenta</p>
</div>

The amount of CSS generated is larger, but it acheives the same effect.

If you want to use this output in all browsers, use the useStyleWithoutCustomProps hook.

On the other hand, if you can guarantee your app wont be run in older browsers, you can skip the support check by using the useStyleWithCustomProps hook directly.

API

useStyle

The useStyle hook is a tagged template that expects CSS & dynamic values, and returns a className you can use in your component.

The hook will memoise the CSS each unique style variant, and inject it into your document's <head>, taking advantage of CSS Custom Properties (if your browser suports them) to reduce style replication.

Style injection happens during the browser's layout phase, so your components will always be painted fully-styled.

Thanks to stylis, you can use some basic nesting and media queries:

import { useStyle } from 'styled-hooks';
import React from 'react';
import ReactDOM from 'react-dom';

function Button({ primary, ...props }) {
  const cn = useStyle`
    display: inline-block;
    padding: 0.5rem 0;
    width: 10rem;
    background-color: ${primary ? 'magenta' : 'yellow'};
    color: ${primary ? 'yellow' : 'magenta'};
    border: 0.125rem solid ${'magenta'};

    @media (min-width: 32rem) {
      padding: 0.75rem 0;
      width: 15rem;
      font-size: 1.5rem;
    }

    &:focus {
      color: #000;
      border-color: #000;
    }
  `;

  return <button className={cn} {...props} />;
}

ReactDOM.render(
  <div>
    <Button>Standard</Button>
    <Button primary>Primary</Button>
  </div>,
  document.getElementById('root')
);

remix button

useTheme

The useTheme hook allows you to read the theme context from the nearest <ThemeProvider /> ancestor:

import { useStyle, useTheme, ThemeProvider } from 'styled-hooks';
import React from 'react';
import ReactDOM from 'react-dom';

function Paragraph({ ...props }) {
  const { fg, bg } = useTheme();

  const cn = useStyle`
    padding: 1rem;
    background-color: ${bg};
    color: ${fg};
  `;

  return <p className={cn} {...props} />;
}

ReactDOM.render(
  <ThemeProvider theme={{ fg: 'magenta', bg: 'yellow' }}>
    <Paragraph>I'm magenta on yellow</Paragraph>
  </ThemeProvider>,
  document.getElementById('root')
);

remix button

Combine this with React's useState hook, and you'll be able to modify the theme on the fly:

import { useStyle, useTheme, ThemeProvider } from 'styled-hooks';
import React, { useState } from 'react';
import ReactDOM from 'react-dom';

function Button({ primary, ...props }) {
  const { fg, bg } = useTheme();

  const cn = useStyle`
    padding: 0.5rem;
    background-color: ${primary ? fg : bg};
    color: ${primary ? bg : fg};
    border: 0.125rem solid ${fg};
  `;

  return <button className={cn} {...props} />;
}

function App() {
  const [theme, setTheme] = useState({
    fg: 'magenta',
    bg: 'yellow'
  });

  const invertTheme = () =>
    setTheme({
      bg: theme.fg,
      fg: theme.bg
    });

  return (
    <ThemeProvider theme={theme}>
      <div>
        <Button onClick={invertTheme}>Invert Theme</Button>
        <Button onClick={invertTheme} primary>
          Invert Theme
        </Button>
      </div>
    </ThemeProvider>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));

remix button

About the project

You can’t perform that action at this time.