Responsively center grid of cards on page and align cards left - javascript

I am having a grid of cards and I want to align the grid center wrt the page and align the cards left wrt to the grid, responsively adapting to different screen sizes.
Say if there are 10 cards, and the screen size is such that only 4 cards will fit on a row, then the first and second rows would have 4 cards each while the third row would have 2 cards aligned to the left. And the spacing on both sides of the grid will be evenly distributed.
I tried to wrap the Grid in a div, but it failed as the Grid was taking up 100% screen width. I tried setting the Grid width to min-content, but then there was only 1 card left on each row. If I set Grid align to center, the trailing cards on the last row would be centered.
EDIT: the following is the code I have. MyCard.tsx is the Card component while CardList.tsx is the div/Grid component.
MyCard.tsx
const useStyles = makeStyles((theme: Theme) =>
createStyles({
card: {
minWidth: 325,
marginBottom: '1vh',
marginLeft: '0.5vw',
marginRight: '0.5vw',
backgroundColor: theme.palette.background.paper,
color: theme.palette.secondary.contrastText,
boxShadow: '3px black',
},
media: {
height: 170,
},
cardContent: {
padding: '5px 15px',
height: 80,
},
})
const MyCard: React.FC<MyCardProp> = (props: MyCardProp) => {
const isDesktopOrLaptop = useMediaQuery({
query: '(min-device-width: 1224px)',
})
const theme = useTheme()
const classes = useStyles(theme
return (
<Card className={classes.card}>
<CardMedia
className={classes.media}
image={props.imageURL}
/>
<CardContent className={classes.cardContent}>
<Typography gutterBottom variant="h5" component="h2">
{props.title}
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
{props.description}
</Typography>
</CardContent>
<CardActions
className={classes.bottomBar}
onClick={() => {
// Do something here.
}}
disableSpacing
>
<IconButton>
<Typography className={classes.bottomBarText} variant="h5">
{props.title}
</Typography>
<ArrowForwardIcon />
</IconButton>
</CardActions>
</Card>
)
}
CardList.tsx
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
display: "flex",
justifyContent: "center",
alignItems: "center",
},
grid: {
marginTop: 20,
overflowX: "auto",
flexGrow: 0,
},
greyText: {
color: "#666666",
ard
})
)
const CardList: React.FC<CardListProps> = (props: CardListProps) => {
const theme = useTheme()
const classes = useStyles(theme)
const cards = useSelector<RootState, Card[]>(
(state: RootState) => state.cards.data
)
return (
<div className={classes.root}>
<Grid
container
className={classes.grid}
wrap={"nowrap"}
direction={props.direction}
>
{cards.length ? (
cards.map((card, i) => {
return (
<MyCard
data={card.data}
/>
)
}) : null}
</div>
)
}
Thank you in advance for any advice.

I finally came across another post here that solved the problem.
The key is to add the following styling to the Grid container.
display: grid;
grid-template-columns: repeat(auto-fill, 100px);
grid-gap: 10px;
justify-content: center;
align-content: flex-start;
margin: 0 auto;
text-align: center;
margin-top: 10px;
In particular, grid-template-columns: repeat(auto-fill, 100px); did the trick where 100px should be the desired column width.

Related

React resizing img not working (Material UI useStyles)

I am trying to resize an image in React, but for some reason changing the height and width of the tag via useStyles does not make the image smaller, but simply shifts it around in the page.
Code:
import { makeStyles } from "#material-ui/core/styles";
import { SvgIcon, Typography } from "#mui/material";
import { Icon } from "#mui/material";
const useStyles = makeStyles((theme) => ({
pageContainer: {
display: "block",
marginTop: 120,
justifyContent: "center",
alignItems: "center",
},
logo: {
display: "flex",
justifyContent: "center",
alignItems: "center",
width: "50%",
height: "50%",
},
info: {
display: "block",
justifyContent: "center",
alignItems: "center",
},
iconContainer: {
display: "flex",
height: "20vh",
width: "auto",
},
}));
const teamNames = [
"Name1",
"Name2",
"Name3",
"Name4",
];
export default function () {
const classes = useStyles();
return (
<div className={classes.pageContainer}>
<div className={classes.logo}>
<img src={process.env.PUBLIC_URL + "/myLogo.png"}></img>
</div>
<div className={classes.info}>
<Typography variant="h3" display="block" align="center">
About the Team
</Typography>
{teamNames.map((personName) => (
<Typography variant="h5" display="block" align="center">
{personName}
</Typography>
))}
</div>
</div>
);
}
I'm not quite sure what is the issue, all I really want to do is to make the image smaller proportionally and put it at the center of the page.
You will need to add this css to your img. this will make sure that the img adjusts itself within the parent div.
width: 100%;
height: fit-content;

MUI: Pseudo element being cut-off outside of Paper

I am having trouble with a red arrow '::before' pseudo element being partly cut-off outside of its '.MuiPaper-root' container. I would like for it to still be visible, any suggestions?
Below I have provided the relevant code and screenshots:
const useStyles = makeStyles(theme => ({
root: {
left: '5rem !important',
'& .MuiPaper-root': {
'&::before': {
position: 'absolute',
left: '4rem',
display: 'inline-block',
top: '-3.9rem',
fontSize: '5rem',
fontFamily: 'Material Icons',
content: '"arrow_drop_up"',
color: 'red',
zIndex: '5 !important',
},
},
},
}));
<S.Item style={{ alignSelf: 'stretch' }}>
<S.ItemGrid>
<S.Title>Guest rating</S.Title>
<S.Rating>
<FormControl style={{ width: '10rem' }}>
<S.StyledSelect
defaultValue={3.5}
value={rating.currency}
onChange={changeRating('currency')}
renderValue={option => option.value}
MenuProps={{
classes: { root: classes.root },
}}
>
{ratings.map(option => (
<S.StyledMenuItem key={option.value} value={option}>
<div>{option.value}</div>
<div>{option.label}</div>
</S.StyledMenuItem>
))}
</S.StyledSelect>
</FormControl>
</S.Rating>
</S.ItemGrid>
</S.Item>
Add overflow: 'visible' in your Paper style to prevent the content from being clipped even if it's outside the parent:
overflow: "visible",
"&::before": {
// ...
}

CSS padding is not applied to the div in react js

I have a div like this in react js which renders multiple divs and overflows :
<div
style={{
display: "flex",
padding: "1em 0.7em",
overflowX: "auto",
width: "100%",
direction: "rtl",
background: "#ef394e"
}}
>
{Array.from(Array(10).keys()).map((each, index) => (
<div
key={index}
className="swiper-slide"
style={{
background: "white",
borderRadius: "10px",
width: "270px",
margin: "0 .4em"
}}
>
<div style={{ padding: "2em 6em" }}>Hello</div>
</div>
))}
</div>
But for some reason the padding is applied to the containers right side but not the left side here are some pictures :
How can I apply padding to the array item's container div for both the left and right sides ?
It's because your div width bigger then the body,
and as result your body also have scroll.
Try add boxSizing: border-box to your parent component, and the body scroll will disappear.
const App = () => {
return (
<div
style={{
display: "flex",
padding: "1em 0em",
overflowX: "auto",
width: "100%",
direction: "rtl",
background: "#ef394e",
boxSizing: "border-box" // <--- this line
}}
>
...
</div>
);
};
It's the padding on the div. It's to little and the margin too.
import React from "react";
const App = () => {
return (
<div
style={{
display: "flex",
padding: "1em 0em",
overflowX: "auto",
width: "100%",
direction: "rtl",
background: "#ef394e"
}}
>
{Array.from(Array(10).keys()).map((each, index) => (
<div
key={index}
className="swiper-slide"
style={{
background: "white",
borderRadius: "10px",
width: "270px",
margin: "0 .4em"
}}
>
<div style={{ padding: "2em 6em" }}>Hello</div>
</div>
))}
</div>
);
};
export default App;

My Card's Background and Image are flickering when I move over it (while hovering), it works fine when I just hover over it and stop moving my cursor

import React from 'react';
import { makeStyles, Typography, Grid } from '#material-ui/core';
import Card from '#material-ui/core/Card';
const styles = makeStyles((theme) => ({
card: {
background: 'black',
width: '140px',
margin: '0px 10px',
},
root: {
width: '142px',
height: '196px',
overflow: 'hidden',
position: 'relative',
transition: 'all 0.5s ease-out',
},
image: {
position: 'absolute',
width: '100%',
height: '100%',
objectFit: 'cover',
transition: 'all 0.5s ease-out',
zIndex: 10,
'&:hover': {
zIndex: -1,
},
},
textPositioning: {
width: '140px',
height: '40px',
overflow: 'hidden',
marginTop: '10px',
},
text: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
fontFamily: 'Comfortaa',
},
genresContainer: {
backgroundColor: theme.palette.primary.main,
width: '100%',
height: '100%',
position: 'relative',
transition: 'all 0.5s ease-out',
zIndex: 2,
},
genreList: {
width: '100%',
height: '100%',
},
}));
interface AnimeData {
image_url: string;
title: string;
genres: Array<any>;
}
interface DisplayAnimeCardProps {
data: AnimeData;
}
const DisplayAnimeCard: React.FC<DisplayAnimeCardProps> = (
props: DisplayAnimeCardProps
) => {
const classes = styles();
const { data } = props;
console.log(typeof data, data.genres);
return (
<Card className={classes.card}>
<div className={classes.root}>
<img
className={classes.image}
alt='anime'
src={data.image_url}
/>
<div className={classes.genresContainer}>
<Grid
className={classes.genreList}
container
direction='column'
justifyContent='center'
alignItems='center'
>
{data.genres.map((genre) => (
<Typography
className={classes.text}
variant='body1'
>
{genre.name}
</Typography>
))}
</Grid>
</div>
</div>
<div className={classes.textPositioning}>
<Typography className={classes.text} variant='body1'>
{data.title}
</Typography>
</div>
</Card>
);
};
export default DisplayAnimeCard;
The Hovering effect show a div a top the image with some text. It works fine when I simply hover over the Card and do not move the cursor again. But If I move my cursor(during hovering) a top the card, the hover effect breaks and causes flickering between the textPositioningdiv and the image. I want to stop this flickering and just show the textPositioning div whenever I hover over the card and move my cursor

Unable to center material-ui GridList

I have a GridList which I am using to display Cards. These components are styled as follows:
card.js
const useStyles = makeStyles({
card: {
maxWidth: 240,
margin: 10
},
media: {
height: 100
}
})
grid.js
const useStyles = makeStyles(theme => ({
root: {
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'space-around',
overflow: 'hidden'
},
gridList: {
width: '80%',
height: '100%'
}
}))
export default function CardGridList() {
const classes = useStyles()
return (
<div className={classes.root}>
<GridList className={classes.gridList} cols={4}>
<CardItem />
<CardItem />
<CardItem />
<CardItem />
<CardItem />
<CardItem />
<CardItem />
<CardItem />
</GridList>
</div>
)
}
and finally, container.js (which uses styled-components)
const ContainerWrapper = styled.div`
margin: 0 auto;
`
export default class Container extends React.Component {
render() {
return (
<ContainerWrapper>
<ThickSpace />
<CardGridList />
</ContainerWrapper>
)
}
}
However, no matter what combination of properties I try, I cannot get the cards to align in the center. I am always left with something like this:
Where the GridList is skewed off-center. I have gone through the material-ui documentation, looked at numerous explanations like this, but nothing is working. Please help!
You specify margin: 0 auto; on the top level container element, however you don't give the element any styles that make this auto margin take effect. You need to give a width gate for the element, so that way the auto margin will actually space on either side.
const ContainerWrapper = styled.div`
margin: 0 auto;
max-width: 1040px;
`
I got 1040 from the size of the card you defined. 240 width and 10 margin on each side means 20 px of space (first card 10px on right, second card 10px on the left). 260 * 4 = 1040 :)

Categories

Resources