非常好用。
基礎應用
這邊是比較偏 CSS 的應用,推薦可以把官方文件的 system 部分給看完,這邊只會列幾個我想特別記一下的。
sx 屬性
這應該是 MUI 裡面最重要的一個東西。
簡單來說只要是 MUI 的組件都可以用 sm
這個 props,他基本上就跟 style
的用途差不多,但重點有兩個:
- 他不是 inline-style(絕對別搞錯囉)
- 可以用 MUI 專屬的 utils 來寫樣式(當 tailwind 在寫 XD)
所以如果想畫一個簡單的方塊
我可以這樣寫:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| export default function Color() { return ( <div> <Box sx={{ width: 1 / 2, // 50% color: 'white', textAlign: 'center', fontWeight: 'bold', background: 'dodgerblue', borderRadius: '4px', py: 1, // 1 = 8px px: 2 // 2 = 16px }} > Box1 </Box> </div> ) }
|
因為 sx
很好用的關係,所以當你用了 MUI 以後通常會直接拿 <Box>
來取代 <div>
。
Spacing
MUI 預設的間距是 8px
,所以只要跟間距有關的設定都會拿 8px
來當作基準,像是常見的 margin 跟 bottom 就會這樣寫:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| export default function Spacing() { const boxStyle = (bg) => ({ width: 1 / 2, color: 'white', textAlign: 'center', fontWeight: 'bold', background: bg, borderRadius: '4px', py: 1, px: 2, mt: 2, ml: 4 })
return ( <div style={{ margin: 50 }}> <Box sx={boxStyle('dodgerblue')}>Box1</Box> <Box sx={boxStyle('cadetblue')}>Box1</Box> </div> ) }
|
Shadow
這個是懶的時候很好用(雖然私心覺得 Tailwind 的 shadow
寫得更自然一些)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| export default function Shadow() { const boxStyle = { width: 1 / 2, color: '#555', textAlign: 'center', background: 'white', borderRadius: '4px', boxShadow: 1, py: 1, px: 2, m: 4 }
return ( <div style={{ margin: 50 }}> <Box sx={boxStyle}>Box1</Box> <Box sx={boxStyle}>Box1</Box> </div> ) }
|
breakpoint
透過 sx
設定的樣式都可以在指定「在哪個 breakpoint 下套用」的規則,像這樣:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| export default function BreakPoint() { const boxStyle = { width: { xs: 1, sm: 1 / 2 }, color: 'white', background: 'dodgerblue', textAlign: 'center', borderRadius: '4px', py: 1, px: 2, mt: 2 }
return ( <div> <Box sx={boxStyle}>Box1</Box> <Box sx={boxStyle}>Box1</Box> </div> ) }
|
預設的斷點是:
xs
: 0px
sm
: 600px
md
: 900px
lg
: 1200px
xl
: 1536px
這個做 RWD 必備,所以記得學起來。不懂的話可以到這邊 範例 來看,我就不貼圖了。
display
這個就是用來設定 block
、inline-block
等等之類的東西,跟 style 的寫法大同小異,所以這邊想特別講的是 textOverflow
的用法,只要搭配 <Box>
來用就能很輕鬆的做出 … 的效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| export default function TextOverflow() { const boxStyle = { width: 1, color: 'white', background: 'dodgerblue', overflow: 'hidden', whiteSpace: 'nowrap', textAlign: 'center', borderRadius: '4px', textOverflow: 'ellipsis', py: 1, px: 2, mt: 2 }
return ( <div> <Box sx={boxStyle}> Lorem Ipsum is simply dummy text Lorem Ipsum is simply dummy text Lorem Ipsum is simply dummy text </Box> </div> ) }
|
不懂的話一樣能能參考我寫的範例。
Palette(調色盤)
簡單來說像 color
跟 bgcolor
這兩個東西可以直接用指定的字串來存取 MUI 的基本配色,像這樣:
寫法也很簡單:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| export default function Color(bg) { const boxStyle = (bg) => ({ width: 1, color: 'white', bgcolor: bg, overflow: 'hidden', whiteSpace: 'nowrap', textAlign: 'center', borderRadius: '4px', textOverflow: 'ellipsis', py: 2, mt: 2 })
return ( <div> <Box sx={boxStyle('primary.main')}>primary</Box> <Box sx={boxStyle('secondary.main')}>secondary</Box> <Box sx={boxStyle('success.main')}>success</Box> <Box sx={boxStyle('warning.main')}>warning</Box> </div> ) }
|
範例到 這邊 看。至於字體顏色的用法也差不多,想知道更多的話看 官方文件 比較快。
TextField
這個寫表單的時候會蠻常用到的,這邊想特別記的幾個 props 有幾個:
required
helperText
Error
InputProps
(ReadOnly)
multiline
演示的部分可以參考這裡。
ThemeProvider
想參考預設值的話可以到 官方文件 看。
如果你想要覆蓋 MUI 預設的一些樣式,像是「顏色」、「間距」、「字體」和「陰影」之類的設定的話,可以用 ThemeProvider
的方式來覆寫。
來看一個最簡單的例子,假設我想把 primary
色改掉,那我可以這樣寫:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import { createTheme, ThemeProvider } from '@mui/material/styles'
const theme = createTheme({ palette: { primary: { main: '#8d69f1' } } })
ReactDOM.render( <React.StrictMode> <ThemeProvider theme={theme}> <App /> </ThemeProvider> </React.StrictMode>, document.getElementById('root') )
|
他背後是用 Context 來實作的,所以這例子的底下所有用到 primary
色的組件都會變成我寫的顏色。
如果我不想要他的 scope 那麼大,那就把 ThemeProvider
放在對應的組件上就好,像這樣:
1 2 3 4 5 6 7 8 9 10
| export default function BasicButtons() { return ( <Stack spacing={2} direction='row'> <ThemeProvider theme={theme}> <Button variant='contained'>Contained</Button> </ThemeProvider> <Button variant='contained'>Contained</Button> </Stack> ) }
|
useTheme 的用法
有時候你可能想寫一些 inline-style,但你想直接拿 MUI 寫好的樣式來用,這時候你就可以用 useTheme
來把對應的值取出來。
例如根據不同長度的文字我想套用不同的顏色:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import { useTheme } from '@mui/material/styles' import { Typography } from '@mui/material'
export default function BasicButtons() { const theme = useTheme() const title1 = 'short Text' const title2 = 'I an long short Text'
const getTypeStyle = (text, theme) => { return { color: text.length < 15 ? theme.palette.primary.main : theme.palette.secondary.main } }
return ( <div style={{ margin: theme.spacing(4) }}> <Typography style={getTypeStyle(title1, theme)} variant='h6' component='div' gutterBottom> {title1} </Typography> <Typography style={getTypeStyle(title2, theme)} variant='h6' component='div' gutterBottom> {title2} </Typography> </div> ) }
|
可以直接當作 utility 來用,我覺得還蠻方便的。
關於 Selectbox 的一個小雷點
這邊只是記錄一下當初覺得很雷的 bug。
我原本預期結果是這樣子:
但出來的結果是這樣子:
就是 label 的部分總會超出 border 的線條,當初找了蠻久才找到解法。
簡單來說 border 會隨著 <Select>
的 label
來做調整,所以你一定要讓它的值跟顯示的 <InputLabel>
的內容是一樣的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <FormControl> <InputLabel>Project Detail</InputLabel> <Select label='Project Detail' // 這個要跟上面的 <InputLabel> 對應 multiple value={personName} onChange={(e) => setPersonName(e.target.value)} renderValue={(selected) => { return ( <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1 }}> {selected.map((value) => ( <Chip variant='outlined' key={value} label={value} /> ))} </Box> ) }} > {names.map((name) => ( <MenuItem key={name} value={name}> {name} </MenuItem> ))} </Select> </FormControl>
|
客製化 CSS
sx 屬性
這是最簡單也是最推薦的作法,就是用 sx 屬性來改:
1 2 3 4 5 6 7 8 9 10 11
| export default function SxProp() { return ( <Slider defaultValue={30} sx={{ width: 300, color: 'success.main' }} /> ) }
|
可以看到這邊寫的樣式會出現在 .css-121j95d-MuiSlider-root
中。如果要用純 CSS 來做的話就無法了,因為 class 中有 hash 值。
在 sx 中使用 selector
一個元件通常是由多個 part 來組成的,像上面的 Slider
中就包含了 rail
、track
和 thumb
這幾個部位:
這邊順便介紹一下 MUI 的命名規則是 [hash]-Mui[元件名稱]-[元件中的其他插槽]
你可能會想說有 hash 值的話要怎麼寫?不過不用擔心,透過 sx
你只需要寫成 & .MuiSlider-[插槽名稱]
就可以了,不用擔心 hash 值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| export default function SxProp() { return ( <Slider defaultValue={30} sx={{ width: 300, color: 'success.main', // 把按鈕的部分改成方形 '& .MuiSlider-thumb': { borderRadius: 1 } }} /> ) }
|
所以當你碰到「要改的部分是元件的插槽」時,就用這種方式來修改就行了。