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

实现堆叠式硬币布局:Vue+SCSS响应式样式适配问题求助

问题描述

想实现堆叠硬币效果,用Vue循环渲染硬币图片,通过SCSS的flex布局结合nth-child设置堆叠样式,桌面端显示正常,但缩放到平板或移动端时,硬币会移出可视区域。需要解决flex换行后非首个元素的样式适配问题。

Vue代码

<div class="coins__images">
      <img
        ref="img"
        class="coins__img"
        src="wallet/coin.png"
        v-for="coin of coinsQuantity"
        :key="coin"
      />
    </div>

SCSS代码

&__images {
    display: flex;
    justify-content: flex-start;
    align-items: flex-start;
    flex-wrap: wrap;
  }

  &__img {
    z-index: 100;

    @for $i from 1 through 100 {
      &:nth-child(#{$i + 1}) {
        z-index: calc(100 - #{$i});
        // transform: translateX(-10px);
        // transform: translateX(calc(-#{$i} * 10px));
        // background-color: red;
      }
    }
  }
解决方案

问题核心是全局nth-child计数导致换行后偏移量累计,第二行及以后的硬币会持续向左偏移超出容器。需要改为按行内元素索引计算偏移量,具体实现如下:

1. 修改Vue代码,绑定行内索引

给每个硬币添加行内索引的CSS变量,同时准备好动态计算每行可容纳硬币数量的逻辑:

<div class="coins__images">
  <img
    ref="img"
    class="coins__img"
    src="wallet/coin.png"
    v-for="(coin, index) of coinsQuantity"
    :key="coin"
    :style="`--row-index: ${index % maxCoinsPerRow}`"
  />
</div>

2. 添加JS逻辑计算每行容量

在Vue组件中监听窗口大小变化,动态更新每行可显示的硬币数:

export default {
  data() {
    return {
      coinsQuantity: 20,
      maxCoinsPerRow: 5
    }
  },
  mounted() {
    this.calculateMaxCoins()
    window.addEventListener('resize', this.calculateMaxCoins)
  },
  beforeUnmount() {
    window.removeEventListener('resize', this.calculateMaxCoins)
  },
  methods: {
    calculateMaxCoins() {
      const container = this.$el.querySelector('.coins__images')
      const coinWidth = this.$refs.img?.[0]?.offsetWidth
      if (!container || !coinWidth) return
      // 10px 是硬币重叠的宽度,可根据需求调整
      this.maxCoinsPerRow = Math.floor(container.offsetWidth / (coinWidth - 10)) || 1
    }
  }
}

3. 优化SCSS样式,基于行内索引计算偏移

去掉全局的nth-child循环,改用CSS变量实现每行内的堆叠逻辑:

&__images {
  display: flex;
  justify-content: flex-start;
  align-items: flex-start;
  flex-wrap: wrap;
  // 用负margin实现重叠(gap不支持负值)
  margin-right: -10px;
}

&__img {
  position: relative;
  z-index: 100;
  margin-right: 10px;
  // 仅在当前行内计算偏移,换行后重置
  transform: translateX(calc(var(--row-index, 0) * -10px));
  // 行内z-index递减,保证前面的硬币在下层
  z-index: calc(100 - var(--row-index, 0));
}

替代方案:使用Grid布局

如果更倾向Grid布局,可通过grid-template-columns自动适配每行数量,同样结合行内索引变量实现堆叠:

&__images {
  display: grid;
  // 基于动态计算的每行数量设置列宽
  grid-template-columns: repeat(auto-fill, minmax(calc((100% / var(--max-coins)) + 10px), 1fr));
  margin-right: -10px;
}

&__img {
  position: relative;
  transform: translateX(calc((var(--row-index, 0)) * -10px));
  z-index: calc(100 - var(--row-index, 0));
}

这样修改后,无论屏幕如何缩放,每行的硬币都会从左到右依次重叠,不会出现换行后偏移出容器的问题。

内容的提问来源于stack exchange,提问作者Kustom

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 09:33:18