Grid layout; Best practices for the client commodity list page, two lines of code to achieve responsiveness

preview

Grid Layout

It is not recommended to use the Grid directly, it is more convenient to use the UI framework. If you have to write your own, it is not recommended to write CSS, but to use the Grid library. The following implementations use AntD and Materrial.

Ant Desing implementation

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>
}
Copy the code

Row is allowed to expand by default and can be used as a grid; Gutter array, which translates to the space between rows and columns, can be adjusted.

Col has XS, SM, MD, LG, XL and XXL, which can specify the corresponding space to be displayed. The space is 24 as full, that is, there is only one Item, and 12 is to display two items. So 6 is 4 items 24/6.

Col The size of the
xs < 576px
sm P 576 px.
md P 768 px.
lg P 992 px.
xl P 1200 px.
xxl P 1600 px.

Open it in CodePen

Material UI implementation

This implementation adds a skeleton screen

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>
  );
};
Copy the code

This is based on 12, which means only one Item, 6 means two items side by side, and so on.

The size of the response is the same as antD

Grid The size of the
xs < 576px
sm P 576 px.
md P 768 px.
lg P 992 px.
xl P 1200 px.
xxl P 1600 px.

For spacing, we can modify the default style implementation. Examples of styles are shown below

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),}}}));Copy the code

Content fill

In general, raster layout should have an image, so let’s add one.

<Container>
    <TestCards>
      {list.map((item) => <TestCard key={item} index={item} />)}
    </TestCards>
</Container>
Copy the code

This is the rendering of the list, the raster layout component that meets the requirements above is already done, now we just need to loop the list rendering, so let’s simply add an item component, called 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>
}
Copy the code

By the way, the reason why img is covered with a layer is that it can prevent collapse and fix the size. Img takes the size of Box as its own size, and uses objectFit internally to control the image display.

Style sample

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%'}},Copy the code

Notice that IMG never defines its size. This will work perfectly with the Grid.

Of course, this is only a simple example, specific IMG to do some errors, clarity and other processing.

Code And Preview

Open it in CodePen

— 完 —