33
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Ateam Brides Inc.Advent Calendar 2019

Day 20

Vueで使えるCSS in JSを調べてみた

Last updated at Posted at 2019-12-19

この記事はAteam Brides Inc. Advent Calendar 2019 20日目の記事です。

本日はWebデザイナーの@naomunaomuが担当いたします。
2回目の登場です☺️

背景

VueのScoped CSSは非常に便利だと思うのですが、スタイルがバッティングするなどの懸念点もあり、結局BEMから抜け出せない感じがなんだかなあ・・と思っていたり。

参考
Vue.jsのscoped CSSは意外とバッティングする - Qiita

「CSSのグローバルスコープ問題を解決し、脱BEMしたい・・」

その銀の弾丸としてCSS in JSがあるのではないか。と淡い期待を込めて調べてみたところ、Vueの場合、Scoped CSSやUIフレームワークのおかげで、CSS in JSの参考例が少なく困ってしまいました・・ 

Reactを先に学んだ自分は、「Reactのstyled-componentsってVueでも使えるの?」「Scss以外の選択肢を知っておきたい」と単純に気になったんですよね

というわけで紹介していきます!

そもそもCSS in JSってなに

その名の通り、JSをつかってスタイルを表現することが可能です。

よく勘違いされますが、インラインで展開されるスタイルとは別物です。
CSS in JSは<style>がDOMのTOPに表示されますし、
インラインでは使えない、:beforeなどの擬似要素も使えます。
そして、CSSにローカルスコープが付与できるんです。*ひゃっほー!*🎉

styled-compornent

GitHub - styled-components/vue-styled-components: Visual primitives for the component age. A simple port for Vue of styled-components 💅

Reactで使われてる方が多いかと思いますが、実はvueにもあります
JSで受け取ったpropsの値でCSSに当てられるところが最高です!

Vue<=>Reactを行き来させる予定のある場合、統一した書き方ができるところもGoodですね

<styled-button>Normal</styled-button>
<styled-button primary>Primary</styled-button>

タグ付きテンプレートリテラルを使用し、JS内にCSSを書きます。

<script>
import styled from 'vue-styled-components';

const btnProps = { primary: Boolean };

//scriptタグの中にスタイルを書きます
const StyledButton = styled('button', btnProps)`
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
  background: ${props => props.primary ? 'palevioletred' : 'white'};
  color: ${props => props.primary ? 'white' : 'palevioletred'};
`;

export default StyledButton;
</script>

GitHub - styled-components/vue-styled-components: Visual primitives for the component age. A simple port for Vue of styled-components 💅

JSでCSS書いてますが、最終的にはちゃんとCSSで吐き出されるので、従来通りCSS設計の考え方、定数管理は必要です。

vue-emotion

GitHub - egoist/vue-emotion: Seamlessly use emotion (CSS-in-JS) with Vue.js
こちらもReactユーザーには馴染みがあるのではないでしょうか。
後発のライブラリな分、CSS in JSでできることはだいたいできるとのこと。

styled-compornent同様、JSでCSS書いてます。

CSS-in-JSのライブラリとして「emotion」を選択している理由 - Qiita

実行速度・ファイルサイズを比べると、styled-compornentよりemotionの方がよさそうですが、ちょっと情報が少ないですね・・ドキュメントを読んだところ、vue-emotionではcss PropやObject Stylesなどは使えなそう・・
styled-compornentでよさそうです。

CSS Modules

Scoped CSSを使っている方は一番馴染み深い書き方かもしれません。
Scoped CSSがカスタムデータ属性data-hogehogeを付与することで、元のclass名に影響を与えないことに対し、
CSS Modulesの場合、コンポーネント名_class名_ランダムな値となり、class名自体が変わることで、css名のバッティングを防ぎます。

<style>タグにscopeの代わりに、module属性を記述できます。

//公式ドキュメントより抜粋
<style lang='scss' module>
.blue {
  color: blue;
}
</style>

htmlの方はこんな感じで、:class=$style.fooで記述します。:がないとスタイルが反映されないので注意!

//公式ドキュメントより抜粋
<template lang="pug">
  p(:class="$style.blue" :id="$style.blue")
    This should be blue
</template>

通常のclassとも併用できます。utilityなど、グローバルなcssを当てるときはこちら。

//公式ドキュメントより抜粋
<template lang="pug">
  //- 複数スタイルの指定も可能
  p.red(:class="[$style.red, $style.bold]" :id="$style.blue")
    This should be blue
    
  p(:class="{ [$style.red]: isRed }" :id="$style.blue")
    This should be blue
</template>

通常のscopeとも併用できますが、そんなに併用するかわかりません・・

//公式ドキュメントより抜粋
<style lang='scss' module>
.blue {
  color: blue;
}
</style>
<style lang='scss' scope>
.red {
  color: red;
}
</style>

導入ハードルも低く個人的にはおすすめですが、やっぱりScoped CSSに比べると、コードの見通しが気になります😢
自分の場合VueはPugで書いているので、PugでシンプルにHTMLが書ける分、冗長さが際立ってしまうのが残念というか・・
この辺は好みですかね?

結論

以上3つをまとめた結果です。

・BEMを辞める、React<->Vueの行き来を考えるなら->styled-compornent
・Vue単体なら->CSS Modules
・別に不便ない->Scoped CSS

というところが良いかなと言う印象でした。
BEM使うからclassのバッティング懸念しない、という場合は引き続きScoped CSSで全く問題なさそうです。

個人的にはstyled-compornentが好きなので、Vueでも試してみようと思います🙇‍♀️

おまけ:デザイナ的にどっちが使いやすいとかある?

正直とくにありません。
どのCSS in JSを使用しても、下記が考慮されれば問題ありませんし、だいたいどれでも実現できます。若干の書き方の違い、気持ち悪さは慣れです

  • propsでによるスタイルの変更ができる
  • グローバル変数が使える
    • Scssが使えなければ、CSSで対応可能

ただ、UIフレームワークでしか開発経験がないメンバーしかいない場合、保守性・汎用性を考慮したCSS設計を行えるデザイナと協業できるとよさそうです〜

私たちのチームで働きませんか?

alt
エイチームは、インターネットを使った多様な技術を駆使し、幅広いビジネスの領域に挑戦し続ける名古屋の総合IT企業です。
そのグループ会社である株式会社エイチームブライズでは、一緒に働く仲間を募集しています!

上記求人をご覧いただき、少しでも興味を持っていただけた方は、まずはチャットでざっくばらんに話をしましょう。
技術的な話だけでなく、私たちが大切にしていることや、お任せしたいお仕事についてなどを詳しくお伝えいたします!

Qiita Jobsよりメッセージお待ちしております!

33
24
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
33
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?