Floated elements: Fill out the bottom line first

222 views Asked by At

One project I'm working on uses tabbed navigation. Because the number of tabs is dynamically calculated, and can reach high numbers, sometimes these tabs (which are, in essence, <li> elements with a float: left; style declaration) overflow into the next line, Using [###] to display a tab, the end result looks something like this:

[###] [###] [###] [###] [###] [###]
[###] [###]
[Rest of the content..............]

Because the last 4 elements on the top row do not have an element they 'connect to' , this just looks horrible.

Is it possible, with the help of Javascript (frameworks such as jQuery or MooTools acceptable, if they provide a shorter/easier solution) to fill out the bottom row first, and placing the remainder of the elements on top?

Like this:

[###] [###]
[###] [###] [###] [###] [###] [###]
[Rest of the content..............]

(Question tagged MooTools, since it's the JS framework we're currently using. An answer given in any other framework would be fine, since it could probably be translated into MT quickly)

4

There are 4 answers

0
Duroth On BEST ANSWER

Below is the code I've used to solve this matter. Basically, using JS, we calculate the width of the container, and together with the width of the tabs (all tabs have the same width) calculate the number of tabs per row, and the remainder. Using a simple modulo comparison, we can then insert a clear: both style (forcing the tab to move to an empty row).

var allTabs = $$('#tab-container li');
var tabNum = allTabs.length;
var tabWidth = allTabs[0].offsetWidth;
var oWidth = $('tab-container').offsetWidth;
var tabRowNum = Math.floor(oWidth/tabWidth);
var tabRowOffset = (tabNum % tabRowNum);

for(var i = 0; i < tabNum; i++) {
    if((i % tabRowNum) == tabRowOffset) {
        allTabs[i].setStyle('clear', 'both');
    }
    else {
        allTabs[i].setStyle('clear', 'none');
    }
}
0
n1313 On

I'm afraid that there is no simple solution to do exactly what you want. Floats are floats. Your best bet will be counting the dimensions and number of tabs on-the-fly with javascript, then positioning them manually with position:absolute. Not pretty.

But the problem of fitting lots of tabs into small space is solvable. The simplest method is to give the tabs in the second row an additional css class and use it to position them on top of the first row. This can be done on server side or on client side, with javascript. Or, if you know the exact number of tabs and exact width of their container, then you can set max-width for them and let them shrink a little. Or you can go with overflow: scroll for tabs container, but this will sure look ugly :)

0
raveren On

Easy with JS. Less-than-pseudo code:

  • Create a div (optionally)
  • Create an ul
  • fill it with lis until either the given max number is reached or their combined width is "just below" the needed width
  • add the div to your html document, saving a reference to id
  • repeat, but if you have a saved reference to a saved div, add the new one before that.
0
user280592 On

I would suggest keeping all the tabs on one line (make it as wide as required) and scrolling to the current tab. (You'll want a drop-down menu listing all of the available tabs as well, for navigation.)

The problem with what you're trying to do is that if you do get what you want, what happens when a tab in the top row is selected?

  • You have a selected tab that is not connected to the current panel (separated by the bottom row of tabs), which is ugly or
  • You move the top row of tabs to the bottom (adjacent to the panel) in which case you have the situation you're trying to avoid or
  • You re-organise the tabs to put the selected one on the bottom, which makes a mess of navigation (it is impossible for a user to learn where the tabs are).