MaterialUI Divider在xs/sm屏幕不显示,如何实现响应式横竖切换?
问题:Material UI Divider 在小屏幕不显示的原因及解决方法
需求说明
我需要使用Material UI的Divider组件,实现md及以上尺寸屏幕显示垂直分割线,xs和sm尺寸屏幕显示水平分割线的效果。初始代码如下:
<Divider orientation="vertical" variant="middle" flexItem />
尝试过的方案
- 通过媒体查询判断屏幕尺寸,动态切换分割线方向:
const theme = useTheme(); const isSmallScreen = useMediaQuery(theme.breakpoints.down('xs')); <Divider orientation={isSmallScreen ? 'horizontal' : 'vertical'} variant='middle' flexItem />
- 尝试将Divider包裹在Grid组件中,但xs和sm屏幕上始终看不到Divider。
完整代码片段
<Card> <Grid2 container spacing={4} sx={{ minWidth: { xs: '100%', md: '715px' } }}> <Grid2 xs={12} md={4}> {booking_items.map(item => ( <React.Fragment key={`${id}-${item.title}`}> <Typography variant='subtitle2'>{item.title}</Typography> <CardMedia component='img' image={item.imageUrl} title={item.title} /> </React.Fragment> ))} </Grid2> <Divider orientation={isSmallScreen ? 'horizontal' : 'vertical'} variant='middle' flexItem /> <Grid2 xs={12} md={8}> <CardContent> <Stack direction='row' spacing={1}> <CalendarBlankIcon sx={iconStyle} /> <Typography variant='body1'> {formatDate(start_date)} - {formatDate(end_date).split(' at ')[1]} </Typography> </Stack> <Stack direction='row' spacing={1}> <UserAltIcon sx={iconStyle} /> <Typography variant='body1'>{people} people</Typography> </Stack> <Stack direction='row' spacing={1}> <MapMarkerIcon sx={iconStyle} /> <Typography variant='body1'>{address}</Typography> </Stack> <Box sx={{ display: 'flex', justifyContent: 'flex-end', mt: '25px' }}> <Button variant='text' color='secondary' endIcon={<ChevronRightIcon />}> View Booking </Button> </Box> </CardContent> </Grid2> </Grid2> </Card>
原因分析与解决方法
核心问题
- 媒体查询范围不全:原代码只判断了
xs屏幕,漏掉了sm尺寸,导致sm屏幕下Divider仍为垂直状态,但此时Grid是上下堆叠布局,垂直分割线没有足够高度支撑,自然看不到。 - Grid布局逻辑冲突:Divider直接和Grid2子项同级,小屏幕下水平分割线需要占据整行,但当前结构没有给它分配正确的网格位置,布局逻辑混乱导致不显示。
解决步骤
- 修正媒体查询条件:将判断范围扩大到
sm,覆盖所有小屏幕尺寸:
const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
- 调整Divider的Grid布局适配:
- 小屏幕(水平分割线):用
Grid2 xs={12}包裹Divider,让它占据整行,同时移除flexItem属性(水平分割线不需要该属性)。 - 大屏幕(垂直分割线):保留
flexItem并添加alignSelf: 'stretch',确保分割线和左右列高度对齐。
- 小屏幕(水平分割线):用
修改后的完整代码:
const theme = useTheme(); const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm')); <Card> <Grid2 container spacing={4} sx={{ minWidth: { xs: '100%', md: '715px' } }}> <Grid2 xs={12} md={4}> {booking_items.map(item => ( <React.Fragment key={`${id}-${item.title}`}> <Typography variant='subtitle2'>{item.title}</Typography> <CardMedia component='img' image={item.imageUrl} title={item.title} /> </React.Fragment> ))} </Grid2> {isSmallScreen ? ( <Grid2 xs={12}> <Divider orientation="horizontal" variant="middle" /> </Grid2> ) : ( <Divider orientation="vertical" variant="middle" flexItem sx={{ height: 'auto', alignSelf: 'stretch' }} /> )} <Grid2 xs={12} md={8}> <CardContent> <Stack direction='row' spacing={1}> <CalendarBlankIcon sx={iconStyle} /> <Typography variant='body1'> {formatDate(start_date)} - {formatDate(end_date).split(' at ')[1]} </Typography> </Stack> <Stack direction='row' spacing={1}> <UserAltIcon sx={iconStyle} /> <Typography variant='body1'>{people} people</Typography> </Stack> <Stack direction='row' spacing={1}> <MapMarkerIcon sx={iconStyle} /> <Typography variant='body1'>{address}</Typography> </Stack> <Box sx={{ display: 'flex', justifyContent: 'flex-end', mt: '25px' }}> <Button variant='text' color='secondary' endIcon={<ChevronRightIcon />}> View Booking </Button> </Box> </CardContent> </Grid2> </Grid2> </Card>
额外说明
flexItem属性仅适用于垂直分割线,用于让它在flex容器中自动拉伸高度;水平分割线添加该属性会导致布局异常,务必移除。- 大屏幕下的
alignSelf: 'stretch'可以保证垂直分割线和左右内容区域高度一致,避免出现分割线过短的问题。
内容的提问来源于stack exchange,提问作者Sevicode
相关产品推荐
相关产品推荐

