Any idea how a create dynamic perfect fitting img grids?

Anyone know how to create a perfect fitting img grid like on this example img?

http://puu.sh/ml3am/03b078b417.jpg

Every row needs to be full-width and every image in it to have the same height.

That’s a CSS question but something like this might suit you

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title></title>
  <style media="screen">
    html, body { height: 100%; margin: 0 }
    .table { display: table }
    .table-row { display: table-row }
    .table-cell { display: table-cell }
  </style>
</head>
<body>
  <div class="table" style="height: 50%; width: 100%">
    <div class="table-row">
      <div class="table-cell" style="width: 30%; background: #000">
      </div>
      <div class="table-cell" style="width: 20%; background: #111">
      </div>
      <div class="table-cell" style="width: 50%; background: #222">
      </div>
    </div>
  </div>
  <div class="table" style="height: 50%; width: 100%">
    <div class="table-row">
      <div class="table-cell" style="width: 20%; background: #333">
      </div>
      <div class="table-cell" style="width: 40%; background: #444">
      </div>
      <div class="table-cell" style="width: 20%; background: #555">
      </div>
      <div class="table-cell" style="width: 20%; background: #666">
      </div>
    </div>
  </div>
</body>
</html>

Hi there ReGGaeBOSS,

here is an alternative method…

[code]

untitled document body { background-color:#f0f0f0; } #container { width:96%; max-width:700px; border:1px solid #666; margin:auto; overflow:hidden; box-shadow:8px 8px 8px #999; } #container img { float:left; } #img1 {width:31.30%;} #img2 {width:18.84%;} #img3 {width:49.86%;} #img4 {width:18.55%} #img5 {width:39.13%;} #img6 {width:21.74%;} #img7 {width:20.58%;}
[/code]

coothead

Thanks,

Just one “detail” i forgot to mention, it has to be dynamic in the sense that I should be able to throw any pictures in there and the correct aspect rations etc will be calculated and images fitted=)

What controls the width of the cells in the grid as you have 3 on top and 4 on the bottom?

Are you creating rows manually with a variable number of images present or are these rows automatic in some way?

It all depends on what the answers to the questions above are and whether you can use foreground or background images also.

For a fully automatic solution you are probably looking at flexbox combined width object-fit for the images but support for object fit is not supported in IE (it does the same job as background-size does on background images).

Otherwise you will probably be looking at javascript to manipulate the image dimensions so that they cover the available space and maintain aspect ratio.

Here’s an example of flexbox and object-fit.

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<style>
.row {display: flex;background-color: red;}
.cell {flex: 1 1 0;text-align: center;background:blue;}
img {object-fit:cover;}
</style>
</head>

<body>
<div class="content">
  <div class="row"> 
  	<img class="cell" id="img1" src="http://placehold.it/300x100/f15/000" alt=""> 
  	<img class="cell" id="img2" src="http://placehold.it/250x150/f0f/000" alt=""> 
  	<img class="cell" id="img3" src="http://placehold.it/220x120/0ff/000" alt=""> 
  </div>
  <div class="row"> 
  	<img class="cell" id="img4" src="http://placehold.it/128x130/ddd/000" alt=""> 
  	<img class="cell" id="img5" src="http://placehold.it/250x150/0f0/000" alt=""> 
  	<img class="cell" id="img6" src="http://placehold.it/220x120/0af/000" alt=""> 
    <img class="cell" id="img7" src="http://placehold.it/142x202/f79/000" alt=""> 
  </div>
</div>
</body>
</html>

The images are all various sizes but scaled to fit with flexbox and then their aspect ratio controlled with object-fit. As mentioned above opject-fit is not supported in IE unfortunately.

Probably easier to see with real images.

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<style>
.row {display: flex;background-color: red;}
.cell {flex: 1 1 0;text-align: center;background:blue;}
img {object-fit:cover;}
</style>
</head>

<body>
<div class="content">
  <div class="row"> 
  	<img class="cell" id="img1" src="http://lorempixel.com/400/200/sports/" alt=""> 
  	<img class="cell" id="img2" src="http://lorempixel.com/300/150/sports/" alt=""> 
  	<img class="cell" id="img3" src="http://lorempixel.com/200/130/sports/" alt=""> 
  </div>
  <div class="row"> 
  	<img class="cell" id="img4" src="http://lorempixel.com/350/200/sports/" alt=""> 
  	<img class="cell" id="img5" src="http://lorempixel.com/450/250/sports/" alt=""> 
  	<img class="cell" id="img6" src="http://lorempixel.com/300/220/sports/" alt=""> 
    <img class="cell" id="img7" src="http://lorempixel.com/250/180/sports/" alt=""> 
  </div>
</div>
</body>
</html>

Hi there ReGGaeBOSS,

check out the attachment, which has a “JavaScript” solution. :sunglasses:

Bear in mind, though, that I am only a dabbler in the art. :ok:

ReGGaeBOSS.zip (120.6 KB)

coothead

1 Like

Looks pretty good to me and the code is very concise.:slight_smile:

Thats awesome mate. Thanks=)

Hi there ReGGaeBOSS,

just to make it a little better for those with
“JavaScript” disabled, change this “CSS”

.row img { float:left; outline:1px solid #fff; }

…to this…

.jsimg { float:left; outline:1px solid #fff; }

…and this “JavaScript”

for(c=0;c<i.length;c++) { w.push(i[c].offsetWidth); h.push(i[c].offsetHeight); hx=hx*h[c]; }

…to this…

for(c=0;c<i.length;c++) { i[c].className='jsimg'; w.push(i[c].offsetWidth); h.push(i[c].offsetHeight); hx=hx*h[c]; }

coothead

thanks!

Just a question to help me understand everything better.

clearInterval(si);
si=setInterval(function(){__checkRows();},1000);

What does this part do? It works if i lower the timer, but can i remove it completely? Well i know that it fires the __checkrows function every second and then clears it but why?

clearInterval(si); si=setInterval(function(){__checkRows();},1000);

It was not in my original test code which
worked perfectly in Firefox and IE11.

Unfortunately Chrome and Opera stuck
after the first iteration of the “for loops”.

The use of “setInterval” effected a cure. :ok:

Obviously, a “JavaScript” guru may have
a better method for re-sizing images. :sunglasses:

coothead

If you are clearing it every time then you are using the wrong call you can do it without needing to clear anything using:

setTimeout(function(){__checkRows();},1000);

That’s assuming that you don’t actually need the code to run every second and only really need it to run when the code that calls it is run. May be worth trying to see if it works as it will use less resources than setInterval

At Sitepoint a “JavaScript” guru will always turn up when summoned. :sunglasses:

1 Like

I just removed the interval and timeout altogether and it seems to be working fine just calling the function. What can be the downside of this be? If I need to wait for something else to finish before calling the function could one use some “fancier” solution using promises or something?=)

I’m kind of new to JS so excuse my dumb questions:P

Did you test in Chrome and Opera - the browsers coothead said had the problem that code was needed to fix.

Havent tried in opera but works fine in chrome.

Hi there ReGGaeBOSS,

in my testing I uploaded the files to my server and, without the
“setTimeout()”, the script did not work in Chrome or Opera. :ng:

Either way, you have nothing to lose by leaving it in. :ok:

coothead

Hi there ReGGaeBOSS,

further testing of the script showed “setTimeout()” to be
not entirely effective. :ng:

The script, although placed before the closing body tag,
did not always resize all of the images. :cold_sweat:

Replacing it with “window.addEventListener()” effected
a cure. :ok:

Go figure. :sunglasses:

Here is the current code…

[code]
(function() {

‘use strict’;

var i,c,w,h,hx,wx,t=0,
r=document.getElementsByClassName(‘row’),
co=document.getElementById(‘container’);

co.className=‘hide’; /* hide the container from view until script has completed */

function checkRows() { /* iterate through the rows */

if(t!==r.length){
i=r[t].getElementsByTagName(‘img’);/* all the images in a row /
w=[]; /
array for img widths /
h=[]; /
array for img hights /
hx=1; /
var for multiplication of image heights /
wx=0; /
var for addition of image widths /
resizeImage(i);
}
else {
co.className=‘’; /
show the container now the script has completed */
}
}

function resizeImage(i){ /* manipulate the image’s dimensions /
for(c=0;c<i.length;c++) {
i[c].className=‘jsimg’; /
change img CSS used for no javascript viewers /
w.push(i[c].offsetWidth);
h.push(i[c].offsetHeight);
hx=hx
h[c]; /* result of multiplication of image heights */
}
for(c=0;c<i.length;c++) {
w[c]=w[c]/h[c]hx; / img widths multiplied by hx divided by it’s own height /
wx=wx+w[c]; /
result of addition of image widths */
}
for(c=0;c<i.length;c++) {
w[c]=w[c]100/wx; / convet image widths to percentage value /
i[c].style.width=w[c]+‘%’; /
apply the CSS */
}
t++;
checkRows();
}
window.addEventListener(‘load’,checkRows,false);
})();[/code]

coothead

1 Like

Just a guess but maybe it would have worked if you has supplied the width and height attributes in the html so that the browser didn’t need to wait until all the images loaded?