2

I have a website template where I do not know the number of menu items or the size of the menu items that will be required. The js below works exactly the way I want it to, however this is the most js I've every written. Are there any disadvantages or potential problems with this method that I'm not aware of because I'm a js beginner? I'm currently manually setting the padding for each site. Thank you!

var width_of_text = 0; 
var number_of_li = 0;

// measure the width of each <li> and add it to the total with, increment li counter
$('li').each(function() {
    width_of_text += $(this).width();
    number_of_li++;
});

// calculate the space between <li>'s so the space is equal
var padding = Math.floor((900 - width_of_text)/(number_of_li - 1));

// add the padding the all but the first <li>
$('li').each(function(index) {
    if (index !== 0)
    {
        $(this).css("padding-left", padding);
    }
});
  • 1
    Why can't you do it with `css` only? – gdoron Jun 02 '12 at 22:20
  • I can, but I have to adjust it for every site depending on the width and number of menu items. I could also do it with a table, but ideally I want the space between elements to be the same, not the total space allotted for each element + padding. That also breaks if there is a long menu item. –  Jun 02 '12 at 22:22
  • Why can't you position li's in the centre of the parent element and create margin between them? Is this what you're trying to do? – Zefiryn Jun 02 '12 at 22:32
  • What generates the template? Can't you generate the widths with it? – Eric Jun 02 '12 at 22:36
  • @Zefiryn - yes, that is what I'm trying to do, however, i just wanted it to distribute automatically. –  Jun 02 '12 at 22:36
  • You can set display: table on ul element and display: table-cell on li's. In theory (I didn't check this) this should make each li even, assuming there is no width style set up in css. – Zefiryn Jun 02 '12 at 22:39
  • @Eric - yes, i didn't even think of that. (im a designer) Someone else posted an answer about doing it on the server side and I think that will work fine, and work in the few cases where js is not enabled. –  Jun 02 '12 at 22:40
  • @Ryan: See my answer for a pure CSS solution – Eric Jun 02 '12 at 22:41

6 Answers6

2

You can do this hackily in CSS, using display: inline-block, and text-align: justify

<ul>
    <li>thing</li>
    <li>thing2</li>
    <li>thing3</li>
    <li>thing4</li>
    <li class="hack"></li>
</ul>

And then:

ul { text-align: justify }
li { display: inline-block }
li.hack { width: 100% } /* force the justified text to wrap */

Demo

Eric
  • 95,302
  • 53
  • 242
  • 374
  • Thanks, I've seen this method before, and I may use it. I gave the answer to Michael because my question was really about if js was appropriate for this application. –  Jun 02 '12 at 22:51
1

Yes, there are disadvantages of using JS for formatting.

It is strongly recommended to avoid using JS for formatting and positioning, use CSS whenever possible.

Javascript is interpreted and run very differently from browser to browser, from OS to OS, from OS/browser version to version.

CSS rendering is a native browser engine function and its rendering priority is higher than that of JS.

CSS rendering is much more speedy than JS.

Etc.

What you are doing now I would never suggest doing. IMHO, this is a very wrong approach. JS is absolutely definetely misused in this case. You have to use CSS for this task, and I would suggest posting a question about how to use CSS correctly for this task.

Michael Zelensky
  • 2,012
  • 3
  • 29
  • 37
  • 1
    A lot of that simply isn't true. There are cross-browser differences with both javascript and CSS, and the differences can be overcome in both cases. CSS does not have higher priority - whichever is loaded first will execute first. However, I agree that CSS will generally be more efficient, and that one should not use javascript for formatting if at all possible. – st-boost Jun 02 '12 at 22:48
0

I would suggest having a default spacing between them in a way that would not push them out of their container. The extra javascript to enable them to space equally should be an enhancement only.

monokh
  • 1,970
  • 3
  • 22
  • 31
0

I think the answer to your question is, if it works, then it works (and will continue to work), but that doesn't mean that this is the best way to handle it. If you *care about the best way, then investigate how to improve your approach using mostly (or even exclusively) CSS. If you're just looking to get the job done, and it's working, then you're good to go.

Yevgeny Simkin
  • 27,946
  • 39
  • 137
  • 236
0

Depending on your site visitors, there will be around 3% who visit you with JS disabled. And you want the site to work for them to. Maybe not the unnessecary parts of the site but you want the critical parts to work. Navigation is one of the most important parts of a website.

Make sure the navigation works without JS (doesn't have to be as fancy as with JS) and then you could make some improvements with JS.

Alfred Larsson
  • 1,339
  • 1
  • 9
  • 16
0

You don't need JavaScript as long as you can rely on a CSS algorithm that adapt width to its content: the table layout algorithm :)

See http://jsfiddle.net/r9yrM/1/ from my previous answer for examples.

Don't forget to have a minimum padding on each "cell", text stuck to a border isn't very readable (and ugly). You'll also probably want text-align: center on cells (last CSS rule).

With JS, you could decide of a maximum number of tabs (or a minimum "reasonable" width) and above (below) that number, add a class on the parent that will trigger each tab to render as float: left and block and not table-cell anymore. Then it'll occupy 2 or more lines (like the extension Tab Mix Plus on Firefox)

Note: there're at least 2 algorithms for table: with and without table-layout: fixed, depending on freedom left to the browser when adapting.

Note on your jQuery code above: "each li except the first" can be expressed by $('li + li') (the first one isn't preceded by a li)

Community
  • 1
  • 1
FelipeAls
  • 21,711
  • 8
  • 54
  • 74