different result of width() and height() since jQuery 3.0

Just to provide feedback:
#2439 has not only the impact returning non-integer values.

I have a CSS transform:scale(2) in a root element with a div which has css width 200px.
jQuery 2.x returns 200 for .width() as it uses offsetWidth
jQuery 3.0 returns 400 for .width() as it uses getBoundingClientRect()

This is a breaking change which should be at least mentioned in the upgrade guide.

Author: Fantashit

3 thoughts on “different result of width() and height() since jQuery 3.0

  1. The change is still not in the upgrade guide. IMO this should be done as fast as possible to prevent upgraders to have the same problems as we had.

  2. Let’s start with a summary of documented surface area (using the horizontal dimension without loss of generality):

    • .css("width") returns the computed CSS “width” property, which will include or exclude padding and borders per the CSS “box-sizing” property.
    • .width() returns the computed content width, which may be less than .css("width") when “box-sizing” is “border-box” but should equal it when “box-sizing” is “content-box”.
    • .innerWidth() returns the computed padding box width (sum of .width() and computed left and right padding).
    • .outerWidth() returns the computed border box width (sum of .innerWidth() and computed left and right borders), which should equal .css("width") when “box-sizing” is “border-box”.
    • .outerWidth(true) returns the computed margin box width (sum of .outerWidth() and computed left and right margins).

    All of these should be capable of returning fractional values, but—since they are so closely tied to the CSS box model and especially since they’re all also setters—ignore transforms. In fact, the non-css methods are probably the most convenient means of getting untransformed dimensions, although if we were starting from scratch we might want to condense them together and would definitely be more consistent with naming.

    For this ticket, though, I have to agree with @HolgerJeromin. We should not use getBoundingClientRect values in any of the above calls.

  3. What can we do before 4.0? I’d consider some of this to be regressions so even if it changes existing behavior for better compatibility with 2.x it still may be in play for a 3.x.0 release.

    • Remove getBoundingClientRect() from getWidthOrHeight so .css("width") once again accurately provides CSS “width”.
    • Rename and refactor the .width/.height/.inner*/.outer* surface area to clarify that they get/set CSS content/padding/border/margin box dimensions (and therefore ignore transforms). Reimplement the existing methods as thin wrappers.
    • Separately, address .offset and .position:
      • Complete and land gh-3096 or a derivative
      • Refactor to avoid dependence upon CSS width/height hooks, allowing the hooks to be removed
      • Document that .offset( setterArg ) is not reliable for elements with transformed ancestors
      • Document that .position() is not reliable for elements with transformed ancestors

Comments are closed.