Skip to content

Commit

Permalink
Dimensions: Detect and account for content-box dimension mishandling
Browse files Browse the repository at this point in the history
Fixes gh-3699
Closes gh-3700
  • Loading branch information
gibson042 authored Jul 10, 2017
1 parent a6a28d2 commit 3fcddd6
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 16 deletions.
22 changes: 17 additions & 5 deletions src/css.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,10 @@ function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computed
function getWidthOrHeight( elem, dimension, extra ) {

// Start with computed style
var valueIsBorderBox,
styles = getStyles( elem ),
var styles = getStyles( elem ),
val = curCSS( elem, dimension, styles ),
isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
valueIsBorderBox = isBorderBox;

// Computed unit is not pixels. Stop here and return.
if ( rnumnonpx.test( val ) ) {
Expand All @@ -160,7 +160,7 @@ function getWidthOrHeight( elem, dimension, extra ) {

// Check for style in case a browser which returns unreliable values
// for getComputedStyle silently falls back to the reliable elem.style
valueIsBorderBox = isBorderBox &&
valueIsBorderBox = valueIsBorderBox &&
( support.boxSizingReliable() || val === elem.style[ dimension ] );

// Fall back to offsetWidth/Height when value is "auto"
Expand Down Expand Up @@ -367,14 +367,26 @@ jQuery.each( [ "height", "width" ], function( i, dimension ) {
set: function( elem, value, extra ) {
var matches,
styles = getStyles( elem ),
isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
subtract = extra && boxModelAdjustment(
elem,
dimension,
extra,
jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
isBorderBox,
styles
);

// Account for unreliable border-box dimensions by comparing offset* to computed and
// faking a content-box to get border and padding (gh-3699)
if ( isBorderBox && !support.borderBoxReliable() ) {
subtract -= Math.ceil(
elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
parseFloat( styles[ dimension ] ) -
boxModelAdjustment( elem, dimension, "border", false, styles ) -
0.5
);
}

// Convert to pixels if value adjustment is needed
if ( subtract && ( matches = rcssNum.exec( value ) ) &&
( matches[ 3 ] || "px" ) !== "px" ) {
Expand Down
21 changes: 15 additions & 6 deletions src/css/support.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,16 @@ define( [

// Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
reliableMarginLeftVal = divStyle.marginLeft === "2px";
boxSizingReliableVal = divStyle.width === "4px";
boxSizingReliableVal = divStyle.width === "5px";

// Support: IE 9 only
// Detect misreporting of content dimensions for border-box elements (gh-3699)
borderBoxReliableVal = divStyle.width[ 0 ] === "5";

// Support: Android 4.0 - 4.3 only
// Some styles come back with percentage values, even though they shouldn't
div.style.marginRight = "50%";
pixelMarginRightVal = divStyle.marginRight === "4px";
pixelMarginRightVal = divStyle.marginRight === "5px";

documentElement.removeChild( container );

Expand All @@ -45,7 +49,8 @@ define( [
div = null;
}

var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,
var pixelPositionVal, boxSizingReliableVal, borderBoxReliableVal, pixelMarginRightVal,
reliableMarginLeftVal,
container = document.createElement( "div" ),
div = document.createElement( "div" );

Expand All @@ -60,19 +65,23 @@ define( [
div.cloneNode( true ).style.backgroundClip = "";
support.clearCloneStyle = div.style.backgroundClip === "content-box";

container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" +
container.style.cssText = "border:0;width:10px;height:0;top:0;left:-9999px;" +
"padding:0;margin-top:1px;position:absolute";
container.appendChild( div );

jQuery.extend( support, {
pixelPosition: function() {
borderBoxReliable: function() {
computeStyleTests();
return pixelPositionVal;
return borderBoxReliableVal;
},
boxSizingReliable: function() {
computeStyleTests();
return boxSizingReliableVal;
},
pixelPosition: function() {
computeStyleTests();
return pixelPositionVal;
},
pixelMarginRight: function() {
computeStyleTests();
return pixelMarginRightVal;
Expand Down
17 changes: 12 additions & 5 deletions test/unit/dimensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,14 @@ QUnit.test( "interaction with scrollbars (gh-3589)", function( assert ) {
.css( borderBox )
.css( { "box-sizing": "border-box" } )
.appendTo( parent ),
$boxes = jQuery( [ plainContentBox[ 0 ], contentBox[ 0 ], borderBox[ 0 ] ] );
$boxes = jQuery( [ plainContentBox[ 0 ], contentBox[ 0 ], borderBox[ 0 ] ] ),

// Support: IE 9 only
// Computed width seems to report content width even with "box-sizing: border-box", and
// "overflow: scroll" actually _shrinks_ the element (gh-3699).
borderBoxLoss =
borderBox.clone().css( { overflow: "auto" } ).appendTo( parent )[ 0 ].offsetWidth -
borderBox[ 0 ].offsetWidth;

for ( i = 0; i < 3; i++ ) {
if ( i === 1 ) {
Expand Down Expand Up @@ -616,13 +623,13 @@ QUnit.test( "interaction with scrollbars (gh-3589)", function( assert ) {
assert.equal( contentBox.outerHeight(), size + 2 * padding + 2 * borderWidth,
"content-box outerHeight includes scroll gutter" + suffix );

assert.equal( borderBox.innerWidth(), size - 2 * borderWidth,
assert.equal( borderBox.innerWidth(), size - borderBoxLoss - 2 * borderWidth,
"border-box innerWidth includes scroll gutter" + suffix );
assert.equal( borderBox.innerHeight(), size - 2 * borderWidth,
assert.equal( borderBox.innerHeight(), size - borderBoxLoss - 2 * borderWidth,
"border-box innerHeight includes scroll gutter" + suffix );
assert.equal( borderBox.outerWidth(), size,
assert.equal( borderBox.outerWidth(), size - borderBoxLoss,
"border-box outerWidth includes scroll gutter" + suffix );
assert.equal( borderBox.outerHeight(), size,
assert.equal( borderBox.outerHeight(), size - borderBoxLoss,
"border-box outerHeight includes scroll gutter" + suffix );
}
} );
Expand Down

1 comment on commit 3fcddd6

@Krinkle
Copy link
Member

@Krinkle Krinkle commented on 3fcddd6 Jul 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit appears to have broken the support tests in all browsers. Still the case on latest master.

See: #3730


It also broke the dimensions tests in IE 10 and IE 11.

See: #3731

Please sign in to comment.