jquery implementation of Waterfall flow layout (PC and mobile end) _jquery

Source: Internet
Author: User

Waterfall Flow layout has become a very popular way to display pictures today, whether it is PC or mobile devices such as cell phones. This kind of layout picture's style is divided into three kinds: equal high width, equal width unequal high, equal height unequal width, next we are the most common equal width unequal high form comes as example.

We use Baidu image as an example:

This is the PC side of the more common waterfall flow layout, next we review the elements to see how Baidu picture inside is how to layout:

As you can see, it's actually a number of equal-width column containers that push pictures into different containers by calculating. This article describes the presentation method is through positioning, although the final layout shows different ways, but the previous algorithms are similar.

Do it

First we write several units of the following style into the body and float "box" to the left:

<div class= "box" >
  <div "class="
 > description</div>
</div>
<div class= "box" >
 
 <div class=" desc ">Description</div>
</div>
<div class=" box " >
  <div class= "desc" >description</div
 >
</div>

Get the following effect:

Next:

var Boxarr = $ ('. Box '),
num = Math.floor (document.body.clientwidth/boxarr.eq (0). Outerwidth (True)),
 Columnheightarr = [];
Columnheightarr.length = num;
Boxarr.each (function (index, item) {
 if (Index < num) {
 Columnheightarr[index] = $ (item). Outerheight (True); c7/>} else {
 var minheight = Math.min.apply (null, Columnheightarr),
 minheightindex = $.inarray (MinHeight, Columnheightarr);

 $ (item). css ({
 position: ' absolute ',
 top:minheight,
 left:boxArr.eq (minheightindex). Position (). Left
 });
 

The above code has the following effect:

1. First calculate how many pictures (num) can be accommodated in a row in the browser, note that the outerwidth is used and the dimensions of the elements including margin, padding, border all box model attributes are returned when true is passed in.

2. Create an array (Columnheightarr) that stores the height of each column, the length of which is the NUM value;

3. Iterate through all the pictures, the first row of the picture height into the column high Array (Columnheightarr), starting from the second row, first calculate the minimum height of all columns (minheight) and the minimum height of the column (Minheightindex). The second row begins with a picture positioned below the height of the smallest column, with the following effect:

You can see that although the place is right, all the pictures are in the same place, because we need to increase the height of the column after placing a picture:

var Boxarr = $ ('. Box '),
 num = Math.floor (document.body.clientwidth/boxarr.eq (0). Outerwidth (True)),
 Columnheightarr = [];
Columnheightarr.length = num;

Boxarr.each (function (index, item) {
if (Index < num) {
Columnheightarr[index] = $ (item). Outerheight (True)  ;
else {
var minheight = Math.min.apply (null, Columnheightarr),
 minheightindex = $.inarray (MinHeight, Columnhe    Ightarr);

$ (item). css ({
 position: ' absolute ',
 top:minheight,
 left:boxArr.eq (minheightindex). Position ().    Left
 });

Columnheightarr[minheightindex] + = $ (item). Outerheight (true);
}
});

The result is correct:

Note: The above code needs to run in the Window.onload method, because the height of each picture will not be valid until the picture resource in the page is loaded.

So there will be some serious problems, when the network is bad when the picture is not fully loaded to complete the picture shows an incomplete height of the situation, which is very obvious at the mobile end. And when we load more, it's harder to tell whether the newly appended picture is loaded.

In actual production there will be no case of writing the images to death in HTML in the first place, so we usually do it in the following ways:

First of all, we need to get the picture address at the same time to get the picture width and height, which is not difficult to the backend of the service, you can come back to the brother of the picture of the wide high data into the JSON, passed to you;

* Next to the introduction of the tips, very practical, it can ensure that an element regardless of the size of the change, the proportion always consistent . This technique is especially useful for moving ends, because elements typically use percentages in response.

If the phone page has a picture, its width to be half of the screen, the aspect ratio of 2:1, need to be in any resolution of the phone to maintain the proportion unchanged. How to do it? Set the following properties for the element:

. box {
 width:50%;
 height:0;
 padding-bottom:100%;
}

Instead of setting the height, you use padding to "squeeze" the element height, while the padding percent value is based on the width of the parent container. How much do padding need to squeeze? is the width times the aspect ratio (both width and padding values are percentages), which is why we need to get the picture size.

Effect:

You can see that the ipone4 and kidney 6Plus display in the Chrome phone simulator is exactly the same. The width is fixed in the mobile phone page, and the high will change with the content of the page, this technique utilizes the value of the element padding percent is actually based on the width of its parent container, and the high value is cleverly transformed into the wide correlation.

When it comes to someone who may finally be tempted to ask, what is the relationship between this and the waterfall flow? Simple is a sentence, we want to discard the IMG tag, and use the way the background map. In order to use the background image, you have to keep the proportions of the elements always consistent with the picture.

In this way, you can not judge the picture is loaded, directly produce some of the same proportion of the picture Div, and then set the background map, as follows:

Here for example, the outermost box width of 220px, the inside of the IMG element width can be 100%, height can be squeezed through the padding.

Lazy load

There is also the advantage of using a background image that is easy to implement lazy loading. So what is lazy loading? That is, when the elements in our vision to show the picture, scrolling at the bottom of the screen pictures do not show, which can be a good increase in the speed of loading to enhance the experience.

First we add a Box-item class name to the outermost box (useful later), not setting the picture URL to the BackgroundImage property, but assigning a custom attribute:data-src.

<div class= "box Box-item" >
 <div class= "img" data-src= "/resource/images/1.jpg" ></div>
 <div class= "desc" >Description</div>
</div>

Next we write lazy load functions:

function Lazyload () {
var Boxarr = $ ('. Box-item ');
Boxarr.each (function (index, item) {
var viewtop = $ (item). offset (). Top-$ (window). scrolltop (),
 imgobj = $ (ite m). Find ('. img ');

 if (Viewtop < $ (window). Height ()) && (($ (item). offset (). Top + $ (item). Outerheight (True)) > $ (window).  ScrollTop ())) {
 imgobj.css (' backgroundimage ', ' url (' +imgobj.attr (' data-src ') + ') '). Removeclass (' data-src ');
 $ (item). Removeclass (' Box-item ');
 }
 )
}  

First we get all the elements that have the. Box-item class name, traversal. Viewtop is the relative height of the picture relative to the browser window, similar to the position:fixed feeling.

Judging by the condition, the DATA-SRC value of the background diagram element needs to be displayed and deleted if the picture is not in the browser window (above or below).

Then the outermost element of the Box-item Delete, because the picture has been shown do not need to make these judgments, delete the name of the class once scrolling will not get to have shown the elements, need to traverse the number of times will be less and more, so that can play an optimization role.

The function needs to be called when your element is already append into the page, and when scrolling is called:

Lazyload ();
$ (window). Scroll (lazyload);

Scrolling load

Said lazy load, say again rolling load. The so-called rolling load is to load a new picture when the page scrolls near the bottom. I've chosen to load new data when I scroll to the bottom of the smallest column, and you can also make judgments based on your preferences.

function Scrollload () {
var viewheight = $ (window). scrolltop () + $ (window). Height (),
 minheight = Math.min.apply  (null, Columnheightarr);

if (viewheight >= minheight) {
 //loadmore ...
}
}

The scrolling load is also monitored in window scrolling events and can be performed with lazy loading:

$ (window). Scroll (function () {
 scrollload ();
 Lazyload (); 
});

Speaking of PC end, let's talk about the end of the mobile phone . In fact, the principle is the same, but from multiple columns into a fixed two columns.

var Boxarr = $ ('. Box '),
 columnheightarr = [];
Columnheightarr.length = 2;

Boxarr.each (function (index, item) {
if (Index < 2) {
Columnheightarr[index] = $ (item). Outerheight (True); c6/>} else {
var minheight = Math.min.apply (null, Columnheightarr),
 minheightindex = $.inarray (MinHeight, CO    Lumnheightarr);

$ (item). css ({
 position: ' absolute ',
 top:minheight,
 left:boxArr.eq (minheightindex). Position ().    Left
 });

Columnheightarr[minheightindex] + = $ (item). Outerheight (true);
}
});

The difference is that the outermost box container width and margin should be set to a percentage in order to accommodate different screen phones.

Finally, there is a point to note , because we do not like Baidu with a list of boxes to install, but with the positioning of the way. The problem is that the image element's parent is not adaptive to the height, and if you have the relevant requirements we can calculate the longest length in all the columns and assign this value to the parent container's Min-height property:

$ (' body '). CSS (' MinHeight ', Math.max.apply (null, Columnheightarr));

Complete the entire code, waterfall flow of the full service is here.

var Dataarr = [{picurl: './resource/images/1.jpg ', width:522,height:783}, {picurl: './resource/images/2.jpg ', Width : 550,height:786}, {picurl: './resource/images/3.jpg ', width:535,height:800}, {picurl: './resource/images/4.jpg ',

 width:578,height:504}, {picurl: './resource/images/5.jpg ', width:1440,height:900}]; $.each (Dataarr, function (index, item) {$ ("body"). Append (' <div class= ' box Box-item ' > ' + ' <div class= ' img ' styl E= "Height:0;padding-bottom: ' +crate (item) * +"% "+ '" data-src= "' +item.picurl+ '" ></div> ' + ' <div class= "
 Desc ">Description</div> ' + ' </div>");

 }); var Boxarr = $ ('. Box '), num = Math.floor (document.body.clientwidth/boxarr.eq (0). Outerwidth (True)), Columnheightarr = [
 ];
 
 Columnheightarr.length = num;

  Arrangement ();

 $ (' body '). CSS (' MinHeight ', Math.max.apply (null, Columnheightarr));

 Lazyload (); function arrangement () {Boxarr.each (function (index, item) {If index < num) {Columnheightarr[index] = $ (item). Out ErHeight (TRUE); 
 else {var minheight = Math.min.apply (null, Columnheightarr), Minheightindex = $.inarray (MinHeight, Columnheightarr);
 $ (item). CSS ({position: ' absolute ', Top:minheight, Left:boxArr.eq (minheightindex). Position (). left});
 Columnheightarr[minheightindex] + = $ (item). Outerheight (True);
 }
 });
 function Lazyload () {var Boxarr = $ ('. Box-item '); Boxarr.each (function (index, item) {var Viewtop = $ (item). offset (). Top-$ (window). scrolltop (), Imgobj = $ (item). Find ('.
 IMG '); if (Viewtop < $ (window). Height ()) && ($ (item). offset (). Top + $ (item). Outerheight (True) > $ (window).
 ScrollTop ())) {//Console.log ($ (item). attr (' data-src '));
 Imgobj.css (' backgroundimage ', ' url (' +imgobj.attr (' data-src ') + ') '. Removeclass (' data-src ');
 $ (item). Removeclass (' Box-item ');
 }})} function crate (obj) {return obj.height/obj.width; function Scrollload () {var viewheight = $ (window). scrolltop () + $ (window). Height (), minheight = Math.min.apply (null , colUmnheightarr);
 if (viewheight >= minheight) {//loadmore ...}
 } $ (window). Scroll (function () {lazyload ();
 Scrollload ();
 });

Above is for you to share on the jquery waterfall flow layout, the content is very rich, we need a little understanding of digestion, really do the practical work, hope to be able to help everyone.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.