Skandal: jQuery gibt relative Margin-Angaben beim iOS5 nicht als Pixelwerte zurück!

Kürzlich musste ich entdecken, dass die Abstände auf einer von mir erstellten iPad-App auf dem neuen iOS5 gegenüber iOS4 durcheinandergeraten sind. Dem wollte ich auf den Grund gehen, denn in der Regel zicken ja alte Browser und nicht neue.

Es stellte sich heraus, das der jQuery-Befehl outerWidth(true), der die Breite eines Elementes inkl. Aussenabstand ausgeben soll, auf iOS5 einen falschen Wert zurückgibt. Im Stylesheet sind die Breiten und Abstände in Prozentwerten definiert, doch jQuery sollte diese in Pixelwerte umrechnen. Dies tut es aber lediglich bei der Innenbreite, der Aussenabstand hingegen wird in Prozentangaben dazugerechnet, und so werden Äpfel und Birnen bzw. Pixelwerte und Prozentwerte ohne weiteres addiert, was zu skandalösen Resultaten führt.

Ein Beispiel

HTML: Ein Element in einem übergeordneten Element.

<div id="container">
    <div id="element"></div>
</div>

<div id="console"></div>

CSS: Übergeordnetes Element: 400px breit, inneres Element: 50% breit, 50% rechter Rand (sollte also je 200px ergeben)

#container {
    width: 400px;
    border: 1px solid black; padding: 2px;
}
#element {
    width: 50%;
    margin-right: 50%;
    height: 100px; background: green;
}

Javascript: Mit den erwarteten und unerwarteten Ergebnissen

var el = jQuery('#element');
var cons = document.getElementById('console');

// expected: 200, iOS5: 200 (correct)
cons.innerHTML  = 'el.width() = ' + el.width() + '<br />';

 // expected: 400, iOS5: 250 (px and % added)
cons.innerHTML += 'el.outerWidth(true) = ' + el.outerWidth(true) + '<br />';

// expected: 200px, iOS5: 200px (correct)
cons.innerHTML += 'el.css(width) = ' + el.css('width') + '<br />';   

// expected: 200px, iOS5: 50% (not incorrect, but not as expected)
cons.innerHTML += 'el.css(margin-right) = ' + el.css('margin-right') + '<br />';

Javascript-Workaround: Den Wert selber ausrechnen.

var value = el.css('margin-right');
if (value.substr(value.length - 1, 1) === '%') {
    var valPercentage = value.substr(0, value.length - 1);
    var valWidth = jQuery('#element').parent().width();
    value = (valWidth * valPercentage) / 100 + 'px';
}

// expected: 200px, iOS5: 200px
cons.innerHTML += 'corrected margin value = ' + value + '<br />';

Das ganze Beispiel kann hier eingesehen werden

Screenshot eines iPads mit iOS5: 200px + 50% = 250

EDIT, 17.01.2012: Der daraus entstandene jQuery-Bugreport wurde artig diskutiert, und auf einen Fehler bei Webkit abgeschoben.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.