Reactの学習をしていてCSS in JS
なるものに出会ったので、
基本的な内容ながらまとめておきたいと思います。
普通のCSS(CSSファイル形式で書いたCSS)をMATERIAL-UIのmakeStylesで書き換える、ちょっとした手がかりのつもりです。
知れること・知れないこと
知れること
- CSSファイルの形式で書かれたスタイルをMATERIAL-UIのmakeStylesで書き換える方法
知れないこと
- MATERIAL-UI以外の実装方法
-
CSS in JS
の是非
CSS in JS って?
字のごとくJSの中でCSSを書く
スタイルの一つの書き方(おそらく総称)。
フロントエンドフレームワークで出てくるコンポーネント
の概念とともに検討され始めた書き方らしいです。
ざっくり言うと、「コンポーネント単位で実装するんだったら、CSSもコンポーネント単位で書いた方がよくない?(CSSをわざわざファイル分けするのは管理上適切ではないのでは?)」と言ったことらしい。
参考
styled-componentsで変わるReactコンポーネントのスタイリング
元々のCSSの記述
※こちらのCSSファイルの内容自体は以下のサイトのものほぼほぼそのままです。
CSSで実装するタグクラウドのサンプル
.taggroup ul {
margin: 0;
padding: 0;
list-style: none;
}
.taggroup ul li {
display: inline-block;
margin: 0 .3em .3em 0;
padding: 0;
}
.taggroup ul li a {
display: inline-block;
max-width: 100px;
height: 28px;
line-height: 28px;
padding: 0 1em;
background-color: #fff;
border: 1px solid #aaa;
border-radius: 3px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
color: #333;
font-size: 13px;
text-decoration: none;
transition: .2s;
}
.taggroup ul li a:hover {
background-color: #555;
color: #fff;
}
CSSファイルで書いた場合は、
以下のようにファイルを読み込んでclassName
にクラス名を付与して利用します。
import React from 'react';
import Container from '@material-ui/core/Container';
import Grid from '@material-ui/core/Grid';
import Box from '@material-ui/core/Box';
import "./Tag.css";
const TagCss = () => {
return (
<>
<Container>
<Grid container>
<Grid item xs={12} sm={12} md={12} lg={12}>
<Box textAlign="center" mt={5}>
<Box mb={1}>CSS</Box>
<div className="taggroupcss">
<ul>
<li><a href="#">JavaScript</a></li>
<li><a href="#">React</a></li>
</ul>
</div>
</Box>
</Grid>
</Grid>
</Container>
</>
)
}
export default TagCss;
MATERIAL-UIのmakeStylesで書き換えた例
これをMATERIAL-UIのmakeStylesで書き換えると、一つのjsファイルにまとめて記載できるという寸法です。
import React from 'react';
import Container from '@material-ui/core/Container';
import Grid from '@material-ui/core/Grid';
import Box from '@material-ui/core/Box';
import { makeStyles } from '@material-ui/core';
const Tag = () => {
const classes = tagStyle();
return (
<>
<Container>
<Grid container>
<Grid item xs={12} sm={12} md={12} lg={12}>
<Box textAlign="center" mt={5}>
<Box mb={1}>makeStyles(CSS in JS)</Box>
<div className={classes.taggroup}>
<ul>
<li><a href="#">JavaScript</a></li>
<li><a href="#">React</a></li>
</ul>
</div>
</Box>
</Grid>
</Grid>
</Container>
</>
)
}
const tagStyle = makeStyles(() => ({
taggroup: {
"& ul": {
margin: "0",
padding: "0",
listStyle: "none",
"& li": {
display: "inline-block",
margin: "0 .3em .3em 0",
padding: "0",
"& a": {
display: "inline-block",
maxWidth: "100px",
height: "28px",
lineHeight: "28px",
padding: "0 1em",
backgroundColor: "#fff",
border: "1px solid #aaa",
borderRadius: "3px",
whitespace: "nowrap",
textOverflow: "ellipsis",
overflow: "hidden",
color: "#333",
fontSize: "13px",
textDecoration: "none",
transition: ".2s",
"&:hover": {
backgroundColor: "#555",
color: "#fff"
}
}
}
}
}
}));
export default Tag;
Tag
の表示例
(書き換えただけなんだからTagCss
と同じ表示のされ方をしないとおかしいですね)
書き換えのポイント
makeStyleの基本的な使い方は以下が参考になります。
React: Material-UI 4.0のコンポーネントへのCSS設定はwithStyles()からmakeStyles()に
公式
一つ目のサイトから書式の説明を拝借すると以下のような感じです。
const フック関数 = makeStyles((theme) => ({
クラス: {
プロパティ: 文字列の設定値,
// 他のプロパティの定め
},
// 他のクラス
}));
(今回前述した例は、引数のtheme
なしバージョンです)
ポイント : プロパティをキャメルケースに変更して書く
例えば
.taggroup ul {
margin: 0;
padding: 0;
list-style: none;
}
のlist-style
は、
const tagStyle = makeStyles(() => ({
taggroup: {
"& ul": {
margin: "0",
padding: "0",
listStyle: "none",
~~以下省略~~
といった風にlistStyle
に変更します。
参考 : material-uiの見た目を調整する3つの方法などなど。
また、実は、以下のようにプロパティを文字列として扱っても表示は同じになります。
const tagStyle = makeStyles(() => ({
taggroup: {
"& ul": {
margin: "0",
padding: "0",
"list-style": "none",
~~以下省略~~
最悪、元のCSSの中身を"だか'で囲みまくったら、書き換え可能ってことですね。(是非はともかく……)
〜〜〜
少し余談ですが、ベンダプレフィックス
が必要なプロパティの場合は、試した限りは文字列として扱った書き換えしかできなさそうでした。(ベンダプレフィックス
→-webkit-
など)
.exp {
-webkit-transition: .2s;
}
なんてのがあったら
const expStyle = makeStyles(() => ({
exp: {
"-webkit-transition": ".2s";
}
}));
とします。
まあ、文字列で書き換える前に、本当にベンダプレフィックス
(-webkit-
)が必要なのかどうかは見ておいた方がいいでしょうね。
参考 : そのベンダープレフィックス、いつまでつけてるの?
ポイント : 絞り込みは&を使う!
.taggroup ul li {
display: inline-block;
margin: 0 .3em .3em 0;
padding: 0;
}
上記のように、taggroupクラスを使った要素の中のulの中のliと、
スタイルを指定する範囲を絞り込んでいく場合。(割と分からなかった)
(答えはすでに書いてあるわけですが)入れ子構造にして文字列として&でつなげていけばOKです。
・上記書き換え分の抜粋
const tagStyle = makeStyles(() => ({
taggroup: {
"& ul": {
~~省略~~
"& li": {
display: "inline-block",
margin: "0 .3em .3em 0",
padding: "0",
~~省略~~
a:hover
なんかも、このやり方で記述可能です。
・a:hover
の部分の抜粋
const tagStyle = makeStyles(() => ({
taggroup: {
~~省略~~
"& a": {
~~省略~~
"&:hover": {
backgroundColor: "#555",
color: "#fff"
}
~~省略~~
ちなみに、
SCSSやSASSでスタイルを書いている人にとっては、&でつなげる
というのは割と自然な考え方のようです。
参考
[SCSS]便利な&(アンパサンド)の使い方メモ
【Sass】親セレクタを参照する&や+の使い方
その他
アニメーションの書き方にも、多少コツが必要そうです。
何度も出している参考記事
React: Material-UI 4.0のコンポーネントへのCSS設定はwithStyles()からmakeStyles()に
(こちらの記事ではひな形のアプリケーションのCSSをmakeStyleに書き換えたものが載っていて、アニメーションについても言及されています)
おわりに
「いや、別に無理して書き換えなくてもCSSのままでもいいんじゃない?」 と言う話は実際あるようですが、「CSSで書いていたものが、CSS in JS
だと全く検討もつかない!」というのは、ちょっと癪だったので、いろいろ調べてみました。
(書き換えることに集中したため詳しいCSS in JS
の是非までは追求していないです)
CSS in JS
のメリットの話(動的にスタイルを変更できるなど)といった発展的な話まではでできていませんが、最初に書いたように、この記事がmakeStyles
(その他)を使うときのちょっとした手がかりになってもらえたら嬉しいです!!
以上になります!