Dynamic grids spanning multiple rows + columns

It can be difficult to explain without seeing the result, so please check out these examples:

JSFiddle Example 1 - looks good
JSFiddle Example 2 - Broken

Code from scripts:

HTML:

<ul id="homepage-grid"> <li id="tile11" class="col1 row1 sizex1 sizey1"> <a href="#" title="test"> <img src="http://placehold.it/295x160" alt="test" title="test" style="width: 295px;height: 160px" /> </a> </li> <li id="tile8" class="col2 row1 sizex2 sizey1 last"> <a href="#" title="test"> <img src="http://placehold.it/602x160" alt="test" title="test" style="width: 602px;height: 160px" /> </a> </li> <li id="tile1" class="col1 row2 sizex1 sizey1"> <a href="#" title="testing"> <img src="http://placehold.it/295x160" alt="testing" title="testing" style="width: 295px;height: 160px" /> </a> </li> <li id="tile4" class="col2 row2 sizex2 sizey1 last"> <a href="#" title="test3"> <img src="http://placehold.it/602x160" alt="test3" title="test3" style="width: 602px;height: 160px" /> </a> </li> <li id="tile10" class="col1 row3 sizex1 sizey2"> <a href="#" title="test"> <img src="http://placehold.it/295x332" alt="test" title="test" style="width: 295px;height: 332px" /> </a> </li> <li id="tile12" class="col2 row3 sizex1 sizey2"> <a href="#" title="test"> <img src="http://placehold.it/295x332" alt="test" title="test" style="width: 295px;height: 332px" /> </a> </li> <li id="tile2" class="col3 row3 sizex1 sizey1 last"> <a href="#" title="testing2"> <img src="http://placehold.it/295x160" alt="testing2" title="testing2" style="width: 295px;height: 160px" /> </a> </li> <li id="tile9" class="col3 row4 sizex1 sizey1 last"> <a href="#" title="test"> <img src="http://placehold.it/295x160" alt="test" title="test" style="width: 295px;height: 160px" /> </a> </li> </ul> 

CSS

 #homepage-grid { width:910px; position:relative; padding:0; overflow: hidden; } #homepage-grid li { list-style:none; float:left; padding:0 12px 12px 0; display:block; } #homepage-grid li.last { list-style:none; float:left; padding:0 0 12px 0; } #homepage-grid li a { display:block; } 

Basically, I want to create a dynamic grid that is populated with a database (currently, part of the database is working fine). In a grid, each tile can span up to 3 columns wide, however, it can span unlimited lines, which seems to be where I run into problems.

I'm having problems with HTML / CSS for something so dynamic. As you can see, one small change from example 1 to example 2, and it broke most of the grid, since the bottom left tile should be pushed up to fill the gap, and the right tile should be moved up to fill this space.

However, I have full control over the code, so HTML / CSS can change as needed (for example, add classes / inline styles / etc).

I think this might (relatively easily) work with tables, but since this is not table content, I really don't want to go that route.

Will there be a way to make CSS so dynamic? Should I use more inline styles to achieve this?
Should I do it differently, for example, Absolute positioning instead of swimming?

Any help on how to achieve this would be greatly appreciated.

+6
source share
5 answers

You will encounter this problem with floats. However, you can change the location of one element on this page, and everything will fall as you expect.

Updated script

Add the following to your CSS:

 #homepage-grid li#tile10 { position: absolute; top: 342px; } 

This violates the violating element from the document flow, thereby eliminating the vertical space reservation that is assigned to it by the "float" applied to the rest of the list items. The last element floats to the right, so it will not overlap an absolutely positioned tile.

EDIT

In the comments below, here is a slightly more flexible way to do this . An example works for published code.

Assumptions made with the updated fiddle:

  • sizex1, sizey1, sizex2 etc. are constant values
  • That the content to the right of them will be placed to the right (this will work in the reverse order for the left movable elements, but these scripts look as if they would not be a problem, since the elements on the right will float correctly if the elements on the left are larger vertically)
  • The user has the ability to redefine styles or apply styles when creating a layout. This is primarily for controlling position: absolute from unnecessarily applying to certain elements.

What does it do:

This CSS sets up different rules based on the existence of siblings with specific classes. Therefore, the constancy of the values ​​of sizex1 sizex2 sizey1 and sizey2 .

CSS:

 #homepage-grid li.col1:not(.row1):not(.row2) { position: absolute; } #homepage-grid li.col1.sizey1.row1 ~ li.col1.row2 { /* The first column of the first row has a sizey of 1 */ top: 172px; } #homepage-grid li.col1.sizey2.row1 ~ li.col1.row2{ /* The first column of the first row has a sizey of 2 */ top: 342px; } #homepage-grid li.col1.sizey1.row1 ~ li.col1.sizey1.row2 ~ li.col1.row3 { /* The first column of the first row has a sizey of 1 and the first column of the first row has a sizey of 1 */ top: 344px; } #homepage-grid li.col1.sizey2.row1 ~ li.col1.sizey2.row2 ~ li.col1.row3{ /* The first column of the first row has a sizey of 2 and the first column of the second row has a sizey of 2 */ top: 684px; } #homepage-grid li.col1.sizey2.row1 ~ li.col1.sizey1.row2 ~ li.col1.row3, #homepage-grid li.col1.sizey1.row1 ~ li.col1.sizey2.row2 ~ li.col1.row3 { /* The first column of the first row has a sizey of 2 and the first column of the second row has a sizey of 1, or vice versa */ top: 514px; } 

Ideally, you want to set #homepage_grid li.col1 to the delivery of the page. This way, you can choose which tiles are broken from the document stream to maintain the correct spacing. I usually do this with the :not() selector, but if you're looking for older browser compatibility, you can just as easily use overriding.

Example:

 #homepage-grid li.col1:not(.row1):not(.row2) { position: absolute; } 

* The above will result in line breaks of 3 or more from the document stream.

 #homepage-grid li.col1 { position: absolute; } #homepage-grid li.col1.row1, #homepage-grid li.col1.row2 { position: static; } 

This does the same as above, but in more detail. However, it will display accordingly in less standardized browsers.

EDIT 2 For simplicity, here is an example of using jQuery to set the corresponding elements as static when the page loads.

Another example of a violin

+1
source

My first thought was to set the height from #title12 to 160px , but that would not work if the element below it is the same width .

Instead, you can try the following:

Assuming each "row" of your grid has a fixed height, wrap it with <div>...</div> or a similar block element with height:160px; (or any other size), but make it the same for each div "row").

Fill the first line with the first line of images. For the second (and subsequent) lines, determine if each β€œcell” overlaps next to it. If so, add a β€œfiller” block consisting of an empty block element with height and width equal to the required row and column sizes.

This allows the <li>...</li> elements to overflow the div "line into one line (below) (since the overflow is set to visible by default). Empty block elements do not allow the next line to overlap the overflow from the previous one.

The disadvantages of this approach include:

  • This makes your HTML a little ugly.
  • Perhaps this is too much like a table to use instead of a real table.
  • This will require additional work on the server side.

EDIT: Also, <div> not allowed in the list, so you will need to start / stop the list on each line. Alternatively, perhaps use <ul> </ul> as strings instead of <div> .

+2
source

Well, that's just a thought. Suppose you have a maximum of 3 columns and a fixed row height, you can massage to store the number of outgoing rows per column, and then add a negative margin-top or class to pull up a certain number of rows. eg:.

At the beginning of the row pool, on the column [0][0][0] after adding a 2-row element, it will look like [2][0][0] , adding two more elements with heights of 3 and 2 rows, we will have [2][3][2] next element to be placed should be placed in the first short column and stretched by the difference of the largest minus the shortest, in this example one column (3 - 2), if the added element has 2 rows in height, pool will be [5][3][2] , the next element will be placed in the rightmost column and will be lifted up by 3 lines (5 - 2).

It's all! At first glance, it looks like it will work, but I have not tested it enough.

+1
source

You need a grid system that allows nesting.

Then do a search in your grid layout for complete rows.

Then do a search in each row for full columns, etc.

0
source

I would recommend using a JavaScript plugin like Masonry .

-1
source

All Articles