for loop - CSS masonry grid with dynamic rows width - Stack Overflow

admin2025-04-30  0

I am trying to create a masonry grid gallery of pictures. The pictures are looped from an array and I want to make wider images to expand on both the columns of the grid.
This is what would like to achieve:

the result I want to achieve

I am actually using tailwind to simplify, but i can throw some custom CSS to complete it.

<div class="columns-2 gap-4 space-y-4">
        <div v-for="(image) in project.images" :key="image.indexOf">
          <img class="w-full rounded-xl shadow" :src="`${image}`" alt="">
        </div>
</div>

now there is a version with only columns and i found out about other grid options like this:

.grid {
    display: grid;
    grid-template-columns: 2, 1fr);
    grid-template-rows: masonry;
    grid-auto-flow: dense;
    /* align-tracks: stretch; */
  }

but I cannot find a way to change the columns dynamically only for wider images, spanning on 2 columns

I am trying to create a masonry grid gallery of pictures. The pictures are looped from an array and I want to make wider images to expand on both the columns of the grid.
This is what would like to achieve:

the result I want to achieve

I am actually using tailwind to simplify, but i can throw some custom CSS to complete it.

<div class="columns-2 gap-4 space-y-4">
        <div v-for="(image) in project.images" :key="image.indexOf">
          <img class="w-full rounded-xl shadow" :src="`${image}`" alt="">
        </div>
</div>

now there is a version with only columns and i found out about other grid options like this:

.grid {
    display: grid;
    grid-template-columns: 2, 1fr);
    grid-template-rows: masonry;
    grid-auto-flow: dense;
    /* align-tracks: stretch; */
  }

but I cannot find a way to change the columns dynamically only for wider images, spanning on 2 columns

Share Improve this question asked Jan 5 at 1:01 JacopoDJacopoD 11 bronze badge
Add a comment  | 

1 Answer 1

Reset to default 0

Using grid, you can apply grid-columns: span 2 via the col-span-2 Tailwind class to have an element take up two columns.

To determine if an image is wide enough, you'd have to wait for it to load so that you can get its dimensions. Then, you can do some conditional check to determine if it should be considered wide.

const { createApp } = Vue;

const app = createApp({
  data() {
    return {
      project: {
        images: [
          'https://picsum.photos/400/400',
          'https://picsum.photos/400/400?',
          'https://picsum.photos/816/400',
          'https://picsum.photos/400/400?0',
          'https://picsum.photos/400/400?1',
        ],
      },
      wideImages: [],
    };
  },
  mounted() {
    this.$refs.images.forEach(
      (img) => {
        if (img.complete) {
          this.maybeMarkWideImage(img);
        } else {
          img.addEventListener('load', () => {
            this.maybeMarkWideImage(img);
          });
        }
      }
    );    
  },
  methods: {
    maybeMarkWideImage({ src, naturalWidth }) {
      if (naturalWidth > 600) {
        this.wideImages = this.wideImages.concat(src);
      }
    },
  },
});

app.mount('#app');
<script src="https://cdn.tailwindcss.com/3.4.16"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.3.4/vue.global.min.js" integrity="sha512-Wbf9QOX8TxnLykSrNGmAc5mDntbpyXjOw9zgnKql3DgQ7Iyr5TCSPWpvpwDuo+jikYoSNMD9tRRH854VfPpL9A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<div id="app">
  <div class="grid grid-cols-2 gap-4">
    <div
      v-for="(image) in project.images"
      :key="image.indexOf"
      :class="wideImages.includes(image) && 'col-span-2'"
    >
      <img
        class="w-full rounded-xl shadow"
        :src="`${image}`"
        alt=""
        ref="images"
      >
     </div>
  </div>
</div>

转载请注明原文地址:http://anycun.com/QandA/1746020700a91447.html