I have array of object ImageKist where I would like to show alternate image with different heights using grid or flex as shown below:
How can I achieve above pattern using grid or flex?
Install styled-component as follow: npm install --save styled-components
Current result is as below where images should come from left to right where I have used grid but its fine if we get the desired result with flex.
Below is my code with alternate images:
import styled from "styled-components";
import React from "react";
const App = () => {
const imageList = [
{
id: "1",
url: "https://images.unsplash.com/photo-1558979158-65a1eaa08691?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80",
},
{
id: "2",
url: "https://images.unsplash.com/photo-1572276596237-5db2c3e16c5d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80",
},
{
id: "3",
url: "https://images.unsplash.com/photo-1507525428034-b723cf961d3e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1353&q=80",
},
{
id: "4",
url: "https://images.unsplash.com/photo-1551009175-8a68da93d5f9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1351&q=80",
},
{
id: "5",
url: "https://images.unsplash.com/photo-1549880338-65ddcdfd017b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80",
},
{
id: "6",
url: "https://res.cloudinary.com/diqqf3eq2/image/upload/v1586883334/person-1_rfzshl.jpg",
},
{
id: "7",
url: "https://res.cloudinary.com/diqqf3eq2/image/upload/v1586883409/person-2_np9x5l.jpg",
},
{
id: "8",
url: "https://res.cloudinary.com/diqqf3eq2/image/upload/v1586883417/person-3_ipa0mj.jpg",
},
];
return (
<Wrapper>
{imageList.map((image: any, index) => (
<>
{index % 2 === 0 ? (
<ImageWrapper key={image.id}>
<ImageStyled src={image.url} alt={image.url} />
<H4Styled>{image.id}</H4Styled>
</ImageWrapper>
) : (
<ImageWrapper1 key={image.id}>
<ImageStyled src={image.url} alt={image.url} />
<H4Styled>{image.id}</H4Styled>
</ImageWrapper1>
)}
</>
))}
</Wrapper>
);
};
export default App;
const Wrapper = styled.div`
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 80px;
gap: 30px;
`;
const ImageWrapper = styled.div`
overflow: hidden;
position: relative;
grid-row: span 2;
`;
const ImageWrapper1 = styled.div`
overflow: hidden;
position: relative;
grid-row: span 3;
`;
const ImageStyled = styled.img`
min-width: 100%;
height: 100%;
border-radius: 20px;
`;
const H4Styled = styled.h4`
position: absolute;
top: 16px;
color: white;
`;
Update
Only quickly tested but this seems to work for me in TypeScript:
interface ImageWrapperProps {
index: number;
}
And apply the interface
to the component using index
as prop:
const ImageWrapper = styled.div`
overflow: hidden;
position: relative;
border-radius: 20px;
grid-row: ${({ index }: ImageWrapperProps) =>
(index + 1) % 2 === 0 ? 'span 3' : 'span 2'};
grid-column: ${({ index }: ImageWrapperProps) =>
(index + 2) % 6 === 0 ? '2' : 'auto'};
`;
It probably depends on configurations, so if it does not work perhaps also reference some suggestions to use TypeScriptt with styled-components
from this question.
Also if not done yet perhaps try install @types/styled-components
in the project:
npm install @types/styled-components
Original
It seems that the props of styled-components
can be used to simplify the logic and also manage the placement of images based on the index
.
The below example pass the index
as prop to ImageWrapper
and change the grid-row
and grid-column
based on index
as a condition, so there is no need to define 2 components for it.
The current condition works for a 3 column image list, but it can be adjusted in the styles to fit other layout, if needed.
Simplified live demo of example: stackblitz
Perhaps try:
const Wrapper = styled.div`
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 80px;
gap: 30px;
grid-auto-flow: row dense;
`;
// 👇 Use prop here to change style by condition
const ImageWrapper = styled.div`
overflow: hidden;
position: relative;
border-radius: 20px;
grid-row: ${({ index }) => ((index + 1) % 2 === 0 ? 'span 3' : 'span 2')};
grid-column: ${({ index }) => ((index + 2) % 6 === 0 ? '2' : 'auto')};
`;
const ImageStyled = styled.img`
width: 100%;
height: 100%;
object-fit: cover;
`;
const H4Styled = styled.h4`
position: absolute;
top: 16px;
color: white;
`;
And in the output:
<Wrapper>
{imageList.map((image, index) => (
<ImageWrapper key={image.id} index={index}>
<ImageStyled src={image.url} alt={image.url} />
<H4Styled>{image.id}</H4Styled>
</ImageWrapper>
))}
</Wrapper>