How to align items at the center in material-ui styling

I have a row of cards inside a container that I want to align in the center with equal spacing around them. I am using the material-ui UI library for the layout. Despite adding the justifyContent: center property, the cards are not evenly spaced.

This is how the current UI appears:

There seems to be extra space on the right side of the last card. The spacing scale reveals this:

Here's the code snippet 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'm not very experienced with MUI, so any help in fixing this issue and achieving the desired layout would be greatly appreciated.

Answer №1

Click here to see a demonstration of how to evenly space your cards using

justifyContent = "space-evenly"
and alignItems = "center".

https://example.com/theme-dark

https://example.com/image.png

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>
  );
}

Answer №2

If you're looking to achieve this, a little hacky approach can do the trick.

Similar questions have been asked before, and you can find some alternative solutions here and here.

Building on the insights from those discussions, I've put together a sample code here, utilizing a 'hacky' technique with a custom hook that provides window dimensions.

Now, let's dive into the code:


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

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

// Calculating total Cards Width based on screen size
const totalwidth = maxWidth * cards.length;

// Getting actual screen width
const { width } = useWindowDimensions();

// Checking if screen width is smaller than total cards width
const screenSmallerThanAllCardsWidth = width < totalwidth + 20;// added +20 for safety

The hacky - adding 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
          }}
        />
      );
    }

Rendering the component:

<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 they exist
      {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;
}

Answer №3

Make the following adjustments:

  1. Take out the spacing and justifyContent properties from the Grid container.
  2. If you want spacing, add padding to the Grid items.
  3. The Grid items should use a display of flex with the
    justifyContent="center"
    property.

Check out a sample on Codesandbox. Borders have been added for better visualization.

Answer №4

It seems like a good idea to wrap each Card in Grid with justifyContent="center" and alignItems="center"

<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 diverse group of reptiles, with over 6,000 species found across all continents except Antarctica
          </Typography>
        </CardContent>
        <CardActions>
          <Button size="small">Share</Button>
          <Button size="small">Learn More</Button>
        </CardActions>
      </Card>
    </Grid>
  ))}
</Grid>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What could be the reason for not receiving any response from my Firestore query?

Hey there! I'm delving into the world of Firebase for the first time and just set up the Firestore emulator. I've added some data that I want to fetch in my Nextjs app. Once I initialized firebase, this is what my component code looks like: funct ...

Introducing a novel class designed to leverage the attributes of another class

Is there a way to use the @extend feature in CSS to inherit properties from one class to another? Imagine having two CSS files loading on a page in this order: <link rel="stylesheet" href="/css/one.css" media="screen"> <link rel="stylesheet" href ...

Ensure that the Map reference object is accessible when the first modal window is displayed or opened

My issue involves a table where selecting a row should display the item's location on a map using react-map-gl in a Dialog component. However, upon clicking the row, the mapref returns null during the initial render, even though it should provide mapr ...

The optimal method for selecting a button from a group of buttons on a calculator using pure JavaScript

I have developed an HTML/CSS code inspired by the Mac/Apple calculator design. It features buttons organized in 5 rows using flexbox. You can view my code on this codepen: <div class="wrapper"> <div class="calheader"> ...

Tips for incorporating adjustable export dimensions for Highcharts within Next.js or React.js

Currently, I'm tackling a project that involves Next.js and Highcharts. One of the requirements is to allow users to export charts in different sizes - small, medium, and large. Is there a way to make this work seamlessly? menuItems: [ ...

Implementing a flat icon as a clickable link to navigate to a different route using React Router

I'm currently using redux, react-router, and Material-ui in my App development. I am facing an issue with displaying the details of an order. My requirement is that when a user clicks on a flat button, it should redirect them to a new URL. I have trie ...

Make sure to load dataLayer variables before setting up gtag in Google Tag Manager for seamless integration

In my NextJS application, I have a functionality that grabs the URL of the page and then uses utility functions to assign values to dataLayer key-value pairs like page_category and content_category. These values are then supposed to be added as custom dime ...

What is the proper file format for a form action in CSS?

What I Currently Have: In my Index.html file, there are a total of 4 form elements including text fields and a dropdown. Upon submission by the user, the data is processed in confirm.html using a separate JavaScript file for formatting before being displa ...

I'm wondering how I can design a utility function within my Redux module that can extract a specific subset of read-only data from the current state

I am currently utilizing redux to create a "helper function" inside my redux module that is responsible for fetching filtered data from the state based on a specified index. This specific data will be used to generate a form consisting of inputs depending ...

Steps to Embed an Image File in a MERN Stack Application

I'm attempting to load an image from a file inline because I need to pass data (the image name), but nothing seems to be working. It doesn't work whether the image is inside the src folder or outside in the public folder. Here's what I trie ...

What is the best way to neatly import multiple images in Next.js?

I have a dilemma involving 10 images located in my public directory that I need to use in a component. Instead of individually importing each image like this: import imgurl1 from "../../public/celsius.gif"; import imgurl2 from "../../public/ ...

Ways to increase the size of a div to match the maximum height of its parent container

My current project involves using an angular dialog layout where the API to open and manage the dialog comes from a separate library. The dialog's parent container has a max-height attribute, meaning the dialog's height is determined by its conte ...

Encountering the error "props.children is throwing a function" while trying to publish my Gatsby website

I've checked out other posts related to this issue but still can't seem to resolve it. My development build is functioning properly, but the error below is being thrown by Netlify during deployment: 4:58:48 PM: WebpackError: TypeError: props.ch ...

I'm interested in developing a React function that generates recipe components based on a set of instructions provided in an array, along with a separate parameter specifying the recipe name

I am currently immersed in the book "Learning React" written by O'Reilly. The book mentions a method of creating components by using a function known as the "component creating function". It advises supplying the necessary parameters as the second par ...

Acquire the content of a nested element using jQuery

I have a navigation list with separate headlines and text for each item. The goal is to switch the main headline and paragraph of text when hovering over a navigation item. CodePen Example Currently, my code displays all text. I only want to display the ...

There is an error in ReactJS: TypeError - _this.props.match is not defined

I am experiencing a TypeError in my console tab and I can't seem to figure out where the error is occurring in my source code. I am relatively new to ReactJS so any help in identifying what I'm doing wrong would be greatly appreciated. Thank you ...

JavaScript encoding and decoding challenges

Can anyone help me figure out what's wrong? I'm trying to encode and decode a simple input, but it just doesn't seem to work! Any ideas why? Thanks in advance for your assistance :) ENCODE: function encryption_encode(s, delta) { var te ...

In Firefox, the scaling of svg masks is not functioning properly

Trying to utilize an svg for masking an image, but encountering scaling issues in Firefox. Safari and Chrome seem to display correctly, with proper fallbacks for IE. Website: SVG File: CSS: -webkit-mask: url("../img/feelfilms-logo.svg#logo_mask"); mask ...

Navigating through parent folder HTML files from child folder HTML files

Seeking guidance as I embark on a new project! Check out this link to see my skills in action: collegewebsite.zip Now for the query at hand. I am working on a project named Coffee Cafe for my tuition assignment. It involves utilizing CSS and HTML with J ...

Leveraging the power of the app folder in conjunction with the pages

Being new to Next.JS, I recently learned that we have the option of organizing our pages in either the app/ or pages/ folder. I am a bit confused because there is a suggestion to utilize a new src/app/ folder instead of the pages/ folder. However, it seem ...