如何实现类似三星One UI的自适应等高图片画廊布局?
实现三星One UI风格图片画廊
单一行(竖屏+横屏图)的纯CSS实现
完全可以用纯CSS实现,核心是利用Flexbox结合图片宽高比动态分配宽度,同时保持等高且占满容器:
.gallery-row { display: flex; width: 100%; /* 占满手机宽度 */ gap: 4px; /* 图片间的间距,可按需调整 */ } .gallery-row img { flex: 1 1 auto; height: auto; object-fit: cover; /* 保持图片比例,裁剪多余区域 */ } /* 根据图片宽高比设置flex基准值,确保等高 */ /* 示例:竖屏图宽高比2:3,横屏图3:2 */ .gallery-row .portrait { flex-basis: calc(100% * (2/3) / ((2/3) + (3/2))); } .gallery-row .landscape { flex-basis: calc(100% * (3/2) / ((2/3) + (3/2))); }
<div class="gallery-row"> <img src="竖屏图地址" class="portrait" alt="竖屏图片"> <img src="横屏图地址" class="landscape" alt="横屏图片"> </div>
原理:通过flex-basis按宽高比的比例分配初始宽度,Flex布局会自动调整行内元素高度一致,object-fit: cover保证图片不拉伸变形,整体行容器占满手机宽度。
完整自动画廊的实现(需JS辅助)
由于图片数量不固定且需要动态分组(1张横屏/2-3张竖屏),纯CSS无法处理分组逻辑,必须结合JavaScript:
核心步骤
- 收集图片真实宽高比:遍历所有图片,用
naturalWidth和naturalHeight计算宽高比,区分横屏(比值>1)和竖屏(比值<1)。 - 分组逻辑:
- 横屏图单独占一行
- 竖屏图每2-3个分为一组,剩余1个时可尝试合并到前一行(若前一行是横屏)
- 支持混合组(如1竖+1横),通过宽高比总和分配宽度
- 动态生成布局:根据分组结果创建行容器,计算每张图片的
flex-basis值,确保行内图片等高且占满宽度。
简化版代码示例
const gallery = document.querySelector('.gallery'); const allImages = Array.from(document.querySelectorAll('.gallery img')); const rowGroups = []; let currentGroup = []; allImages.forEach(img => { const ratio = img.naturalWidth / img.naturalHeight; img.dataset.ratio = ratio; // 横屏图单独成组 if (ratio > 1) { if (currentGroup.length) { rowGroups.push([...currentGroup]); currentGroup = []; } rowGroups.push([img]); } else { // 竖屏图最多3个一组 if (currentGroup.length >= 3) { rowGroups.push([...currentGroup]); currentGroup = []; } currentGroup.push(img); } }); // 处理剩余的竖屏图 if (currentGroup.length) rowGroups.push([...currentGroup]); // 生成布局 rowGroups.forEach(group => { const row = document.createElement('div'); row.classList.add('gallery-row'); // 计算组内所有图片的宽高比总和 const totalRatio = group.reduce((sum, img) => sum + parseFloat(img.dataset.ratio), 0); group.forEach(img => { const ratio = parseFloat(img.dataset.ratio); // 分配flex-basis占比 img.style.flexBasis = `${(ratio / totalRatio) * 100}%`; row.appendChild(img); }); gallery.appendChild(row); });
.gallery { width: 100%; padding: 4px; } .gallery-row { display: flex; width: 100%; margin-bottom: 4px; gap: 4px; } .gallery-row img { flex: 1 1 auto; height: auto; object-fit: cover; }
关键提示
- 必须使用
object-fit: cover,否则图片会拉伸变形,不符合相册展示逻辑 - 用
naturalWidth/naturalHeight获取图片真实尺寸,避免DOM渲染尺寸的干扰 - 可根据需求调整分组规则,比如混合组的优先级、图片间距等
内容的提问来源于stack exchange,提问作者Chloé
相关产品推荐
相关产品推荐

