10

I'm trying to make an "image mosaic" that consists mostly of images of the same size, and some of them the double height.

They all should align neatly like this:

goal

To make automatic generation of those mosaic as easy as possible, I thought floating them would be the best option. Unfortunately, the big block causes the following ones to flow behind it, but not before:

current floats

What can I do - apart from manually positioning them - to get the images to the place I want, and still have it easy to automatically create likewise layouts?


The code I'm currently using is :

FIDDLE

HTML :

<div class="frame">
    <div id="p11" class="img">1.1</div>
    <div id="p12" class="img h2">1.2</div>
    <div id="p13" class="img">1.3</div>
    <div id="p21" class="img">2.1</div>
    <div id="p22" class="img">2.2</div>
</div>

CSS :

.frame {
    background-color: blue;
    border: 5px solid black;
    width: 670px;
}
.img {
    width: 200px;
    height: 125px;
    background-color: white;
    border: 1px solid black;
    float: left;
    margin: 10px;
}
.h2 {
    height: 272px;
}
web-tiki
  • 99,765
  • 32
  • 217
  • 249
cweiske
  • 30,033
  • 14
  • 133
  • 194
  • 3
    see my answer here - http://stackoverflow.com/questions/9588591/how-to-float-these-boxes-so-that-they-fit-snug-together/9588627#9588627 – Alex Mar 07 '12 at 20:57

4 Answers4

3

You need to use Javascript to achieve this effect, I had to do that once and I used http://masonry.desandro.com/ -- worked well!

allaire
  • 5,995
  • 3
  • 41
  • 56
  • 3
    Could you provide a code example? This answer isn't very helpful to anybody otherwise. – BoltClock Mar 07 '12 at 22:08
  • It's still the right answer-- CSS doesn't really do vertical floating. Masonry and Isotope (both by the same guy) achieve exactly what OP wants. – Interrobang Mar 07 '12 at 23:53
  • @BoltClock You want me to re-code a whole plugin made especially for what he wants just to show him a "code exemple"? And the link I pasted already provides multiple demos that will be updated if the plugin ever gets updated. Oh well... – allaire Mar 08 '12 at 02:11
  • @Interrobang--there is a CSS answer, see the fiddle in my answer. – ScottS Mar 08 '12 at 03:28
1

Pure CSS Solution

Tested in Firefox, IE8+ (IE7 looks like it would need to be targeted to add a top margin added to 2.1 because it overlaps 1.1). See fiddle. This assumes .h2 is the middle div (as your example). If left most div it should not need any change. If right most, you would need to expand the negative margin to also include the third div following.

.h2 + div {
    float: right;
    margin: 10px 14px 10px 0; /*14px I believe also has to do with borders */
}

.h2 + div + div {
    margin-left: -434px; /*need to account for borders*/
    clear: right;
}
ScottS
  • 71,703
  • 13
  • 126
  • 146
  • Interesting idea. Unfortunately, the double-height div can move, and the real mosaic is 5x4 stones large, with several double-height pictures in there. – cweiske Mar 08 '12 at 05:15
1

You can use a column layout like this: http://jsfiddle.net/KKUZL/

I don't know if that will conflict with your automation process though....

es_beto
  • 21
  • 1
  • Thanks for the try. As you already guessed does that interfere with the automatic generation of the layout, since the computer just puts many pictures in the html and sets the property if it's normal sized or double height. In that case, it cannot determine where to add which divs to make it look right. – cweiske Mar 08 '12 at 05:13
0

I realize this is not a CSS-only solution, but for what it's worth (JSFiddle):

HTML:

<div id='container'></div>

CSS:

html, body {
    margin:0px;
    padding:0px;
    height:100%;
}
body {
    background-color:#def;
}
#container {
    margin:0px auto;
    width:635px;
    min-height:100%;
    background-color:#fff;
    box-shadow:0px 0px 5px #888;
    box-sizing:border-box;
    overflow:auto;
}
.widget {
    float:left;
    box-sizing:border-box;
    padding:10px 10px 0px 0px;
}
.widget > div{
    height:100%;
    box-sizing:border-box;
    color:#fff;
    font-size:3em;
    text-align:center;
    padding:.5em;
    overflow:hidden;
}
.widget > div:hover {
    background-color:purple !important;
}

JS:

////////////////////////////////////////
//  ASSUMPTIONS
//    
var TWO_COLUMN_WIDGET_COUNT = 1;
var ONE_COLUMN_WIDGET_COUNT = 15;

var NUMBER_OF_COLUMNS = 2;

////////////////////////////////////////
function rand(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}
var colorFactory = (function () {
    var colors = [
        '#CC9A17',
        '#9B2C16',
        '#1A8B41',
        '#D97114',
        '#3B9EE6'];
    var index = 0;
    return function () {
        if (index > 4) {
            index = 0;
        }
        return colors[index++];
    }
})();
function widgetFactory(columnSpan) {
    return {
        'height': rand(10, 30) * 10,
            'width': 100 * columnSpan / NUMBER_OF_COLUMNS,
            'columnSpan': columnSpan,
            'color': colorFactory()
    }
}
function getWidgets() {
    var widgets = [];
    for (var i = 0; i < TWO_COLUMN_WIDGET_COUNT; i++) {
        widgets.push(widgetFactory(2));
    }
    for (var i = 0; i < ONE_COLUMN_WIDGET_COUNT; i++) {
        widgets.push(widgetFactory(1));
    }
    return widgets;
}
function getHighestOffset(offsets){

}
function getHighestSlot(offsets, numOfColumns){

}
$(document).ready(function () {
    var container = $('#container');
    var widgets = getWidgets();
    var col1 = Math.floor(container[0].offsetLeft);
    var col2 = Math.floor(container[0].clientWidth / 2 + container[0].offsetLeft);
    var offsets = {};
    offsets[col1] = 0;
    offsets[col2] = 0;
    var newLine = true;

    for (var i = 0; i < widgets.length; i++) {
        var w = widgets[i];
        var marginTop = 0;
        if (offsets[col1] < offsets[col2]) {
            marginTop = (offsets[col2] - offsets[col1]) * -1;
        }
        if(offsets[col1] <= offsets[col2] || w.columnSpan == 2){
            newLine = true;
        }
        var margin = 'margin-top:' + marginTop + 'px;';
        var height = 'height:' + w.height + 'px;';
        var color = 'background-color:' + colorFactory() + ';';
        var width = 'width:' + w.width + '%;';
        var padding = newLine ? "padding-left:10px;" : "";
        var component = $('<div class="widget" style="' + padding + margin + height + width + '"><div style="' + color + '">' + i + '</div></div>');
        component.appendTo(container);
        var c = component[0];

        var index = 0;
        var minOffset = null;
        for(var p in offsets){
            if(minOffset == null || offsets[p] < minOffset){
                minOffset = offsets[p];
            }
            if(p == Math.floor(c.offsetLeft)){
                index = 1;
            }
            if(index > 0 && index <= w.columnSpan){
                offsets[p] = c.offsetTop + c.offsetHeight;
                index++;
            }
        }
        newLine = minOffset >= offsets[col1];
    }
});
Trevor
  • 13,085
  • 13
  • 76
  • 99