• ..

React

    要素を作る

    styled

    styled-componentsからstyled(default)をインポートして使います。styled[htmlタグ名]にはそれぞれタグ付けテンプレート構文になっているのでここに CSS を書いていくだけでスタイル付けした要素を作ることができます。実際には

    1. 定義した CSS にstyled-componentsが適当なクラス名を振る
    2. それを実際に使っている要素のclassNameに指定する

    といった感じのことをやっています。

    以下はスタイル付けdiv要素を作っている例です。

    import styled from 'styled-components';
    
    const StyledDiv = styled.div`
      padding: 1em;
    `;
    
    <StyledDiv>foo</StyledDiv>

    作られた要素はそのまま React コンポーネントとして使うことができます。

    動的スタイル・動的属性

    普通の React コンポーネントがpropsを渡せるようにstyled-componentsで作った要素にもpropsを扱える仕組みがあります。それにはタグ付けテンプレート構文の中に関数を埋め込みます。関数を埋め込むとそれにはpropsが渡ってくるのでそれを好きなように触って目的の値を返すようにします。

    const MARGIN = '1em';
    
    const StyledDiv = styled.div`
      padding: ${props => props.padding || 0};
      margin: ${MARGIN};
    `;
    
    <StyledDiv padding="1em">foo</StyledDiv>
    // padding: 1em;
    // margin: 1em;

    ちなみに埋め込みには関数以外を指定するとそのまま出力されます。

    属性の場合は、attrsというメソッドがあるのでこれでpropsを受け取るコールバックを定義します。以下はtitle属性値を少し編集してる例ですが、このように好きな属性値のオブジェクトを返すようにするといいです。

    const StyledDiv = styled.div.attrs(props => {
      return {
        title: `edited ${props.title}`
      }
    })`
      // ...
    `;

    共通スタイル

    styled-componentsが提供しているcssヘルパーを使うことで共通部分を分けることができます。特にpropsを扱いたいときの共通部分の切り出しには必須です。

    import styled, {css} from 'styled-components';
    
    const common = css`
      padding: ${props => props.padding || 0};
    `;
    
    const StyledFooDiv = styled.div`
      ${common};
      margin: 1em;
    `;
    
    const StyledBarDiv = styled.div`
      ${common};
      margin: 2em;
    `;

    テーマ

    親階層でThemeProviderコンポーネントを使うことでそれ以下のすべてのstyled要素のprops.themeに値を渡せます。全体を通して一貫した動的な値を渡すことができます。

    import styled, {ThemeProvider} from 'styled-components';
    
    const StyledDiv = styled.div`
      padding: ${props => props.theme.padding || 0};
    `;
    
    const App = () => (
      <StyledDiv />
    );
    
    const Root = () => (
      <ThemeProvider theme={{padding: '1em}}>
        <App />
      </ThemeProvider>
    );
    
    <Root />