この記事の概要
CSS in JSのライブラリであるEmotionを使うと自動でベンダープレフィックスが付与されます。
されるのですが、その内訳があまり現実に即していないラインナップです。
というわけでベンダープレフィックスを外す方法を記事にしました。
autoprefixerを外すのを推奨する記事ではなく、あくまで「こういうアプローチもある」という紹介です。
検証した際の環境
| パッケージ | バージョン |
|---|---|
| react | 18.2.0 |
| react-dom | 18.2.0 |
| @emotion/react | 11.10.5 |
| @emotion/cache | 11.10.5 |
| typescript | 4.6.4 |
| vite | 3.2.3 |
デフォルトの挙動とその問題点
分かりやすい例としてdisplay: flex;を使用した際に出力されるCSSをお見せします。
打ち消し線が入っていて少し見づらいですが、display: flex;以外に以下の3つの指定が追加されています。
- -webkit-box
- -webkit-flex
- -ms-flexbox
例えば-webkit-flexは、Chromeでいうとバージョン21から28まで必要でした。
-ms-flexboxはIE 10のために必要です(IE 11では不要です。)
この記事を書いている2022年12月現在、ここまでのサポートが必要な場面がどれだけあるのでしょう?
Autoprefixer CSS onlineで確かめてみるとBrowsers: > 0.01%の指定でようやく-webkit-flexと-ms-flexboxが現れます。
よしんば0.01%まで対応しようと思っても、-moz-boxはEmotionからは生成されていないため不十分です。
そもそも現在はベンダープレフィックスはあまり使う必要がありません。
かつてCSSにおいて実験的なプロパティを出す際、ベンダープレフィックス付きで実装していました。
今は、フラグや設定によってユーザーが制御して追加できるようになっています。(あくまで傾向の話ですが。)
ただしそうは言っても必要なベンダープレフィックスもあります。
そちらは以下の記事でまとめました。
https://qiita.com/xrxoxcxox/items/3e0e34003a45d3618b29
解決策
-
createCacheにstylisPlugins: []を指定する -
CacheProviderでラップする
createCacheにstylisPlugins: []を指定する
@emotion/reactや@emotion/styledの他に@emotion/cacheが必要になるのでインストールします。
2022/12/7 追記
@emotion/reactをインストールした時点で@emotion/cacheもインストールされるため、別途の導入は不要でした。
Reactのルートになるファイルを編集します。
先程インストールした@emotion/cacheからcreateCacheをインポートし、適当な名前で定義します。
その中でstylisPlugins: []を指定します。
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import createCache from '@emotion/cache'
const myCache = createCache({
key: 'css',
stylisPlugins: [], // これが重要
})
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>
)
Emotionは内部でstylisというCSSプリプロセッサーを使用しています。
デフォルトではstylisPluginsの中にprefixerが指定されているのを「何も使用しない」と上書きしているのがこのコードです。
ちなみにEmotionではprefixer以外は使用していないので、この変更による他の影響は起きないはずです。
ちなみにcreateCacheの中のkeyは、今回の内容には何も関係ないのですが指定しなければなりません。
createCacheを使わないときは'css'が指定されていて、特に変更したい意図もないのでこう記載しています。
CacheProviderでラップする
ここは特に説明する箇所はありません。
よくある感じで、Providerでラップするだけです。
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import createCache from '@emotion/cache'
+ import { CacheProvider } from '@emotion/react'
const myCache = createCache({
key: 'css',
stylisPlugins: [],
})
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
+ <CacheProvider value={myCache}>
<App />
+ </CacheProvider>
</React.StrictMode>
)
これにより、無事ベンダープレフィックスが消えました。
最後に
「browserlistを更新するとかで解決するでしょ?」と思っていたのに、随分とハマってしまいました。
実はstylisのprefixerプラグインは、どのプロパティにどのベンダープレフィックスをつけるかをハードコーディングしています。
そのためprefixerプラグインを使わないという強硬策に出る他ありませんでした。
検索してもあまり出てこない話題だったので困っている人自体が少ないのかもしれませんが……どなたかのお役に立てれば幸いです。
最後まで読んでくださってありがとうございます!
Twitterでも情報を発信しているので、良かったらフォローお願いします!
Devトークでのお話してくださる方も募集中です!


