
Reactを中心とするコンポーネントベースのWebアプリケーション開発は、CSSをモジュール化しようとする動きにも影響を与えています。今回はReactのStyled Componentsを簡単に試してみましょう。(2019/2/1にアップデートしました)
はじめに
CSSのモジュール化の流れは自然な発想です。そもそもCSSはグローバルスコープであるため、あるCSSファイルに書いた内容は全てのCSSファイルに影響を及ぼします。誰かが書いたCSSを見てどれがどこに影響を及ぼしているかの全容を把握するのはそもそも難しいのです。そこで近年、SASS等のCSSフレームワークやBEM等の命名規約を用いることでローカルスコープっぽく扱おうとするモジュール化の動きが盛んになりました。そして最近ではCSS Modulesがよく使われるようになってきました。Webpackのcss-loaderのmoduleオプションを有効にすることで、CSSのクラス名を一意に変換し、あるReactコンポーネント用のCSSファイルが他のCSSファイルに影響を及ぼすことを回避できるようになりました。そして、次のパラダイムとして、CSSを完全にコンポーネントに閉じ込めることでJavascriptの力を引き出す方法がCSS in JSであり、Reactでそれを実現したのがStyled Componentsです。
今回はcreate-react-appで作成したアプリケーションを元に、まずはCSS Modulesを適用し、その後でStyled Componentsを適用して違いを見ていきましょう。
CSS Modulesの適用
まずはCSS Modulesを使ってcreate-react-appで自動生成されたサンプルアプリケーションを書き直してみましょう。
準備
それではcreate-react-appでサンプルアプリケーションを作り、CSS Modulesを有効化しましょう。
$ create-react-app my-css-modules-app
$ cd my-css-modules-app
$ yarn eject
$ yarn install
$ vi config/webpack.config.dev.js
...
{
loader: require.resolve('css-loader'),
options: {
modules: true, // 追加
importLoaders: 1,
localIndentName: '[name]__[local]__[hash:base64:5]' // 追加
},
},
...
index.js
index.cssの内容をCSS Modulesで書き直します。
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import styles from './index.css';
ReactDOM.render(<App className={styles} />, document.getElementById('root'));
registerServiceWorker();
App.js
CSS Modulesで書き直しましょう。
import React, { Component } from 'react';
import logo from './logo.svg';
import styles from './App.css';
class App extends Component {
render() {
return (
<div className={styles.App}>
<header className={styles['App-header']}>
<img src={logo} className={styles['App-logo']} alt="logo" />
<h1 className={styles['App-title']}>Welcome to React</h1>
</header>
<p className={styles['App-intro']}>
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
);
}
}
export default App;
動作確認
元のスタイルが反映されていることを確認しましょう、
$ yarn start
OKですね。CSSのクラス名に一意の値が自動的に設定されています。
Styled Componentsの適用
それでは、いよいよStyled Componentsを使ってcreate-react-appで自動生成されたサンプルアプリケーションを書き直してみましょう。
準備
create-react-appでサンプルアプリケーションを作り、必要なパッケージをインストールしましょう。
$ create-react-app my-styled-components-app
$ cd my-styled-components-app
$ yarn add styled-components
index.js(old)
index.cssの内容をinjectGlobalを使って書き直します。
import React from 'react';
import ReactDOM from 'react-dom';
import { injectGlobal } from 'styled-components';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
injectGlobal`
body {
margin: 0;
padding: 0;
font-family: sans-serif;
}
`;
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
App.js(old)
Styled Componentsを使って書き直しましょう。
import React, { Component } from 'react';
import styled, { keyframes } from 'styled-components';
import logo from './logo.svg';
const AppWrapper = styled.div`
text-align: center;
`;
const AppHeader = styled.header`
background-color: #222;
height: 150px;
padding: 20px;
color: white;
`;
const rotate360 = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`;
const AppLogo = styled.img.attrs({
src: logo,
alt: 'logo',
})`
animation: ${rotate360} infinite 20s linear;
height: 80px;
`;
const AppTitle = styled.h1`
font-size: 1.5em;
`;
const AppIntro = styled.p`
font-size: large;
`;
class App extends Component {
render() {
return (
<AppWrapper>
<AppHeader>
<AppLogo />
<AppTitle>Welcome to React</AppTitle>
</AppHeader>
<AppIntro>
To get started, edit <code>src/App.js</code> and save to reload.
</AppIntro>
</AppWrapper>
);
}
}
export default App;
index.js(new)
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
App.js(new)
Styled Componentsを使って書き直しましょう。index.cssの内容はcreateGlobalStyleを使って書き直します。
import React, { Component } from 'react';
import styled, { createGlobalStyle, keyframes } from 'styled-components';
import logo from './logo.svg';
const GlobalStyle = createGlobalStyle`
body {
margin: 0;
padding: 0;
font-family: sans-serif;
}
`;
const AppWrapper = styled.div`
text-align: center;
`;
const AppHeader = styled.header`
background-color: #222;
height: 150px;
padding: 20px;
color: white;
`;
const rotate360 = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`;
const AppLogo = styled.img.attrs({
src: logo,
alt: 'logo',
})`
animation: ${rotate360} infinite 20s linear;
height: 80px;
`;
const AppTitle = styled.h1`
font-size: 1.5em;
`;
const AppIntro = styled.p`
font-size: large;
`;
class App extends Component {
render() {
return (
<>
<AppWrapper>
<AppHeader>
<AppLogo />
<AppTitle>Welcome to React</AppTitle>
</AppHeader>
<AppIntro>
To get started, edit <code>src/App.js</code> and save to reload.
</AppIntro>
</AppWrapper>
<GlobalStyle />
</>
);
}
}
export default App;
動作確認
CSSファイルを削除しても元のスタイルが反映されていることを確認しましょう、
$ rm src/index.css
$ rm src/App.css
$ yarn start
表示もアニメーションもOKです。CSSのクラス名には一意の値が自動的に設定され、スタイルが正しく適用されています。
最後に
いかがでしたか?Styled Componentsをざっくりではありますが、理解できたのではないでしょうか。新しいプロジェクトでは積極的に使っていきましょう。では。
環境
- create-react-app: 1.5.2
- yarn: 1.9.4 -> 1.13.0
- styled-components: 3.4.5 -> 4.1.3