MUI で Select の border を変えました

MUI のカスタマイズわからんすぎて、毎回こんな顔になってる👹

TL;DR

sx でこれを書くのがきれいなのかは一旦おいておいて、とりあえずこれで「すべての状態で border が細いグレー」な Select が作れる

<Select
  value={value}
  onChange={handleChange}
  sx={{
    '& .MuiOutlinedInput-notchedOutline': {
      border: '1px solid #e0e0e0',
    },
    '&:hover .MuiOutlinedInput-notchedOutline': {
      border: '1px solid #e0e0e0',
    },
    '&.Mui-focused .MuiOutlinedInput-notchedOutline': {
      border: '1px solid #e0e0e0',
    },
  }}
>

以下、どうやってこれを組み立てるかの自分なりの理解

コンポーネント構造

↑のサンプルコードを走らせてみて、Elements タブを見てみる。が、 .MuiSelect-root みたいなクラス名はなくて、Select の部品をページ上でクリックすると、 Select の親の FormControl のクラスがあたってる div がハイライトされる。

で、 Select はこの辺にありそうとわかる

Select の docs を見ると

Props of the OutlinedInput component are also available.

ってあって、 OutlinedInput のページを見るとさらに

Props of the InputBase component are also available.

とあるので、何やら Select は OutlinedInput の中に InputBase があるコンポーネントぽいとわかる

OutlinedInput をいじる

"mui select change border" とかでぐぐると、だいたい要素としては

  • .MuiOutlinedInput-notchedOutline
  • &:hover
  • &.Mui-focused

を組み合わせればなんとかなりそうな気がしてくる

まず .MuiOutlinedInput-notchedOutline は、 OutlinedInput のクラスで

Styles applied to the NotchedOutline element.

https://mui.com/material-ui/api/outlined-input/#outlined-input-prop-notched

と、わかるようなわからないような...

Material Design のページを見ると

The notched outline is a border around all sides of either a Text Field or Select component. This is used for the Outlined variant of either a Text Field or Select.

https://m2.material.io/develop/web/supporting/notched-outline
とあって結局謎なんだけど、とりあえず outline のある部品に対するクラスというのがなんとなく察せる。

こいつは結構わかりにくいところにいて、 Select そのものじゃなくて Select の子の fieldset 要素にあたってる

で、CSS を inspect するとたしかにこのクラスに対して青い border があたってる

なので、このクラスに対して自分の border を書けばよさそう

.Mui-focused

...については、ここに書いてある

https://mui.com/material-ui/customization/how-to-customize/#state-classes

1行まとめは :hover みたいなステートを .Mui-focused のようなクラスを mui が設定していて、コンポーネントを完全にカスタマイズするには &:hover だけじゃなくて &.Mui-focused のような状態についても CSS をいじる必要がある

このクラスは Select そのものにあたってる、というのがインスペクタからわかる (FormControl のすぐ下にいるから)

&:hover

同じノリで &:hover もみると、これも Select そのものにあたってるのがわかる

sx を書く

ここまででわかったのは、

  • .MuiOutlinedInput-notchedOutlineSelect の子
  • :hoverSelect そのもの
  • .Mui-focusedSelect そのもの

ので、これを組み合わせるとこういう selector でいけばよいというのがわかり、冒頭のコードができる

'& .MuiOutlinedInput-notchedOutline': {
  // Select の子
  border: '1px solid #e0e0e0',
},
'&:hover .MuiOutlinedInput-notchedOutline': {
  // :hover な Select の子
  border: '1px solid #e0e0e0',
},
'&.Mui-focused .MuiOutlinedInput-notchedOutline': {
  // .Mui-focused な Select の子
  border: '1px solid #e0e0e0',
},