LoginSignup
53
34

More than 3 years have passed since last update.

CSSをMATERIAL-UIのmakeStylesで書き換える

Posted at

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の記述

以下のようなタグのスタイルを今回対象にしてみます。
css2.gif

※こちらのCSSファイルの内容自体は以下のサイトのものほぼほぼそのままです。
CSSで実装するタグクラウドのサンプル

tag.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にクラス名を付与して利用します。

TagCss.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 "./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;

TagCssの表示例をもう一度
css2.gif

MATERIAL-UIのmakeStylesで書き換えた例

これをMATERIAL-UIのmakeStylesで書き換えると、一つのjsファイルにまとめて記載できるという寸法です。

Tag.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.gif

書き換えのポイント

makeStyleの基本的な使い方は以下が参考になります。
React: Material-UI 4.0のコンポーネントへのCSS設定はwithStyles()からmakeStyles()に
公式

一つ目のサイトから書式の説明を拝借すると以下のような感じです。

const フック関数 = makeStyles((theme) => ({
  クラス: {
    プロパティ: 文字列の設定値,
    // 他のプロパティの定め
  },
  // 他のクラス
}));

(今回前述した例は、引数のthemeなしバージョンです)

ポイント : プロパティをキャメルケースに変更して書く

例えば

tag.css
.taggroup ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

list-styleは、

tag.js
const tagStyle = makeStyles(() => ({
    taggroup: {
        "& ul": {
            margin: "0",
            padding: "0",
            listStyle: "none",
~~以下省略~~

といった風にlistStyleに変更します。
参考 : material-uiの見た目を調整する3つの方法などなど。

また、実は、以下のようにプロパティを文字列として扱っても表示は同じになります。

tag.js
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-)が必要なのかどうかは見ておいた方がいいでしょうね。
参考 : そのベンダープレフィックス、いつまでつけてるの?

ポイント : 絞り込みは&を使う!

tag.css
.taggroup ul li {
    display: inline-block;
    margin: 0 .3em .3em 0;
    padding: 0;
}

上記のように、taggroupクラスを使った要素の中のulの中のliと、
スタイルを指定する範囲を絞り込んでいく場合。(割と分からなかった)

(答えはすでに書いてあるわけですが)入れ子構造にして文字列として&でつなげていけばOKです。
・上記書き換え分の抜粋

tag.js
const tagStyle = makeStyles(() => ({
    taggroup: {
        "& ul": {
           ~~省略~~
            "& li": {
                display: "inline-block",
                margin: "0 .3em .3em 0",
                padding: "0",
           ~~省略~~

a:hoverなんかも、このやり方で記述可能です。
a:hoverの部分の抜粋

tag.js
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の是非までは追求していないです:sweat_smile:

CSS in JSのメリットの話(動的にスタイルを変更できるなど)といった発展的な話まではでできていませんが、最初に書いたように、この記事がmakeStyles(その他)を使うときのちょっとした手がかりになってもらえたら嬉しいです!!

以上になります!

53
34
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
53
34