• 0

[JS] Center a menu that is floated left.


Question

I found the following snippet of javascript (uses jQuery) that would allow me to centre a menu/nav that is set to float:left. It seems to work in IE and Opera OK. But in FF and Safari, it works sometimes and other times trips out (keep refreshing the page and it will eventually work/fail). In Chrome it doesn't work at all.

Here is the code:

$(function() {
	var menu_width = $('#nav').css('float', 'left').width();
	$('#nav').css({float : 'none', width : menu_width, margin : '0 auto'});
});

I don't know js so I can't figure out what the problem is. If anyone can help it would be much appreciated.

Here is the page running the code:

http://www.islandrobot.com/vanessa/

Cheers,

Jordan

15 answers to this question

Recommended Posts

  • 0

Sorry, yes I am trying to centre the entire navigation on that blue strip. Without the js it would be aligned to the left. With the js it should be centred.

P.s. I made an edit to my above post and then deleted it. If you saw the edit, just ignore it ;)

  • 0

That would be the easy way out, yes. But I would rather have it centre automatically since the client may add/remove/rename items from the menu at any time which would mean manually recalculating and changing the width. Since they don't know CSS I wouldn't expect them to have to do that.

  • 0

It wasn't the easy way out when I looked over your code but rather the logical solution to your problem based only on your initial post (which didn't say that the menu would actually be dynamic versus static.)

That being said the best bet is to replace float: left for display:inline. Then you can have all list items centered under the unordered list without needing any javascript.

  • 0

That being said the best bet is to replace float: left for display:inline. Then you can have all list items centered under the unordered list without needing any javascript.

I tried this method at first but encountered problems with the drop down menus. I couldn't get them to fall directly under their parent li. Instead, the drop-downs always appeared in the far left corner (beginning of the root ul) regardless of which li you were mousing over (if that makes any sense). I played around with it for a while but couldn't get it to behave the way I wanted.

I also tried using inline-blocks which worked nicely except in FF2 which doesn't support it. -moz-inline-box didn't help either because of the drop-down menus.

JS seems like my last and only resort to have a centred, horizontal menu of unknown width and with drop down menus.

  • 0

Hi sweetsam. That seems to have helped a little bit. It at least works in Chrome now sometimes where as it didn't work at all before. However, it is still failing on some page loads. If you keep refreshing the page in FF/Chrome/Safari (Opera and IE seem stable) it will eventually get screwed up. Is this a common problem with javascript? Could it be a jQuery issue?

  • 0

An update:

I've almost got it pegged now. Previously I did not have float:left; applied to #nav (which is the ul). I only had it applied to the li's. As I understood it, the .css('float', 'left') part of the script was trying to add the float to #nav for me??? Well I took that part out and just added float:left; to #nav in the css. This made #nav wrap snug around the li's and allowed for the correct width to be determined. Now everything seems stable in FF.

EDIT: FF is still giving the same problem as Chrome and Safari

Chrome and Safari still seem to be having slight problems getting it perfectly centred though. Sometimes its a bit more to the left and other times it's perfect.

I have also simplified the script down to this:

$(function() {
        var mleft = Math.round(($('#nav-wrap').width() - $('#nav').width()) * 0.5);
        $('#nav').css('margin-left', mleft);
});

  • 0

Ok I am pretty sure now that the problem is a simple matter of the calculations being made before the navigation part of the page has been drawn up (if that makes sense). I realize this as some testing showed that occasionally $('#nav-wrap').width() and $('#nav').width() were returning results like 1407 and 1367 respectively. This would also explain why the browsers with faster javascript engines are having the problem more frequently. How can I make sure that the calculations are only made AFTER the html/css has been drawn up by the browser?

Sorry for all these posts, as I said in the beginning I don't know much about js so figuring this out is a whole learning experience :/

EDIT: HOT DAMN.... I guess it was as simple as moving my stylesheet above the javascript. All good now :)

  • 0

To avoid this kind of problem though you should have done this :


$(document).ready(function() {
$(function() {
 var mleft = Math.round(($('#nav-wrap').width() - $('#nav').width()) * 0.5);
 $('#nav').css('margin-left', mleft);
});});

It ensures any jquery is applied after the dom has been fully parsed, most of the time the effect is instant.

  • 0

I was actually reading up on the .ready() function when I discovered that I could just move the css above the js.

To quote the .ready() page of the jQuery site that tipped me off:

When using scripts that rely on the value of CSS style properties, it's important to reference external stylesheets or embed style elements before referencing the scripts.

Is it still advisable that I also use the .ready any ways?

  • 0

Yes. But you were using it already. Following pieces of code are equivalent. The problem was being caused by the fact that the styles were being applied after the script swung in to action. Scripts should always be the last to run and more importantly should be included after the stylesheets. Sometimes you will see scripts attached to the end of the document for the same reason.


$(function(){

})

and

$(document).ready(function(){

})

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • Dead by Daylight, Two Point Museum, and more join Xbox Free Play Days for the weekend by Pulasthi Ariyasinghe There is a brand-new Free Play Days offer available to Xbox players, giving them a chance to try out a new selection of games over the weekend. Microsoft's latest promotion brings some high-profile titles, including the sports title PGA TOUR 2K25 and the racing sim Assetto Corsa. Almost all the games being offered this time require an Xbox Game Pass subscription, with only one title being available for all players. Starting with the fully free-to-play section, Dead by Daylight is populating it solo. This asymmetric survival horror title should be the most familiar to most gamers, considering its age. The multiplayer four-versus-one asymmetric survival horror game has you assuming the roles of survivors or the killer to see who can come out on top. This Dead by Daylight offer will be available to play until Monday, June 22, giving you an extra day of play compared to the remainder of the Free Play Days titles. Meanwhile, Xbox Game Pass Ultimate, Premium, and Essential members can now try out the well-received tycoon game Two Point Museum, the circuit racing sim Assetto Corsa, as well as 2K's golf sim experience that gives players a career to develop alongside real-world pros and courses. Here are the announced games and the platforms they are available to play on: PGA TOUR 2K25 (Xbox Series X|S) Two Point Museum (Xbox Series X|S) Assetto Corsa (Xbox Series X|S, Xbox One) Dead by Daylight (Xbox Series X|S, Xbox One) To easily find the titles on Xbox consoles, first head to the Store, and then in the sidebar, find the Home section. In there, open the Subscriptions tab. All the games from the Free Play Days collection will show up in this section for quick access. Apart from Dead by Daylight's offer, this week's Free Play Days promotions will end on Sunday, June 21, at 11:59 pm PT.
  • Recent Achievements

    • Week One Done
      Huge Trailer earned a badge
      Week One Done
    • Week One Done
      Classifyskilleducation earned a badge
      Week One Done
    • One Month Later
      eurospharma62 earned a badge
      One Month Later
    • Week One Done
      With What earned a badge
      Week One Done
    • Week One Done
      Harris Gilbert earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      590
    2. 2
      +Edouard
      170
    3. 3
      PsYcHoKiLLa
      74
    4. 4
      Michael Scrip
      65
    5. 5
      neufuse
      64
  • Tell a friend

    Love Neowin? Tell a friend!