React: Material-UIのwithStyles()でCSSをJavaScriptコードに定める
React: Material-UIのwithStyles()でCSSをJavaScriptコードに定める:
Material-UIは、Googleの提唱するマテリアルデザインを実装したReactコンポーネントです。また、CSSのスタイルシートをJavaScriptコードに書き込む「CSS-in-JS」を採用しました。そして、そのスタイルシートをコンポーネントに組み込む関数が
Reactアプリケーションのひな形は、
アプリケーション(
これで、Material-UIを使う準備が整いました。
ReactコンポーネントにJavaScriptコードのスタイルシートを組み込む関数
スタイルシートをコンポーネントに関連づけます。引数に渡したコンポーネントそのものは変わりません。戻り値は、プロパティ
create-react-appでつくられたReactアプリケーション(
まずは、CSSファイル(
スタイルシートはオブジェクトで定めます。クラス名はプロパティとし、設定は入れ子のオブジェクトです。その中にプロパティと文字列の設定値を加えるかたちになります。
テーマを参照する場合には、スタイルシートを関数で定めます。引数にテーマ(
今回は、簡単にオブジェクトで定めましょう。ここで、JavaScriptのプロパティにはハイフン(
すると、プロパティ
これで、JavaScriptコードに定めたCSSのクラスがひとつReactアプリケーション(
クラスとプロパティの名前はキャメルケースにし、CSSの値が文字列、そしてプロパティはカンマ(
これで、アニメーションする要素(
これでひな形Reactアプリケーションのスタイルシートが、すべてJavaScriptコードに移せました。CSSファイル(
Material-UIは、Googleの提唱するマテリアルデザインを実装したReactコンポーネントです。また、CSSのスタイルシートをJavaScriptコードに書き込む「CSS-in-JS」を採用しました。そして、そのスタイルシートをコンポーネントに組み込む関数が
withStyles()
です。本稿では、この関数を使って、Reactの簡単なアプリケーションのJavaScriptコードにスタイルシートを定めてみます。
ひな形のアプリケーションにインストールする
Reactアプリケーションのひな形は、create-react-app
でつくりましょう。コマンドラインツールからつぎのように入力します。$ npx create-react-app my-app
my-app
)のディレクトリに切り替えたら、つぎにmaterial-ui
をインストールしてください。$ npm install @material-ui/core
withStyles()の構文
ReactコンポーネントにJavaScriptコードのスタイルシートを組み込む関数withStyles()
の構文を先にご紹介しましょう。
withStyles(styles, [options]) => higher-order component
スタイルシートをコンポーネントに関連づけます。引数に渡したコンポーネントそのものは変わりません。戻り値は、プロパティclasses
が備わった新たなコンポーネントです。classes
オブジェクトには、DOMに加えられたCSSのクラス名が納められています。
引数
-
styles
(Function | Object
)
スタイルをつくる関数、またはスタイルオブジェクトです。コンポーネントに関連づけられます。テーマを参照する場合には、関数で定めてください。 -
options
(Object
[省略可能])
-
options.withTheme
(Boolean
[省略可能]): デフォルト値はfalse
です。theme
オブジェクトをコンポーネントにプロパティとして与えます。 -
options.name
(String
[省略可能]): スタイルシートの名前です。デバッグに役立ちます。値がなければ、コンポーネント名へのフォールバックが試みられます。 -
options.flip
(Boolean
[省略可能]):false
にすると、スタイルシートのrtl
(Right-to-left)変換はオプトアウトされます。true
は、スタイルが左右反転します。null
の場合は、theme.direction
にしたがいます。 - その他のキーは、
jss.createStyleSheet([styles], [options])
の引数options
に渡されます。
-
戻り値
- higher-order component
ラップされてプロパティclassesが備わったコンポーネントです。
CSSのスタイルをJavaScriptコードに移す
create-react-appでつくられたReactアプリケーション(src/App.js
)に、withStyles()
をimport
します。そして、CSSファイル(src/App.css
)は除いてしまいましょう。これで、一旦スタイルシートは適用されなくなりました。src/App.js
import { withStyles } from '@material-ui/core/styles'; // import './App.css';
src/App.css
)からクラスの定めをひとつ(App
)、JavaScriptコードに移してみます。src/App.css
.App { text-align: center; }
const スタイルシート = { クラス: { プロパティ: 文字列の設定値, // 他のプロパティの定め }, // 他のクラス }
theme
)を受け取り、戻り値がスタイルシートオブジェクトです。const スタイルシート = (theme) => { クラス: { プロパティ: 文字列の設定値, // 他のプロパティの定め }, // 他のクラス }
-
)が使えないことにご注意ください。クラスやプロパティのハイフンは除いて、キャメルケースにしなければなりません。そして、スタイルシート(styles
)はwithStyles()
の引数にして呼び出し、戻り値のラップしたコンポーネントにReactコンポーネント(App
)を渡します。すると、プロパティ
props
にclasses
が備わって、スタイルシートに定めたクラスを参照できるようになります。それをrender()
が返すマークアップ(テンプレート)のclassName
に与えればよいのです。src/App.js
const styles = { app: { textAlign: 'center' } } class App extends Component { render() { return ( <div className={this.props.classes.app}> </div> ); } } // export default App; export default withStyles(styles)(App);
src/App.js
)に割り当てられました。同じ要領で、CSSファイル(src/App.css
)の他のクラスも移していきましょう。ただし、animation
が使われているクラス(App-logo
)はあとに回します。src/App.css
.App-logo { animation: App-logo-spin infinite 20s linear; height: 40vmin; } .App-header { background-color: #282c34; min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; font-size: calc(10px + 2vmin); color: white; } .App-link { color: #61dafb; }
,
)区切りになることに注意してください。src/App.js
const styles = { appHeader: { backgroundColor: '#282c34', minHeight: '100vh', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', fontSize: 'calc(10px + 2vmin)', color: 'white' }, appLink: { color: '#61dafb' } }; class App extends Component { render() { return ( <div className={this.props.classes.app}> <header className={this.props.classes.appHeader}> <a className={this.props.classes.appLink} > </a> </header> </div> ); } }
<img>
)以外のスタイルは整いました。
animationを定める
animation
プロパティには@keyframes
規則が加えられています。これは、@keyframes キーフレーム名
までをひとつの文字列としてスタイルオブジェクトのプロパティに定めてください。src/App.css
.App-logo { animation: App-logo-spin infinite 20s linear; height: 40vmin; } @keyframes App-logo-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes
規則の中身は、つぎのように入れ子のオブジェクトです。パーセンテージ(%
)を用いる場合には、頭が数字になるため文字列で定めてください。src/App.js
const styles = { '@keyframes App-logo-spin': { from: { transform: 'rotate(0deg)' }, to: { transform: 'rotate(360deg)' } }, appLogo: { animation: 'App-logo-spin infinite 20s linear', height: '40vmin' }, }; class App extends Component { render() { return ( <div className={this.props.classes.app}> <header className={this.props.classes.appHeader}> <img src={logo} className={this.props.classes.appLogo} alt="logo" /> </header> </div> ); } }
src/App.css
)はもう要りません。JavaScriptファイル(src/App.js
)の中身を改めて以下にまとめて掲げます。src/App.js
import React, { Component } from 'react'; import { withStyles } from '@material-ui/core/styles'; import logo from './logo.svg'; const styles = { app: { textAlign: 'center' }, '@keyframes App-logo-spin': { from: { transform: 'rotate(0deg)' }, to: { transform: 'rotate(360deg)' } }, appLogo: { animation: 'App-logo-spin infinite 20s linear', height: '40vmin' }, appHeader: { backgroundColor: '#282c34', minHeight: '100vh', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', fontSize: 'calc(10px + 2vmin)', color: 'white' }, appLink: { color: '#61dafb' } }; class App extends Component { render() { return ( <div className={this.props.classes.app}> <header className={this.props.classes.appHeader}> <img src={logo} className={this.props.classes.appLogo} alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <a className={this.props.classes.appLink} href="https://reactjs.org" target="_blank" rel="noopener noreferrer" > Learn React </a> </header> </div> ); } } export default withStyles(styles)(App);
コメント
コメントを投稿