英文:
Displaying photos that fill the grid - regardless of aspect ratio
问题
以下是翻译的内容:
我正在尝试在React中创建一个家庭学习项目的照片库。我能够在网格中显示照片:
使用以下代码:
const Container = styled.div`
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-gap: 10px;
justify-items: center;
align-items: center;
margin: 0;
padding: 0;
`
const PhotoWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
height: 200px; /* 为每个网格项设置固定高度 */
`
const Photo = styled.img`
max-width: 100%;
max-height: 100%;
object-fit: contain;
height: 100%; /* 使图像填充网格项的高度 */
`
const Home = () => {
return (
<Container>
{imagesData.map((image) => <PhotoWrapper><Photo src={image.imageUrl} /></PhotoWrapper> )}
</Container>
)
}
export default Home
这差不多是我想要的,但是...我想让它更像Flickr。他们在填充网格时做得非常出色,而且不会拉伸照片(据我所知)。
示例:
https://www.flickr.com/prints/discover
他们是如何保持行的长度和高度一致的?是否有一些出色的CSS技巧?或者可能有很多后端工作来计算大小并看看什么适合?我怎样才能像那样显示我的网格?
编辑:已接受的解决方案非常适合我所需的。这是现在的样子:
唯一的问题是当少数照片放在最后一行时。它们被大大裁剪,很难看清它们是什么。是否有一种类似 :last
的类可以帮助解决这个问题?
英文:
I am trying to create a photo gallery as a home learning project in react. I am able to display the photos in a grid:
Using this code:
const Container = styled.div`
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-gap: 10px;
justify-items: center;
align-items: center;
margin: 0;
padding: 0;
`
const PhotoWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
height: 200px; /* set a fixed height for each grid item */
`
const Photo = styled.img`
max-width: 100%;
max-height: 100%;
object-fit: contain;
height: 100%; /* make the image fill the height of the grid item */
`
const Home = () => {
return (
<Container>
{imagesData.map((image) => <PhotoWrapper><Photo src={image.imageUrl} /></PhotoWrapper> )}
</Container>
)
}
export default Home
That's NEARLY how I want it, but... I want it to be more like Flickr. Who do an AMAZING job at filling the grid without stretching photos (That I can tell).
Example:
https://www.flickr.com/prints/discover
How do they manage to keep the rows the same length, and height? Is there some awesome CSS trick? Or is there maybe a load of backend work to calculate sizes and see what fits? How can I display my grid like that?
Edit: The solution accepted is amazing for what I need. Here's what it looks like for me now:
The only issue is when a small number of photos go onto the last row. The get cropped a lot, ad hard to see what they are. Is there a :last type class that could help this?
答案1
得分: 2
一个简单的解决方案是使用 object-fit
和 flex-wrap
。请注意,如果图片无法适应,则只会显示一部分。
首先,我们需要一个具有多个 .item
的 #gallery
:
<div id="gallery">
<div class="item">
<img src="https://www.example.com/img.png">
</div>
<!-- ... -->
</div>
由于无法预测图像的数量和宽度,我们将 #gallery
设置为 flex-wrap: wrap
容器。
#gallery {
display: flex;
flex-wrap: wrap;
}
然后,允许 .item
在其行上自由扩展,行的高度固定为 100px
或您选择的其他值:
.item {
flex: 1 1 auto;
height: 100px;
}
最后,为图像设置 object-fit: cover
。这个设置,再加上 height: 100%
和 width: 100%
,确保它们始终触碰两侧并溢出另外两侧:
.item img {
object-fit: cover;
height: 100%;
width: 100%;
}
尝试一下:
(最后的图像可能有点太宽,因为我们显示的图像数量有限,但通常使用infiniscroll来解决这个问题。)
【代码部分未翻译】
英文:
A simple solution is to use object-fit
and flex-wrap
. Note that only a portion of an image will be displayed if it doesn't fit.
First, we need a #gallery
with multiple .item
s:
<div id="gallery">
<div class="item">
<img src="https://www.example.com/img.png">
</div>
<!-- ... -->
</div>
As the number of images and their width cannot be predicted, we make #gallery
a flex-wrap: wrap
container.
#gallery {
display: flex;
flex-wrap: wrap;
}
We then allow .item
s to expand as much as they'd like on their row, which has a fixed height of 100px
or another value of your choice:
.item {
flex: 1 1 auto;
height: 100px;
}
Finally, set object-fit: cover
for the images. This, along with height: 100%
and width: 100%
, ensure that they will always touch two sides and overflow the other two:
.item img {
object-fit: cover;
height: 100%;
width: 100%;
}
Try it:
(The last images might be a bit too wide, since we are displaying a limited number of images, but infiniscroll is normally used to overcome this.)
<!-- begin snippet: js hide: true console: false babel: false -->
<!-- language: lang-js -->
/**
* Randomly add 15 - 44 images, of which sizes are in range 100 - 499.
**/
const gallery = document.querySelector('#gallery');
const l = 15 + Math.random() * 30 | 0;
for (let i = 0; i < l; i++) {
const wrapper = document.createElement('div');
const img = document.createElement('img');
const [width, height] = [0, 0].map(
_ => 100 + Math.random() * 400 | 0
);
wrapper.classList.add('item');
img.src = `https://picsum.photos/${width}/${height}`;
wrapper.appendChild(img);
gallery.appendChild(wrapper);
}
<!-- language: lang-css -->
#gallery {
display: flex;
flex-wrap: wrap;
gap: 1em;
}
.item {
flex: 1 1 auto;
display: flex;
height: 100px;
}
.item img {
object-fit: cover;
object-position: center center;
height: 100%;
width: 100%;
}
body {
background: #000;
}
<!-- language: lang-html -->
<div id="gallery"></div>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论