Grid 栅格布局; 用户端商品列表页面的最佳实践方案,两行代码实现响应式
预览图
Grid 栅格布局
不建议直接使用grid,使用UI框架的更方便一点,如果非要自己写,也不建议写css,而是使用Grid的库。下面使用AntD和Materrial实现。
Ant Desing 实现
const TestCards: React.FC = ({ children }) => {
const modifyChildren = useCallback(
(child: any) => {
return <Col xs={24} sm={12} lg={6} xl={4}>
{child}
</Col>
}
, [])
return <Row gutter={[24, 24]}>
{React.Children.map(children, modifyChildren)}
</Row>
}
复制代码
Row 默认是允许展开的,可以当作grid使用;
gutter
数组,对应的是行列的间距,可以调节的。
Col 有 xs、sm、md、lg、xl、xxl 可以指定对应的要显示的空间,空间以24作为满的,也就是只有一个Item,12就是显示两个Item;6就是4个Item (24 / 6)。
Col | 大小 |
---|---|
xs | < 576px |
sm | ≥ 576px |
md | ≥ 768px |
lg | ≥ 992px |
xl | ≥ 1200px |
xxl | ≥ 1600px |
Material UI 实现
这个实现多加了一个骨架屏
export const ProductCards = ({
children,
isLoading,
skeletonsCount = 5,
}: IProductCardsProps) => {
const classes = useProductCardsStyles();
const modifyChildren = useCallback(
(child: any) => {
return (
<Grid item xs={12} sm={6} lg={4} xl={3} className={classes.col}>
{child}
</Grid>
);
},
[classes.col],
);
const renderedSkeletons = Array(skeletonsCount)
.fill(0)
.map((_, i) => <ProductCardSkeleton key={uid(i)} />);
return (
<Grid container className={classes.row}>
{React.Children.map(isLoading ? renderedSkeletons : children, child =>
modifyChildren(child),
)}
</Grid>
);
};
复制代码
这里是以12作为基准的,12就是只有一个Item的意思,6就是两个并排的意思,以此类推。
关于响应式尺寸,和antd都是一样的
Grid | 大小 |
---|---|
xs | < 576px |
sm | ≥ 576px |
md | ≥ 768px |
lg | ≥ 992px |
xl | ≥ 1200px |
xxl | ≥ 1600px |
关于间隔,我们可以修改默认样式实现。下面展示样式示例
import { makeStyles, Theme } from '@material-ui/core';
import { getPercentage } from 'modules/common/utils/styleUtils';
export const useProductCardsStyles = makeStyles<Theme>(theme => ({
row: {
marginLeft: theme.spacing(-2),
marginRight: theme.spacing(-2),
marginTop: theme.spacing(-4),
width: 'auto',
[theme.breakpoints.up('HD')]: {
marginLeft: theme.spacing(-1.25),
marginRight: theme.spacing(-1.25),
marginTop: theme.spacing(-2.5),
},
[theme.breakpoints.up('WXGAPlus')]: {
marginLeft: theme.spacing(-2),
marginRight: theme.spacing(-2),
marginTop: theme.spacing(-4),
},
},
col: {
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(2),
marginTop: theme.spacing(4),
[theme.breakpoints.up('HD')]: {
flex: '0 0 auto',
width: getPercentage(1, 5),
paddingLeft: theme.spacing(1.25),
paddingRight: theme.spacing(1.25),
marginTop: theme.spacing(2.5),
},
[theme.breakpoints.up('WXGAPlus')]: {
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(2),
marginTop: theme.spacing(4),
},
},
}));
复制代码
内容填充
一般栅格布局展示的内容都要有一个图片,我们给他加一个吧。
<Container>
<TestCards>
{list.map((item) => <TestCard key={item} index={item} />)}
</TestCards>
</Container>
复制代码
这是列表的渲染,上面符合需求的栅格布局组件已经做好了,下面只需要循环列表渲染即可,那我们简单加一个item的组件吧,就叫TestCard吧。
const TestCard: React.FC<{ index: number }> = ({ index }) => {
return <Card>
<div style={styles.cardRoot}>
<div style={styles.mainImgBox}>
<img src={imgUrl} alt="" style={styles.mainImg} />
</div>
Col{index}
</div>
</Card>
}
复制代码
说一下哈,之所以img外面要包一层,是因为这个可以防止坍塌也可以固定大小,img就以Box的大小为自己大小,然后内部使用objectFit控制图片展示方式。
样式示例
const styles: { [className: string]: React.CSSProperties } = {
cardRoot: { width: '100%', height: '100%' },
mainImgBox: { paddingTop: '100%', position: 'relative' },
mainImg: { position: 'absolute', top: 0, left: 0, objectFit: 'contain', width: '100%', height: '100%' },
}
复制代码
有没有注意到一点,img从始至终都没有定义过自己的大小。这样就可以和grid完美配合啦。
当然这个只是简陋示例,具体img要做一些错误,清晰度等处理。
Code And Preview
— 完 —
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END