6

I'm creating a 2 column masonry layout using images of different sizes. The images can be any size as long as they have the greatest common divisor (as required by the Masonry plugin).

In order to make the layout responsive I'm converting the width of the masonry items into percent (or I can use min-width and width 100%).

Update: I noticed that many who answer make both columns 50% as a solution. That works but is not the goal. Images have to retain their original image size. They can shrink but keep the same ratio.

$(function () {    
    var container = $('#container');

    // Convert .box width from pixels to percent
    $('.box').find('img').each(function () {
        var percent = ($(this).width()) / container.width() * 100 //convert to percent;
        $(this).closest('.box').css('max-width', percent + '%');
    });

    // Trigger masonry
    container.masonry({
        itemSelector: '.box',
        columnWidth: 1 //widths dividable by 1
    });
});

jsfiffle: http://jsfiddle.net/AMLqg/278/

This seems to work. The items are fluid when you resize the window. However if you load the script in a small window size (smaller than the 2 column width) the items collapse. How can I keep the masonry items responsive on window load even when the window is smaller?

Update: Here is more info for a better understanding. I'm trying to keep 2 responsive columns regardless of the window size. The columns can't have equal widths because the images have different widths. For this reason I'm using columnWidth: 1 because all widths are dividable by 1.

Please see images below for examples.

Problem: When you open the page in a small window the elements are collapsed. When you resize the window to be larger the elements remain collapsed until the window width is larger than the width of both elements.

enter image description here

Goal: I'm trying to keep the elements in 2 responsive columns on load like in the image below. Currently they remain responsive if on load the window is large and you resize it to be smaller but not vice verse when window is small on load and you make it larger.

enter image description here

Community
  • 1
  • 1
CyberJunkie
  • 18,604
  • 50
  • 135
  • 207
  • Put your code inside `$(window).load(function() {` and try again. See if that works. Images do not have `width` / `height`, until they are loaded. `$(document).ready` fires, before images are loaded. – Jashwant Nov 13 '14 at 17:54
  • 1
    I'm sorry, but I'm not seeing the problem in your JSFiddle. You don't want the images to stack when the window is smaller? – Drazzah Nov 13 '14 at 17:55
  • @Godisgood yes I don't want them to stack. Try making the window smaller than the container width and run the script again. You will see that they stack. I'm trying to avoid that. – CyberJunkie Nov 13 '14 at 20:00
  • You would need to make a `min-width` CSS property to keep that from happening. Check out @JoshBurgess's answer. – Drazzah Nov 13 '14 at 20:01
  • @Godisgood please see update. I added images to better explain the issue. Thank you! – CyberJunkie Nov 13 '14 at 20:12
  • @Jashwant `$(function()` has the same functionality I believe. I tried on load too but doesn't work. – CyberJunkie Nov 13 '14 at 20:16
  • 2
    If you want two responsive columns, you don't even need the masonry layout. That may be your problem, that you don't need the masonry layout. – Drazzah Nov 13 '14 at 20:43
  • 1
    I left masonry in for the edited response, but it's pointless if that's the desired output. – Josh Burgess Nov 13 '14 at 22:43

9 Answers9

0

You can try overflow:hidden on the surrounding box.

Gigamegs
  • 12,342
  • 7
  • 31
  • 71
  • do you mean on `#container`? That doesn't work unfortunately. – CyberJunkie Nov 11 '14 at 15:15
  • @CyberJunkie:I had this problem, too. Maybe a bit different buy you are doing sth. wrong. Maybe you can try my solution here:http://stackoverflow.com/questions/7971258/masonry-images-overlapping-issue/7971857#7971857. Read also the comment from the creator.BTW. did you try packery. It seems to solve many problems but its not free for commercial use. – Gigamegs Nov 13 '14 at 23:07
0

Are you looking for something like this?

Fiddle

So, all we're doing here is getting rid of your percentage calculation (of which I really don't understand the necessity), and setting a min-width on the .box class. Just like this:

.box {
    float: left;
    min-width: 100px;
}

I was able to reproduce your problem. This is how it looks for those curious:

The stacking collapse problem

The problem is your float: left rule in the CSS, which is collapsing the box when Masonry is doing its positioning calculations after adding the image. You can do a simple clear-fix to keep this if you really need to keep that clunky percentage calculation, like so:

.container:after {
   content: '';
   display: table;
   clear: both;
}

Hope that helps!

Edit – Based on your comments:

Okay, if you always want there to be two columns, it's an even simpler change:

Get rid of this Javascript

// Convert .box width from pixels to percent
$('.box').find('img').each(function () {
    var percent = $(this).width() / container.width() * 100;
    $(this).closest('.box').css('max-width', percent + '%');
});

Add this CSS

.box {
   max-width: 50%;
}

Fairly straightforward, I think.

Here's a fiddle, just for giggles

Community
  • 1
  • 1
Josh Burgess
  • 8,696
  • 30
  • 45
  • Thanks but that was not the issue. I don't want the images to collapse beneath eachother when you resize the window or load it while it's small. Basically I want to keep 2 columns regardless of the window size. I can't figure out how to do that. – CyberJunkie Nov 13 '14 at 20:03
  • Couldn't you just remove `Masonry` then? Seems to work for me. – Josh Burgess Nov 13 '14 at 20:34
  • I have to use masonry – CyberJunkie Nov 13 '14 at 21:24
  • I dont think elements will stack without js masonry. I also cant use html tables. – CyberJunkie Nov 13 '14 at 21:30
  • @CyberJunkie – They'll definitely stack, and you don't need tables for this by any stretch of the imagination. Check the edit, there's very little extra you need to do given the two column constraint. – Josh Burgess Nov 13 '14 at 22:43
  • making the grid-sizer 50% adds a gap between the images when the window is larger because the images don't have equal widths. I use `1` in the `columnWidth` property for masonry to position the elements properly. As far as I know the layout can't be achieved with CSS alone unless both columns and images have the same widths. – CyberJunkie Nov 14 '14 at 21:54
  • And something like this doesn't solve this problem? http://jsfiddle.net/org6nsr8/4/ – Josh Burgess Nov 14 '14 at 22:06
  • Or if you wanted to force it to fill all the available space of the container: http://jsfiddle.net/org6nsr8/5/ – Josh Burgess Nov 14 '14 at 22:09
0

Using imagesloaded.js and columnwidth set using css like so:

jsFiddle

<div id="container">
<div class="grid-sizer"></div>
<div class="box">
    <img src="http://images.huffingtonpost.com/2007-11-01-ice.jpg" />
</div>
<div class="box">
    <img src="http://www.wwalls.ru/mini/201211/57608.jpg" />
</div>
<div class="box">
    <img src="http://artistsandwriters.com/site/wp-content/uploads/2014/09/IMG_7303LR-390x150-1412284267.jpg" />
</div>
</div>

Script

$(document).ready(function () {
 var container = $('#container');

 $('.box').find('img').each(function () {
     var percent = $(this).width() / container.width() * 50;
     $(this).closest('.box').css('max-width', percent + '%');
 });

 // Trigger masonry
 container.imagesLoaded(function () {
     container.masonry({
         itemSelector: '.box',
         columnWidth: '.grid-sizer'
     });
 });
 });

CSS

#container {
max-width:580px;
}
.box {
float: left;
margin-bottom: 5px;
}
.box img {
 width: 100%;
}
.grid-sizer {
 width: 50%;
 }
Macsupport
  • 5,144
  • 3
  • 24
  • 41
0

EDIT

Check this http://jsfiddle.net/gk3t009j/2/

CSS

#wrapper
{
    background-color: red;
    margin: 0 auto; max-width:580px;
}

#container,
{
       overflow: hidden; 
       width: 100%;
}
.box
{       
    max-width: 290px!important; width: 50%;     
}

.box img{width: 100%;}

JS

$( window ).load( function()
{
    var wc=$( '#container').width();
    wc=parseInt(wc);
    if( wc % 2) 
    {
        var wb=$('.box').width();
        wb--;
        $('.box').width(wb)
    } 


    $( '#container').masonry(
    {
        itemSelector: '.box',
        columnWidth: function( containerWidth ) {
            return parseInt(containerWidth / 2);
          }

    });
});

HTML

<div id="wrapper">
    <div id="container">
        <div class="box">
            <img src="http://images.huffingtonpost.com/2007-11-01-ice.jpg" />
        </div>



        <div class="box">
                <img src="http://www.wwalls.ru/mini/201211/57608.jpg" />
            </div>
            <div class="box">
                <img src="http://artistsandwriters.com/site/wp-content/uploads/2014/09/IMG_7303LR-390x150-1412284267.jpg" />
            </div>
    </div>
</div>
dm4web
  • 4,504
  • 1
  • 12
  • 20
0

I removed the JS code and some of the HTML markup and updated the styling:

#container {
    width: 100%;
}
img {
    display: inline;
    vertical-align: top;
    float: left;
    min-width: 50%;
    width: 50%;
}

http://jsfiddle.net/org6nsr8/8/ I agree with Josh Burgess on that Masonry is not needed to accomplish this, take a look and see if this is what you're after.

I'd be happy to elaborate if something is unclear or you want anything explained.

Viktor
  • 257
  • 1
  • 5
  • Thanks for the help. I can't use 50% for each column and alter the original image size. The goal is to use images of different widths. – CyberJunkie Nov 18 '14 at 20:42
0

You don't need the JavaScript; just change the css for .box to:

.box {
    float: left;
    max-width: 50%;
}
Salil Dabholkar
  • 622
  • 3
  • 7
0

I am not sure if this is what you need. If I understood the problem correctly may be you need to use max-width instead of width.

Here is example fiddle : http://jsfiddle.net/AMLqg/304/

My JS code :

        $(function () {

            var container = $('#container');
            var maxWidth = container.css("maxWidth");
            maxWidth = parseInt(maxWidth.substring(0,maxWidth.indexOf("px")));
            // Convert .box width from pixels to percent
            $('.box').find('img').each(function () {
                var percent = ($(this).width()) / maxWidth * 100;
                console.log(percent);
                $(this).closest('.box').css('max-width', percent + '%');
            });

            // Trigger masonry
            container.masonry({
                itemSelector: '.box',
                columnWidth: 1 //widths dividable by 1
            });
        });
Abhas Tandon
  • 1,757
  • 15
  • 25
0

After trying several library to make a masonry layout , I prefer salvattor.js

Very easy to use. the size of the columns you can configure css.

@media screen and (max-width: 480px){
    #grid[data-columns]::before {
        content: '1 .column.size-1of1';
    }
}
Queli Coto
  • 586
  • 4
  • 9
0

What i understand you want to keep Layout 2 Column with Images on aspect ratio on all screen sizes ,

Check

http://jsfiddle.net/tasaeed/k40cgfye/

CSS

#container {
  max-width: 580px;
}

.box {
  float: left;
  width:50%;
}

.box img {
  width: 100%;
  height:auto;
}

Script

$(function () {

    var container = $('#container');

    // Trigger masonry
    container.masonry({
        itemSelector: '.box',
    });
});