简体   繁体   中英

Center align items in material-ui

I am rendering some cards in a container row and need to align them in the center with equal spacing around. I am using UI library material-ui for the layout. Even though I have added the justifyContent: center property, the cards have uneven spacing around them.

This is what the current UI looks like:

在此处输入图像描述

Notice the extra space on the right side of the last card. On inspecting, the spacing scale looks like this:

Here is the code so far:

const Home = ({ cards }) => {
  return (
    <Container maxWidth="xl">
      <Grid
        container
        justifyContent="center"
        spacing={3}
        my={8}
      >
        {cards.map((card) => {
          return (
            <Grid item xs={12} sm={6} md={3}>
              <Card sx={{ maxWidth: 300 }}>
                <CardActionArea>
                  <CardMedia
                    component="img"
                    height="140"
                    image="../../bg2.png"
                    alt="green iguana"
                  />
                  <CardContent>
                    <Typography gutterBottom variant="h5" component="div">
                      {card.title}
                    </Typography>
                    <Typography variant="body2" color="text.secondary">
                      {card.description}
                    </Typography>
                  </CardContent>
                </CardActionArea>
                <CardActions>
                  <Button size="small" color="primary">
                    View More
                  </Button>
                </CardActions>
              </Card>
            </Grid>
          );
        })}
      </Grid>
    </Container>
  );
};

If I remove the container wrapper <Container maxWidth="xl"> , then the UI looks like this:

在此处输入图像描述

I am not a very good hand at MUI, If anyone can help to rectify the issue and achieve desired results, will be really helpful.

Here is a live demo that spaces your cards out evenly. Use justifyContent = "space-evenly" in conjunction with alignItems = "center" .

编辑 MediaCard 材料演示(分叉)

在此处输入图像描述

import * as React from "react";
import Card from "@mui/material/Card";
import CardActions from "@mui/material/CardActions";
import CardContent from "@mui/material/CardContent";
import Button from "@mui/material/Button";
import Typography from "@mui/material/Typography";
import Grid from "@mui/material/Grid";

export default function MediaCard() {
  const cards = [1, 2, 3];
  return (
    <Grid
      container
      direction="row"
      justifyContent="space-evenly"
      alignItems="center"
    >
      {cards.map(() => (
        <Card sx={{ maxWidth: 345 }}>
          <CardContent>
            <Typography gutterBottom variant="h5" component="div">
              Lizard
            </Typography>
            <Typography variant="body2" color="text.secondary">
              Lizards are a widespread group of squamate reptiles, with over
              6,000 species, ranging across all continents except Antarctica
            </Typography>
          </CardContent>
          <CardActions>
            <Button size="small">Share</Button>
            <Button size="small">Learn More</Button>
          </CardActions>
        </Card>
      ))}
    </Grid>
  );
}

You can accomplish this with a little hacky.

There are some others questions like yours as you can see here and here with some alternatives to accomplish what you want.

Based on the answers to the above questions, I've created a codesample using this hacky with a custom hook that returns the dimensions of the window.

So, let`s go to the code:


const cards = [1, 2, 3, 4, 5];

// const related to the card maxWidth
const maxWidth = 300;

// const related to the total Cards Width - based on how cards the screen contains.
const totalwidth = maxWidth * cards.length;

// get the actual width of the screen
const { width } = useWindowDimensions();

// Check if the width screen is smaller than the total count of all cards width
// and if yes, we do the hacky mentioned above.
const screenSmallerThanAllCardsWidth = width < totalwidth + 20;// just added +20 to garantee

The hacky - add extra (n - 1) filler divs

let divsHacky= [];

  if (screenSmallerThanAllCardsWidth)
    for (var i = 0; i < cards.length - 1; i++) {
      divsHacky.push(
        <Box
          key={i}
          sx={{
            width: maxWidth,
            height: 0
          }}
        />
      );
    }

The component render:

<Grid container direction="row" justifyContent="space-around">
      {cards.map((item, index) => (
        <Grid item my={1} key={index}>
          <Card sx={{ maxWidth }}>
            <CardContent>
              <Typography gutterBottom variant="h5" component="div">
                Lizard
              </Typography>
              <Typography variant="body2" color="text.secondary">
                Lizards are a widespread group of squamate reptiles, with over
                6,000 species, ranging across all continents except Antarctica
              </Typography>
            </CardContent>
            <CardActions>
              <Button size="small">Share</Button>
              <Button size="small">Learn More</Button>
            </CardActions>
          </Card>
        </Grid>
      ))}
    // Render the divsHacky if exists
      {divsHacky}
    </Grid>

The windowDimensions custom hook:

import { useState, useEffect } from "react";

function getWindowDimensions() {
  const { innerWidth: width, innerHeight: height } = window;
  return {
    width,
    height
  };
}

export default function useWindowDimensions() {
  const [windowDimensions, setWindowDimensions] = useState(
    getWindowDimensions()
  );

  useEffect(() => {
    function handleResize() {
      setWindowDimensions(getWindowDimensions());
    }

    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  return windowDimensions;
}

You need to:

  1. Remove spacing and justifyContent props from Grid container.
  2. Add spacing (padding) to Grid items, if you want have spacing!
  3. Grid items should have display of flex with justifyContent="center" prop.

Here is a sample on Codesandbox . I just added borders to demonstrate it better.

I think wrapping each Card in Grid that has justifyContent="center" alignItems="center" will do

<Grid container direction="row">
  {cards.map(() => (
    <Grid xs={4} item justifyContent="center" alignItems="center">
      <Card sx={{ maxWidth: 345 }}>
        <CardContent>
          <Typography gutterBottom variant="h5" component="div">
            Lizard
          </Typography>
          <Typography variant="body2" color="text.secondary">
            Lizards are a widespread group of squamate reptiles, with over 6,000 species, ranging across all
            continents except Antarctica
          </Typography>
        </CardContent>
        <CardActions>
          <Button size="small">Share</Button>
          <Button size="small">Learn More</Button>
        </CardActions>
      </Card>
    </Grid>
  ))}
</Grid>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM