Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expanding Vertical Space Issue with Floated Elements

I have a layout that requires a list of items to be organized into two vertical columns. The items are in a single list of <div>s, with the markup also being re-purposed for mobile, so I don't want to modify the structure.

The problem I have here is that each item has an expanding content area which the user can toggle, and when this content is expanded the vertical space for that column needs to expand downward with the other column staying fixed.

Right now I have a basic solution with floated items, but when I expand the content areas the vertical space expands in both columns instead of just the one.

Here's a link to an example of the functionality as I have it now, and below is a screenshot of what the desired behavior should be.

[screenshot]

Is it possible to style this to support the required behavior? Or am I going to have to modify the structure of items in order to get this to work? Thanks in advance for your help!

like image 960
ataddeini Avatar asked Nov 11 '11 17:11

ataddeini


People also ask

What happens if you use a float property on an absolutely positioned element?

Absolutely positioned page elements will not affect the position of other elements and other elements will not affect them, whether they touch each other or not. There are four valid values for the float property. Left and Right float elements those directions respectively.

What usually happens to the parent container of floated elements?

4. What happens to a parent of a "Float"? Parents don't care much about their "Float" children, except that they shouldn't go out of their left or right boundaries. Typically a block element of unspecified height increases its height to accommodate its child elements, but that isn't the case for "Float" children.

Which property is used to prevent an element's content from floating around a floated element?

The float property specifies whether an element should float to the left, right, or not at all. Note: Absolutely positioned elements ignore the float property! Note: Elements next to a floating element will flow around it.

How do you clear a floated element?

Clearing Floats The footer should sit below both the sidebar and main content. To clear a float, add the clear property to the element that needs to clear the float. This is usually the element after the floated element. The clear property can take the values of left , right , and both .


1 Answers

Your premise is flawed. Document structure flows left-to-right, top-to-bottom. You will need to make some change to the structure... Easiest would be adding two containers for a left column and a right column. Otherwise, you're in for some tricky absolute positioning markup, and a little funky jquery, which I can only suggest with the addition of some unique IDs for each of the panels.

I would, personally, add ids such as panel1 through panel4 per your example, then use this javascript (or similar) as a jumping off point:

for(var i=1; i<=4; i++) {
        $('#panel'+i).css('left', function(index) {
           if(i%2 == 0) return "120px";
           else return "0px"; 
        });
}

$('.more').click(function(e) {
    e.preventDefault();
    $(this).parent().children('p').toggle();
    var id = $(this).parent().attr("id");
    switch( id ) {
        case 'panel1':
          console.log("panel1 found");
          $('#panel3').css('top', function(index) {
            var buffer = $('#'+id).height() + 20 + "px";
            return buffer;
          });
          break;
        case 'panel2':
          $('#panel4').css('top', function(index) {
            var buffer = $('#'+id).height() + 20 + "px";
            return buffer;
          });
          break;
        default: break;
    }
});

With the default values in the css for those panels:

#panel1 { top:0px; }
#panel2 { top:0px; }
#panel3 { top:56px; }
#panel4 { top:56px; }

The less you tweak the html, the more work you'll create in javascript.

edit:

Proposed alternate Javascript to remove need to alter HTML, assuming two elements per row. Since we know the row to be the problem...

var ct = 1
$('#container > div').each(function(index, domEle) {
  $(domEle).attr('id', 'panel'+ct);
  $('#panel'+ct).css({
     'position': 'absolute',
     'left' : function(index, value) {
        if(ct%2 == 0) return "120px";
        else return "0px"; 
     },
     'top' : function(index, value) {
        return (56 * Math.floor(ct/3)) + "px";
     }
  });
  ct++;
});

$('.more').click(function(e) {
    e.preventDefault();
    $(this).parent().children('p').toggle();
    var id = $(this).parent().attr("id");

    switch( id ) {
        case 'panel1':
          $('#panel3').css('top', function(index) {
            var buffer = $('#'+id).height() + 20 + "px";
            return buffer;
          });
          break;
        case 'panel2':
          $('#panel4').css('top', function(index) {
            var buffer = $('#'+id).height() + 20 + "px";
            return buffer;
          });
          break;
        default: break;
    }
});

Now no changes need be made to the HTML, though you'll want to redo the click function to handle repositioning of elements after a click. I would make life easy and hide all .more items before expanding a new box, since it would mean having to calculate the heights of all elements above, but how much work you want to make is your business.

like image 57
stslavik Avatar answered Oct 20 '22 17:10

stslavik