'Dynamically adjust ImageList columns based on screen size?
I've tried using ImageList
component instead of Grid
as I just need a grid of photos with titles and it seems to be the whole point of ImageList
. My issue is that unlike with Grid I cannot pass breakpoint props for different screen sizes (which I find weird as this would seem logical) so that I can get different count of columns on different screens. What would be the best approach to adjust number of columns based on screen size?
Solution 1:[1]
ImageList
uses CSS grid and needs the col
prop to set the grid-template-columns
but without any responsive API baked in. You can swap the ImageList
with a Box
component with the display set to grid
, and uses the sx
prop to declare the column template value depend on the screen size, but first let define some breakpoints:
const theme = createTheme({
breakpoints: {
values: {
mobile: 0,
bigMobile: 350,
tablet: 650,
desktop: 900
}
}
});
Then in the component, you can start using it like this:
import ImageListItem, { imageListItemClasses } from "@mui/material/ImageListItem";
<ThemeProvider theme={theme}>
<Box
sx={{
display: "grid",
gridTemplateColumns: {
mobile: "repeat(1, 1fr)",
bigMobile: "repeat(2, 1fr)",
tablet: "repeat(3, 1fr)",
desktop: "repeat(4, 1fr)"
}
// standard variant from here:
// https://github.com/mui-org/material-ui/blob/3e679ac9e368aeb170d564d206d59913ceca7062/packages/mui-material/src/ImageListItem/ImageListItem.js#L42-L43
[`& .${imageListItemClasses.root}`]: {
display: "flex",
flexDirection: "column"
}
}}
>
{itemData.map((item) => <ImageListItem {...}/>)}
</Box>
</ThemeProvider>
Live Demo
References
Solution 2:[2]
This solution I came up with works, but seems like a lot of lines for something that Grid handles out of the box. Doesn't ImageList have some built in responsive design implementation?
export function Example(props) {
// not sure if there is a way to get something like this dictionary from React?
const breakpoints = {
xs: 0,
sm: 600,
md: 960,
lg: 1280,
xl: 1920
}
const getColumns = (width) => {
if (width < breakpoints.sm) {
return 2
} else if (width < breakpoints.md) {
return 3
} else if (width < breakpoints.lg) {
return 6
} else if (width < breakpoints.xl) {
return 7
} else {
return 8
}
}
const [columns, setColumns] = useState(getColumns(window.innerWidth))
const updateDimensions = () => {
setColumns(getColumns(window.innerWidth))
}
useEffect(() => {
window.addEventListener("resize", updateDimensions);
return () => window.removeEventListener("resize", updateDimensions);
}, []);
return (
<ImageList cols={columns}>
{/* list items ... */}
</ImageList>
)
}
Solution 3:[3]
I spotted a similar problem. The ImageList
renders a <ul>
tag in DOM. Hence I created my own ImageList
styled <ul>
component which works fine with ImageListItem
. Here as per the gridTemplateColumns
attribute for screens with display size sm
will show 2 images, display size md
will show 4 images
and display size lg
will show 5 images.
import * as React from 'react';
import ImageListItem from '@mui/material/ImageListItem';
import { styled } from '@mui/material/styles';
const ImageGalleryList = styled('ul')(({ theme }) => ({
display: 'grid',
padding: 0,
margin: theme.spacing(0, 4),
gap: 8,
[theme.breakpoints.up('sm')]: {
gridTemplateColumns: 'repeat(2, 1fr)'
},
[theme.breakpoints.up('md')]: {
gridTemplateColumns: 'repeat(4, 1fr)'
},
[theme.breakpoints.up('lg')]: {
gridTemplateColumns: 'repeat(5, 1fr)'
},
}));
export default function ImageGallery({imageData}) {
return (
<ImageGalleryList>
{itemData.map((item) => (
<ImageListItem key={item.img}>
// Replace this with your ImageListItem
</ImageListItem>
))}
</ImageGalleryList>
);
}
Solution 4:[4]
I resolved this by overriding column-count
property on ImageList (root component)
So, you can add breakpoints using sx props
<ImageList
sx={{
columnCount: {
xs: '1 !important',
sm: '2 !important',
md: '3 !important',
lg: '4 !important',
xl: '5 !important',
},
}}
>
{/* list items ... */}
</ImageList>
Solution 5:[5]
Instead of using ImageList I used "Image masonry" seems to work. https://mui.com/material-ui/react-masonry/#main-content
<Masonry columns={{ xs: 1, sm: 2, md: 3, lg: 4, xl: 5 }} spacing={{ xs: 1, sm: 2 }}>
Image masonry This example demonstrates the use of Masonry for images. Masonry orders its children by row. If you'd like to order images by column, check out ImageList.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Stormwaker |
Solution 3 | Agent RX |
Solution 4 | Maqsood Ahmed |
Solution 5 | atazmin |