あまり知られていないかもしれない、CSS-in-JSを実装するライブラリでできる5つの便利なテクニック
Post on:2018年11月6日
CSS-in-JSはJavaScriptを使用してコンポーネントをスタイルするテクニックです。
Reactには従来のCSSに加えて、スタイリングのオプションとして、インラインスタイルとCSS-in-JSがあります。
CSS-in-JSを実装するライブラリでできる5つの便利なテクニックを紹介します。
5 things you can do in CSS-in-JS that you didn’t know about
originally published at LogRocket
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
- はじめに
- 1. 他のスタイル付きコンポーネントを参照
- 2. ライブラリの機能をJSSで拡張
- 3. 複数のアニメーションをキーフレームで連結
- 4. グローバルスタイルを宣言
- 5. スタイルによるコンポーネントのテスト
- まとめ
はじめに
Reactには従来のCSSに加えて、スタイリングのオプションとして、インラインスタイルとCSS-in-JSがあります。
インラインスタイルでは、JavaScriptオブジェクトをstyle属性に渡すことができます。
1 2 3 4 5 6 7 |
const myStyle = { fontSize: 24, lineHeight: '1.3em', fontWeight: 'bold', }; <span style={myStyle}>Hello World!</p> |
しかしながら、CSSのすべての機能がサポートされているわけではありません。
そして、CSS-in-JSはJavaScriptを使用してコンポーネントをスタイルするテクニックです。JavaScriptが解析されると、CSSが生成され(通常は<style>要素として)、DOMに付加されます。
この機能はサードパーティのライブラリによって実装されています。例えば、Aphroditeで実装された例を見てましょう。
1 2 3 4 5 6 7 8 9 10 |
import { StyleSheet, css } from 'aphrodite'; const styles = StyleSheet.create({ myStyle: { fontSize: 24, lineHeight: '1.3em', fontWeight: 'bold', } }); <span className={css(styles.myStyle)}>Hello World!</p> |
私が推奨するライブラリは、下記の通りです。
CSS-in-JSを私は全面的に支持しているわけではありませんが、これらのライブラリは特定の状況で役立つ機能をサポートしてます。
この記事では、CSS-in-JSのあなたが知らなかったと思われる上記のライブラリでできる5つのテクニックについて説明します。
1. 他のスタイル付きコンポーネントを参照
Styled-Componentsやemotionのようなライブラリでは、ES6 Tagged Template Literalsを使ってスタイルからReactコンポーネントを作成することができます。
1 2 3 4 5 6 7 |
import styled from 'styled-components'; // Create a component that renders a <p> element with blue text const BlueText = styled.p` color: blue; `; <BlueText>My blue text</BlueText> |
ただし、CSSセレクタを使用していた場合など、他のスタイル付きコンポーネントをターゲットにすることもできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
const ImportantText = styled.div` font-weight: bold; `; const Text = styled.div` color: gray; ${ImportantText} { font-style: italic; } `; render( <div> <Text> Text in gray <ImportantText>Important text in gray, bold and italic</ImportantText> </Text> <ImportantText>Important text bold</ImportantText> </div> ); |
これは例えば、ホバー時にコンポーネントのカラーを変更するなど、擬似クラスを組み合わせる場合に便利です。
1 2 3 4 5 6 |
const Text = styled.div` color: gray; &:hover ${ImportantText} { color: red; } `; |
2. ライブラリの機能をJSSで拡張
Aphroditeを使ってアプリケーションのスタイルを設定し、テーマをサポートする必要があるとします。ここで問題になるのは、Aphroditeが簡単な方法でテーマをサポートしていないということです。少なくとも、emotionほど、簡単ではありません。
しかしながら、JSSのコアとAphroditeとのスタイル付きコンポーネントをつなぐ2つのプロジェクトがあります、aphrodite-jss、styled-jssです。
この方法でAphrodite(またはスタイル付きコンポーネント)の優れた部分はそのままで、すべての機能とJSSのプラグイン、キャッシュ(cache)から隔離(isolate)まで、そしてテーマ用に、テーマのパッケージなど、優れたコンポーネントを提供できます。
-
- ThemeProvider
- テーマオブジェクトをReactツリーに渡します。
-
- withTheme
- テーマオブジェクトとアップデートをプロパティとして受け取ることができます。
以下、例です。
1 2 3 4 5 6 7 8 9 |
const blackTheme = { color: 'black', }; const App = () => ( <ThemeProvider theme={blackTheme}> <MyComponent /> </ThemeProvider> ); |
Aphroditeとテーマの特別なケースではもう一つの例として、スタイルを定義するときにテーマ情報にアクセスするために、AphroditeやJSSなどと相互に作用するreact-with-stylesを使用することもできます。
3. 複数のアニメーションをキーフレームで連結
インラインスタイルとは異なり、CSS-in-JSではキーフレームを使用してアニメーションを定義できます。スタイル付きコンポーネントでどのように実装できるか見てましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
const heightAnimation = keyframes` 0% { height: 0; } 100% { height: 200; } `; const myComponent = styled.div` display: inline-block; width: 200; position: relative; animation-name: ${heightAnimation}; animation-duration: 1.5s; animation-timing-function: ease; `; |
あまり知られていないのは、アニメーションのプロパティで複数のキーフレームオブジェクトを使用して複数のアニメーションを連結できることです。
この例では、2つのアニメーションを組み合わせています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
const heightAnimation = keyframes` 0% { height: 0; } 100% { height: 200; } `; const rotateAnimation = keyframes` 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } `; const myComponent = styled.div` display: inline-block; width: 200; position: relative; animation: ${props => css` ${heightAnimation} 1.5s ease infinite, ${rotateAnimation} 1.5s linear infinite `} `; |
RadiumはanimationNameプロパティの値としてキーフレームオブジェクトの配列を渡すことによって、複数のアニメーションをサポートするもう一つのライブラリです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
const heightAnimation = Radium.keyframes( { 0% { height: 0; } 100% { height: 200; } }, 'myHeightAnimation', ); const rotateAnimation = Radium.keyframes( { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }, 'myRotateAnimation', ); const styles = { myStyle: { animationName: [heightAnimation, rotateAnimation], animationDuration: '1.5s, 1s', animationIterationCount: 'infinite, infinite', animationTimingFunction: 'ease, linear', display: inline-block; width: 200; position: relative; }, }; |
4. グローバルスタイルを宣言
CSSのすべてはグローバルであり、CSS-in-JSを使用する目的の1つは、グローバルスタイルの定義を取り除くことです。ただし、ページ内のすべての要素に同じフォントスタイルを適用する場合など、グローバルスタイルを有効に使用することもできます。
もちろん、従来のCSSをいつでもWebpackでインポートしたり、index.htmlファイルで宣言したりすることもできます。
しかし、すべてのスタイルにJavaScriptを使用することを検討するなら、コンポーネントや拡張機能・プラグインを使ってグローバルスタイルを定義できるライブラリがあります。Radiumでは、Style Componentを使用して、スタイルされた要素をグローバルスタイルでレンダリングできます。
例を見てましょう。
1 2 3 4 5 6 7 |
<Style rules={{ body: { fontFamily: 'Arial, Helvetica, sans-serif' } }} /> |
上記のコードは、下記を返します。
1 2 3 4 5 |
<style> body { font-family: 'Arial, Helvetica, sans-serif'; } </style> |
JSSではプラグインを使用して、グローバルスタイルを定義します。
1 2 3 4 5 |
<style> body { font-family: 'Arial, Helvetica, sans-serif'; } </style> |
また、Aphroditeではサードパーティの拡張機能を使用します。
1 2 3 4 5 6 7 |
import {injectGlobalStyles} from "aphrodite-globals"; injectGlobalStyles({ "body": { fontFamily: 'Arial, Helvetica, sans-serif', } }); |
あるいは、AphroditeのAPIのような機能を備えたaphrodite-jssというJSSのプラグインを使用します。
5. スタイルによるコンポーネントのテスト
一部のライブラリには、スタイルでコンポーネントをテストするためのユーティリティが含まれています.
Aphroditeは、非生産の環境(process.env.NODE_ENV !== 'production')でのみ利用可能で、3つのメソッドを持っていますが、ドキュメント化されていない(少なくともこの執筆時点で)オブジェクトStyleSheetTestUtilsを提供しています。
-
- suppressStyleInjection
- DOMにスタイルが挿入されるのを防ぎます。DOMを持たないときに、Aphroditeコンポーネントの出力をテストしたいときに便利です。
-
- clearBufferAndResumeStyleInjection
- suppressStyleInjectionとは逆で、ペアにする必要があります。
-
- getBufferedStyles
- バッファリングされたスタイルの文字列を返します。
これらをどのように使用するのか、見てましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import { StyleSheetTestUtils, css } from 'aphrodite'; //... beforeEach(() => { StyleSheetTestUtils.suppressStyleInjection(); }); afterEach(() => { StyleSheetTestUtils.clearBufferAndResumeStyleInjection(); }); test('my test', () => { const sheet = StyleSheet.create({ background: { backgroundColor: 'blue' }, }); css(sheet.background); // buffer will contain something like [ ".background_k554e1{background-color:blue !important;}" ] const buffer = StyleSheetTestUtils.getBufferedStyles(); // ... }); |
RadiumだとTestModeがあり、clearState, enable, disableなどのメソッドを使用してテスト中の内部状態や動作を制御できます。
実際のコードは、media-query-test.jsで見つけることができます。
まとめ
CSS-in-JSは、JavaScriptを使ってアプリケーションをスタイルするためのテクニックであり、それを実装するライブラリでいろいろな面白いことができます。この記事では、これらのライブラリを使ってできることを5つ紹介しました。
もちろん、すべてのライブラリで可能ということではなく、特定のライブラリだけ可能というものもあります。
CSS-in-JSのライブラリをテストして、比較するには下記のサイトが便利です。
逆に、CSSやJavaScriptのコンセプトを深めるライブラリもあります。
そのうちの一つはStylableで、コンポーネントベースのライブラリです。CSSをクロスブラウザ対応で、最小限のCSSに変換するプリプロセッサを備えています。
最後に、CSS-in-JSの素晴らしいプレゼンテーションを紹介します。
sponsors