1

I have a website that uses a JavaScript/jQuery script to get the width of a div based on the screen size.

When I pull the website up in Firefox the div does not appear because the width is being set to 0px. The div appears fine in Chrome and IE, so I checked to make sure JavaScript was enabled in Firefox and it is.

Any ideas on a solution?

The script I'm using is:

$(document).ready(function () {
  var w = $('#content').css("margin-left");
  $('#wrapper').css("width", w);
});

If you open this JSfiddle in Firefox and inspect the sidebar wrapper div, you'll see the width is being set to 0, where in Chrome it has a value.

Casey
  • 536
  • 2
  • 14
  • 28
  • 1
    Can you create this issue in jsbin.com or similar service? There isn't enough information here for this to be answered. – m59 Sep 07 '14 at 04:45
  • 1
    a copy of your code in jsfiddle would be nice – Bob Tate Sep 07 '14 at 05:31
  • Yes, jsBin or JSFiddle. What I can see is happening from your code so far is you are assigning the value of `margin-left` from your `#content` element to the width of `#wrapper`. If wrapper is `0`, that means in FireFox, `margin-left` for `#content` is also set to `0`. If `margin-left` is `0`, then your width will also be `0`. – Samuel MacLachlan Sep 08 '14 at 01:08
  • In my CSS the #content margin-left is set to auto, however when I view the computed value it says its value is 0, when its clearly not. – Casey Sep 09 '14 at 15:58

3 Answers3

1

The reason for your problem is a strange behaviour of Firefox and Safari, thats clearly against the W3C specification of getComputedStyle() and should be reported as a bug.

You have set the margin of your #content to: 0px auto. Thats a common way to center a blocklevel element with given width in its containing block. Browsers take the width of the parent, subtract the width of the the element and divide by two. The resulting value is is used for marginLeft and marginRight and should be returned as computedValue for both properties. After calculation the element gets rendered (correctly centered). But Firefox and Safari see the keyword auto and set computedStyle to 0px (the default value for auto) before doing calculation and rendering.

Don't believe you can always rely on the values other browsers return. At that moment the parent or grandparent itself have some margin or padding or the boxSizing property is changed somewhere, they get confused and return wrong values even when the rendering is correct.

If you try to detect such cases by looking for the (shorthand) property margin, you'll fail again: Firefox, InternetExplorer and Safari answere with silence (empty string). Chrome and Opera return the margin shorthand, but the values there are often different from what you get with marginLeft and marginRight.

A workaround for marginLeft uses the difference between the left offset of the element and its parent (or its offset-parent, when element has position: 'absolute'). Refering to your code it looks like:

$(document).ready(function () {
    var con = $("#content"), cpos = con.css('position'), par, w;
    if (cpos === 'static' || cpos === 'relative') par = con.parent();
    else par = con.offsetParent();
    w = con.offset().left - par.offset().left;
    $("#wrapper").css('width', w);
});

I can not guarantee that it works in all usecases, but I havn't found problems until now. Working JSFiddle here. Now even Firefox and safari gets a width for the sidebar. Second JSFiddle. Here you can toggle between using marginLeft and offsetLeft for a quick browser test.

Since there is no offset right, the workaround for marginRight needs some more calculations.If you need it, post a comment and I will extend my answer.

Martin Ernst
  • 3,199
  • 1
  • 12
  • 12
  • Thanks for the thorough answer Martin. I tried the script you provided and it made my div disappear for the same reason as above, the width is 0. I'm not as familiar with some of the javascript you used, however I will try and find a solution off it. – Casey Sep 11 '14 at 16:01
  • I made a [Fiddle](http://jsfiddle.net/6y6esp8h/48/) with my code, and both FireFox (32) and Safari now show your sidebar. Please try. – Martin Ernst Sep 11 '14 at 16:46
  • @Casey I have updated my answer with two JSFiddles. Please try and post the behaviour of your browsers. – Martin Ernst Sep 12 '14 at 10:01
  • DOH! Ok it did work. When I copied your script to test it I forgot to add the script tag before and after. I tried it with the tags and it looks great! Thanks Martin! – Casey Sep 12 '14 at 18:55
0

Seems like everything is working on jsFiddle.

http://jsfiddle.net/wnxLr9bo/

<div id="wrapper">width of: </div>
<div id="content">the margin of: </div>

    $().ready(function() {
      var w = $('#content').css("margin-left");
      $('#content').append($('#content').css("margin-left"));
      $('#wrapper').css("width", w);
      $('#wrapper').append(w);
    });

#content {
    margin-left: 100px;
}

#wrapper {
    width: 0px;
}
HelpNeeder
  • 6,383
  • 24
  • 91
  • 155
0

So here's what I found on another thread...I guess Firefox isn't going to let it happen.

Unfortunately, this comes down to browser differences. To quote an answer to a similar problem:

As to why Chrome and IE return different values: .css() provides a unified gateway to the browsers' computed style functions, but it doesn't unify the way the browsers actually compute the style. It's not uncommon for browsers to decide such edge cases differently.

So you're kinda screwed. You have a few options to make this consistent.

You can reliably return auto by hiding the element before you compute the style. Something like this might work:

var $bar = $('.bar');
$bar.hide();
var barMarginRight = $('.bar').margin().right; // "auto"
// do whatever you need to do with this value
$bar.show();

You can also use jQuery's $('.bar').offset(), which returns properties you might be able to use.

// This might not be exactly what you want, but...
$('.spec').css('margin-left', $('.bar').offset().left + 'px');

You can also try to fix the problem with CSS, though we'd need to see your whole page to decide about that.

Community
  • 1
  • 1
Casey
  • 536
  • 2
  • 14
  • 28