Search code examples
javascripthtmlcssreactjsresponsive-design

How to fit text a into React Grid while also maintaining a little gap in between the boxes


I've been struggling to modify this grid so that there is some space in between the boxes while also fitting all the text inside the boxes. My current code is responsively made however every I fix one thing one other item gets broken and doesn't look correct. For example, when I fit all the text (assume this box contains more text than others) into the box, then the number's position starts moving up and doesn't look uniform to the other boxes.

Here's my code so far in my sandbox: Responsive Sandbox

import { Box, Grid, Paper, Typography } from "@mui/material";
import { styled } from "@mui/material/styles";

const Contained = styled(Box)({
  backgroundColor: "rgba(241, 243, 246, 1)",
  fontFamily: "Roboto",
  height: "100vh",
  width: "100vw"
});

const ResponsiveGridBox = styled(Box)`
  // Mobile Screen
  grid-template-columns: repeat(3, auto);

  // Tablet
  @media (min-width: 768px) {
    grid-template-columns: repeat(5, auto);
  }

  // Desktop
  @media (min-width: 1024px) {
    grid-template-columns: repeat(9, auto);
  }
`;

const Appbox = styled("div")({
  backgroundColor: "#fff",
  border: "1px solid #E4E9F2",
  borderRadius: "4px",
  color: "#64768C",
  display: "flex",
  flexDirection: "column",
  justifyContent: "center",
  alignItems: "center",
  padding: "16px",
  textAlign: "center",
  height: "92px",
  width: "133px",
  "&:hover": {
    boxShadow: "0px 3px 6px #00000029"
  }
});

const StatsNumber = styled(Typography)({
  fontSize: "32px",
  fontWeight: 600
});

const StatsNumberContainer = styled("div")({
  height: "36px",
  display: "flex",
  justifyContent: "center",
  alignItems: "center"
});

const LabelContainer = styled("div")({
  height: "20px",
  display: "flex",
  justifyContent: "center",
  alignItems: "center",
  flexWrap: "wrap",
  whiteSpace: "normal",
  maxWidth: "100%"
});

const labels = [
  "Quotes",
  "Applications",
  "Identity Verified",
  "Underwriting Questions Submitted",
  "Consent",
  "Approved",
  "Policy Submitted",
  "Not Paid",
  "Policy Issued"
];

function ResponsiveGrid() {
  return (
    <Contained>
      <Typography
        align="left"
        variant="h1"
        sx={{ margin: "0px 32px 24px 32px", fontSize: "24px" }}
      >
        Dashboard
      </Typography>
      <Grid item xl={18} xs={8}>
        <Paper sx={{ padding: "32px", height: "100%" }}>
          <ResponsiveGridBox gap={1} display="grid">
            {labels.map((label) => (
              <Grid key={label} item lg={1} md={3} xs={3}>
                <Appbox sx={{ width: "100%" }}>
                  <StatsNumberContainer>
                    <StatsNumber>33</StatsNumber>
                  </StatsNumberContainer>
                  <LabelContainer>
                    <Typography>{label}</Typography>
                  </LabelContainer>
                </Appbox>
              </Grid>
            ))}
          </ResponsiveGridBox>
        </Paper>
      </Grid>
    </Contained>
  );
}

export default ResponsiveGrid;

And here's what I'm trying to achieve: enter image description here


Solution

  • There are (at least) three problems.

    First, <Appbox>'s width should not be 100%, as it is a grid item; width: 100% means it should be as wide as its parent. Remove the sx property altogether.

    // Change
    <Appbox sx={{ width: "100%" }}>
    
    // to
    <Appbox>
    

    Second, <LabelContainer> should not have a fixed height, since it has a <Typography> child which may overflow.

    // Change
    const LabelContainer = styled("div")({
      height: "20px",
      /* ... */
    });
    
    // to
    const LabelContainer = styled("div")({
      /* ... */
    });
    

    Third, <Appbox>'s justifyContent should be start instead of center. This vertically aligns every child of it to the top of the box (the start of the main axis).

    // Change
    const Appbox = styled("div")({
      /* ... */
      justifyContent: "center",
      /* ... */
    });
    
    // to
    const Appbox = styled("div")({
      /* ... */
      justifyContent: "start",
      /* ... */
    });