TL;DR
こんな書き方でした。要するに、:local
の中で:global
を明示的に宣言することでした。
:local {
.foo {
width: 100%;
height: 200px;
:global {
.bar {
color: blue;
}
.baz {
background-color: green;
}
}
}
}
はじめに
Reactでも、Vue.jsみたいに**スコープ付き CSSを使いたい時、css-loader
を使って、CSS Modules**として導入する方法があります。
しかし、下記の記述だと、<Foo/>
にはスタイルが効くものの、その配下のdiv.bar
やdiv.baz
までスタイルは効いてくれませんでした。
:local(.foo) {
width: 100%;
height: 200px;
.bar {
color: blue;
}
.baz {
background-color: green;
}
}
import * as React from 'react'
import { foo as fooStyle } from 'foo.scss'
const Foo: React.FC<{}> = props => (
<div className={fooStyle}>
<div className='bar'>Bar</div>
<div className='baz'>Baz</div>
</div>
)
export default Foo
css-loaderの導入の仕方はこちらの記事を参考してください。本記事では割愛いたします。
https://codeburst.io/4-four-ways-to-style-react-components-ac6f323da822
https://qiita.com/Quramy/items/a5d8967cdbd1b8575130
対策
その1
最初見つかった対策は、foo.scss
をこんな書き方にすることで、解決できました。
:local(.foo) {
width: 100%;
height: 200px;
[class=bar] {
color: blue;
}
[class=baz] {
background-color: green;
}
}
.bar
のような記法はある意味で糖衣構文であり、本来の書き方に戻すことで、css-loaderが普通に解釈してくれました。
その2
[class=bar]
のような構文をたくさん書くと、「やっぱり、.bar
書きたいだよね」と思っちゃいますね。
そこで見つかったのは、:local
スコープの内部に :global
スコープを明示的に宣言することでした。
css-loaderのREADMEでも、この記法の存在を示唆しました。
:local(.foo) {
width: 100%;
height: 200px;
:global {
.bar {
color: blue;
}
.baz {
background-color: green;
}
}
}
前述したように、foo.scss
を上記構文に直すと、無事、div.bar
やdiv.baz
までスコープできました。
コンパイルされたHTMLやCSSはこんな感じでした。
<div class="_3stJVexdk1_1H90Xh-wKBa">
<div class="bar">Bar</div>
<div class="baz">Baz</div>
</div>
._3stJVexdk1_1H90Xh-wKBa {
width: 100%;
height: 200px;
}
._3stJVexdk1_1H90Xh-wKBa .bar {
color: blue;
}
._3stJVexdk1_1H90Xh-wKBa .baz {
background-color: green;
}