You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现类似三星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:

核心步骤

  1. 收集图片真实宽高比:遍历所有图片,用naturalWidth和naturalHeight计算宽高比,区分横屏(比值>1)和竖屏(比值<1)。
  2. 分组逻辑:
    • 横屏图单独占一行
    • 竖屏图每2-3个分为一组,剩余1个时可尝试合并到前一行(若前一行是横屏)
    • 支持混合组(如1竖+1横),通过宽高比总和分配宽度
  3. 动态生成布局:根据分组结果创建行容器,计算每张图片的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é

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 00:04:57