👫

chakra-uiで同じ属性に複数の値(fallback値)を持たせたい時

2022/05/26に公開

CSSで特定の値でしか利用できない指定を行う際、複数記述してfallback値とすることがある。

あまり最近は使わないが、例えばsvhdvhのようにsafariでしか使えないものの場合はこんな具合になる

.some-container {
  height: 100vh;
  height: 100dvh;
}

Chakra UIなどの場合、オブジェクト形式で記載することになるので<Box height={"100vh"} height={"100dvh"} />と記述しても片方で上書きされてしまう。
一方<Box height={["100dvh","100vh"]} />のようにしてしまうとレスポンシブとして扱われてしまう。
そのためこの場合どうするか?というのに迷った。

### 解決策1: 型エラーを許容しつつ二重配列形式で記述。

TypeScriptのエラーが出てしまうのだが、下記のような記述で設定されるようだ

<Box 
  // @ts-ignore
  height={[["100vh","100dvh"]]}
>

型を抑止するのに上記ではts-ignoreを利用している。
一応実現は可能だが、ざっとChakra UIのコードを見てもそれらしいコードやテストコードは見つけられなかったので、意図していない仕様バグのようなものの可能性もありそうだ

解決策2: cssプロパティを使う

cssプロパティを利用すれば生のCSSをねじ込むことが出来るので、一応これも可能。
この場合は型エラーも出ないが、CSS部分はなんのハンドリングも無いのでこの点は注意が必要

<Box css={`height: 100vh; height: 100dvh;`} >

解決策3: sxプロパティと&で解決する

sxを利用する場合は、&を駆使すると実現できる。

&はその指定された自身のクラス名に置き換えられるため、無理やり自分を参照するスタイルを複数当てることになる。

<Box
  sx={{
    height: "100vh",
    "&":{
      height: "100svh"
    }
  }}
/>

sxであればChakraのthemeなども利用可能となるので、cssプロパティよりは利点もある。

また、3つ、4つと増やしたい場合、かなり無理はあるが、下記のようにスペースや詳細度に影響を与えない*を追加することでも解決出来る。

<Box
  sx={{
    bg: "red.200",
    "&":{
      bg: "blue.200"
    },
    " &":{ // スペースを入れればJSを騙す
      bg: "yellow.200"
    },
    "* &":{ // スペースの代わりに*でも代用出来る
      bg: "green.200"
    },
  }}
/>

下に行くほど優先されるのが基本だが、div &などの場合はCSSの詳細度が変わってしまうので、注意が必要だ。

GitHubで編集を提案

Discussion