简体   繁体   中英

Creating rows of unknown-size images that scale to 100% of container width

Given a set of images with random dimensions, I'm trying to display them in rows so that each row takes up 100% of the container width, and the space between each image is approximately the same. Because I don't know the dimensions beforehand, I also don't know how many images will end up in a row. Right now, I'm using a container with flex wrap, and inside the container is a list of image wrappers with a set height and max-width (so very wide images are cropped). The images themselves have height: 100% and width: auto. Then I have a resizing function that uses the offset top values to figure out which images are in a row, and scales them up based on a factor calculated from the sum of the widths of the images in that row.

It kind of works, but not very well - for one thing, I'm executing the resizing function on a timeout because if I don't, it will try to resize before the images are all loaded, which causes problems. Also, the factor isn't perfect, so I end up with slightly jagged edges on the right side of the container. I can do the resizing twice, and that gives results that are close enough, but that seems silly. I know I can give the container justify-content: space-between to take care of jagged edges on the left and right of the container, but it would be nice to just get it right (and the differences in spacing are kind of annoying). The last issue is if the window is resized after loading, the whole grid is messed up. I guess I could solve this with setInterval on the resizing function, but that seems messy (and this is already a messy solution).

( Edit : I tried using setInterval, and it gives nicer results for everything but the window-resizing problem, because once you shrink the window enough to cause flex to wrap differently, sizing the window back up will never allow things to wrap the way they did before.)

Is there a better solution? The timeout and window-resizing are the main problems. Ideally, I would end up with something like the Google Image results page, or the front page of DeviantArt. I'm fine with using another grid framework, as long as it does what I need. Here's my code (I'm using Bootstrap, so some of the formatting is in the HTML classes):

HTML/ERB:

<div class="img-grid d-flex flex-wrap m-n1">
  <% images = create_placeholder_array %>
  <% images.each do |img| %>
    <%= link_to(img[:url],
      class: 'img-wrapper position-relative m-1') do %>
      <%= image_tag(img[:url], class: 'grid-img-wide', height: img[:height], width: img[:width]) %>
    <% end %>
  <% end %>
</div>

(The create_placeholder_array helper just makes an array of URLs to placeholder.com for images with random sizes.)

CSS:

.img-wrapper {
  max-width: 320px;
  min-width: 100px;
  height: 200px;
  overflow: hidden;
}

.grid-img-wide {
  height: 100%;
  width: auto;
}

JavaScript/JQuery:

document.addEventListener("turbolinks:load", function () {
    imagesPerRow = 0
    widthPerRow = 0
    currOffset = $('.img-wrapper').offset().top
    setTimeout(function() {
      $('.img-wrapper').each(function(i) {
        if (currOffset == $(this).offset().top) {
          imagesPerRow++;
          widthPerRow += $(this).outerWidth(true);
        } else {
          factor = $('.img-grid').innerWidth() / widthPerRow;
          console.log('factor: ' + factor);
          $('.img-wrapper').slice(i - imagesPerRow, i).each(function() {
            $(this).css('height', $(this).innerHeight() * factor + 'px');
            $(this).css('max-width', $(this).innerWidth() * factor + 'px');
          })
          currOffset = $(this).offset().top;
          imagesPerRow = 1;
          widthPerRow = $(this).outerWidth(true);
        }
      });
    }, 1000)
});

Thanks for your help!

have you tried changing your javascript reference of the event listener from document to window?

refer to this to learn the difference.

window.addEventListener("load", function () {
    ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM