Material-UI makeStyles でネストした要素にクラス名でスタイルを適用したい


こんにちは、 Gaji-Labo フロントエンドエンジニアの鈴木です。

タイトルの通りですが、Material-UI を使ったコンポーネントで makeStyles 使用時、ネストした要素にクラス名でスタイルを当てるのに少しハマりました。

無事解決できたのでサンプルコードを残しておこうと思います。

実現したい事

実現したかったことは「ある要素に hover したら、その子要素に変化を与えたい」でした。このサンプルでは要素を表示したい、です。

HTML / SCSS でのサンプル

Material-UI でのサンプルコードの前に、まずは HTML / SCSS でのサンプルを用意しました。

<div class="contents">
  <p>
   このグレーのエリアに hover したら ⭐️ が表示される
  </p>
  <div class="icon">⭐️⭐️⭐️</div>
</div>
.icon {
  display: none;
}

.contents {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background-color: #ddd;

  &:hover {
    .icon {
      display: block;
    }
  }
}

Material-UI コンポーネントでの実装

次に Material-UI での実装方法を解説します。
ネストした要素のクラスセレクター は "& $icon" と指定します。

const useStyles = makeStyles({
  contents: {
    display: "flex",
    alignItems: "center",
    justifyContent: "space-between",
    backgroundColor: "#ddd",

    "&:hover": {
      backgroundColor: "#eee",

      "& $icon": {
        display: "block",
      },
    },
  },

  icon: {
    display: "none",
  },
});

export function SomethingComponent(): ReactElement | null {
  const classes = useStyles();

  return (
    <div className={classes.contents}>
      <p>このグレーのエリアに hover したら ⭐️ が表示される</p>
      <div className={classes.icon}><Icon name="star" /></div>
    </div>
  );
}

コンパイル結果はこのようになります。
.makeStyles-contents-666:hover .makeStyles-icon-665 { }

実現するにあたっての条件

この実装をするにあたり条件がありました。

要素型セレクターではなくクラスセレクターで書きたい

要素型セレクターで逃げることもできますが、既存プロジェクトのコードに沿うことと、より安全な選択をしたかったです。
要素型セレクターで書く場合は以下のようにできます。

foo: {
  "&:hover": {
    "& > span": {
      display: "block",
    },
  },
},

ハマったのは "& $ruleName" これで実現できることに気づけなかった

調べている間に公式ドキュメントも読んでいたのですが、解決方法を探している時って読んでいるようで読んでいない時があります。(焦っているだけですね)

contents: {
  "&:hover": {
    "& $icon": {
      display: "block",
    },
  },
},

公式ドキュメントたち

一文さらっと書いてあるこちらです。そして jss-nested プラグインと書かれています。

ここにしっかり書かれていました。

const styles = {
  container: {
    // Reference the local rule "button".
    '& $button': {
      padding: '10px'
    },
    // Multiple local refs in one rule.
    '&:hover $button, &:active $button': {
      color: 'red'
    },
    '&:focus $button': {
      color: 'blue'
    }
  },
  button: {
    color: 'grey'
  }
}

おわりに

実はひたすら「materialui makestyles nest styles」などでググってみたのですが、なかなか辿り着けませんでした。

いっそ、実現したいことをそのまま自動翻訳しようと「Apply styles to nested elements with makeStyles」で検索したところ見つかりました。

そしていつも通り公式ドキュメントで答え合わせした流れです。

Gaji-Laboでは、React経験が豊富なフロントエンドエンジニアを募集しています

弊社ではReactの知見で事業作りに貢献したいフロントエンドエンジニアを募集しています。大きな制作会社や事業会社とはひと味もふた味も違うGaji-Laboを味わいに来ませんか?

もちろん、一緒にお仕事をしてくださるパートナーさんも随時募集中です。まずはお気軽に声をかけてください。お仕事お問い合わせや採用への応募、共に大歓迎です!

求人応募してみる!

タグ


投稿者 Gaji-Labo Staff

Gaji-Laboの社内デジタル環境でいろいろなお手伝いをしているがじ専務&じら常務。みんなのシリーズ記事をまとめたり、卒業したスタッフの過去記事を記録したり、Twitterをやったりしています。