Skip to content

Commit

Permalink
Dimensions: fall back to offsetWidth/Height for border-box in IE
Browse files Browse the repository at this point in the history
- Use getClientRects() to explicitly detect hidden/disconnected
  elements

Close gh-4223
Fixes gh-4102
  • Loading branch information
timmywil committed Nov 27, 2018
1 parent 13d0be1 commit 315199c
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 20 deletions.
33 changes: 18 additions & 15 deletions src/css.js
@@ -1,9 +1,7 @@
define( [
"./core",
"./var/pnum",
"./core/access",
"./core/camelCase",
"./var/document",
"./var/rcssNum",
"./css/var/rnumnonpx",
"./css/var/cssExpand",
Expand All @@ -18,7 +16,7 @@ define( [
"./core/init",
"./core/ready",
"./selector" // contains
], function( jQuery, pnum, access, camelCase, document, rcssNum, rnumnonpx, cssExpand,
], function( jQuery, access, camelCase, rcssNum, rnumnonpx, cssExpand,
getStyles, swap, curCSS, adjustCSS, addGetHookIf, support, finalPropName ) {

"use strict";
Expand Down Expand Up @@ -122,7 +120,8 @@ function getWidthOrHeight( elem, dimension, extra ) {
var styles = getStyles( elem ),
val = curCSS( elem, dimension, styles ),
isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
valueIsBorderBox = isBorderBox;
valueIsBorderBox = isBorderBox,
offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 );

// Support: Firefox <=54
// Return a confounding non-pixel value or feign ignorance, as appropriate.
Expand All @@ -133,22 +132,26 @@ function getWidthOrHeight( elem, dimension, extra ) {
val = "auto";
}

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

// Fall back to offsetWidth/offsetHeight when value is "auto"
// This happens for inline elements with no explicit setting (gh-3571)
// Support: Android <=4.1 - 4.3 only
// Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602)
if ( val === "auto" ||
!parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) {

val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ];

// offsetWidth/offsetHeight provide border-box values
valueIsBorderBox = true;
// Support: IE 9-11 only
// Also use offsetWidth/offsetHeight for when box sizing is unreliable
// We use getClientRects() to check for hidden/disconnected.
// In those cases, the computed value can be trusted to be border-box
if ( ( isBorderBox && !support.boxSizingReliable() || val === "auto" ||
!parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) &&
elem.getClientRects().length ) {

// Where available, offsetWidth/offsetHeight approximate border box dimensions.
// Where not available (e.g., SVG), assume unreliable box-sizing and interpret the
// retrieved value as a content box dimension.
valueIsBorderBox = offsetProp in elem;
if ( valueIsBorderBox ) {
val = elem[ offsetProp ];
}
}

// Normalize "" and auto
Expand Down
4 changes: 4 additions & 0 deletions test/data/testsuite.css
Expand Up @@ -142,3 +142,7 @@ section { background:#f0f; display:block; }
padding: 0;
margin: 0;
}

.border-box, .border-box * {
box-sizing: border-box;
}
32 changes: 27 additions & 5 deletions test/unit/dimensions.js
Expand Up @@ -659,7 +659,9 @@ QUnit.test( "interaction with scrollbars (gh-3589)", function( assert ) {
parent = jQuery( "<div/>" )
.css( { position: "absolute", width: "1000px", height: "1000px" } )
.appendTo( "#qunit-fixture" ),
fraction = jQuery( "<div style='width:4.5px;'/>" ).appendTo( parent ).width() % 1,
fraction = jQuery.support.boxSizingReliable() ?
jQuery( "<div style='width:4.5px;'/>" ).appendTo( parent ).width() % 1 :
0,
borderWidth = 1,
padding = 2,
size = 100 + fraction,
Expand Down Expand Up @@ -695,10 +697,8 @@ QUnit.test( "interaction with scrollbars (gh-3589)", function( assert ) {
borderBox[ 0 ].offsetWidth;

if ( borderBoxLoss > 0 ) {
borderBox.css( {
width: ( size + borderBoxLoss ) + "px",
height: ( size + borderBoxLoss ) + "px"
} );
borderBox[ 0 ].style.width = ( size + borderBoxLoss ) + "px";
borderBox[ 0 ].style.height = ( size + borderBoxLoss ) + "px";
}

for ( i = 0; i < 3; i++ ) {
Expand Down Expand Up @@ -750,4 +750,26 @@ QUnit.test( "interaction with scrollbars (gh-3589)", function( assert ) {
}
} );

QUnit.test( "outerWidth/Height for table cells and textarea with border-box in IE 11 (gh-4102)", function( assert ) {
assert.expect( 5 );
var $table = jQuery( "<table class='border-box' style='border-collapse: separate' />" ).appendTo( "#qunit-fixture" ),
$thead = jQuery( "<thead />" ).appendTo( $table ),
$firstTh = jQuery( "<th style='width: 200px;padding: 5px' />" ),
$secondTh = jQuery( "<th style='width: 190px;padding: 5px' />" ),
$thirdTh = jQuery( "<th style='width: 180px;padding: 5px' />" ),
$td = jQuery( "<td style='height: 20px;padding: 5px;border: 1px solid'>text</td>" ),
$tbody = jQuery( "<tbody />" ).appendTo( $table ),
$textarea = jQuery( "<textarea style='height: 0;padding: 2px;border: 1px solid;box-sizing: border-box' />" ).appendTo( "#qunit-fixture" );
jQuery( "<tr />" ).appendTo( $thead ).append( $firstTh );
jQuery( "<tr />" ).appendTo( $thead ).append( $secondTh );
jQuery( "<tr />" ).appendTo( $thead ).append( $thirdTh );
jQuery( "<tr><td></td></tr>" ).appendTo( $tbody ).append( $td );

assert.strictEqual( $firstTh.outerWidth(), 200, "First th has outerWidth 200." );
assert.strictEqual( $secondTh.outerWidth(), 200, "Second th has outerWidth 200." );
assert.strictEqual( $thirdTh.outerWidth(), 200, "Third th has outerWidth 200." );
assert.strictEqual( $td.outerHeight(), 30, "outerHeight of td with border-box should include padding." );
assert.strictEqual( $textarea.outerHeight(), 6, "outerHeight of textarea with border-box should include padding and border." );
} );

} )();

0 comments on commit 315199c

Please sign in to comment.