methods for element width/height - javascript

Question: Is there a scenario where getBoundingClientRect and window.getComputedStyle would differ in width or height?
I just found a inconsistent width (see under) in IE when a element has box-sizing where window.getComputedStyle returns the wrong value.
So I thought about overriding just width and height with values from getBoundingClientRect but not sure if there are cases where that would fail.
Example of the problem (broken in IE): http://jsfiddle.net/bwPM8/
var box = document.querySelector('.box');
var gBCR_width = box.getBoundingClientRect().width; // always 200
var wGCS = window.getComputedStyle(box).width; // 200 some browsers, 160 in IE

Yes, there are several differences between these two functions.
getBoundingClientRect() will return a text rectangle object that encloses a group of text rectangles (the union of the rectangles returned by getClientRects() for the element, i.e., the CSS border-boxes associated with the element). The latter, getComputedStyle(), will return the computed CSS style of that element, after applying all CSS.
Therefore the resulting width and height can be drastically different.
For instance, by simply applying a transform to that element you already change the width that is returned by getBoundingClientRect():
http://jsfiddle.net/epW3c/
Moreover, even if you add a border or padding to your element, the width and height will be different in both cases.
Depending on the version of IE you're testing this on, you might be experiencing the infamous Internet Explorer box model bug which causes the interpretation of the dimensions of the element to be wrong. Make sure you're not running your page in quirks mode by adding the doctype properly.

In IE the CSS padding: 10px; cause overflow and that gives you extra size of the computedStyle..
Also IE calculates Borders separately from the object.
This sums up the answer with difference of 40px
Now with overflow:hidden; OR box-sizing: border-box; that cause value go in minus so will become 200px - 40px = 160px.
Note: Here if we remove overflow:hidden will not make any difference as the box-sizing:border-box cause the design not to grow further from defined height and width.
I have generate another fiddle 1 (without padding) which gives
'computedValue : 180px'
And with Border:0px the fiddle 2 give results
same as in other browser..
I hope this clears what causes what in IE(IE has its own mind that sometimes cause pain to developers)

Related

Detect overflow fails in Firefox using (this.clientWidth < this.scrollWidth)

We're trying to detect if an element is overflowing using this simple Javascript code:
this.clientWidth < this.scrollWidth
This works perfectly on Chrome/IE but on Firefox it fails in until there's too much overflowing.
The example can be seen here: http://colnect.com/en/coins/countries#-1;yemen
This page show a list of countries. We do vertical centering of the text if it fits in a single line. If it's too long for one line (which is why we want to detect the overflow), we change it so the text appears in two lines.
In this attachment you can see what happens on Firefox (depending on the width of your window). When the overflow isn't "big enough", it's not detected even though CSS has clearly added the ellipsis for it so it IS overflowing. First 4 "countries" shown are correct (the 4th even broke into two lines) but the others are not.
To recreate, simply start resizing your Firefox window slowly until you see where this breaks.
Any ideas? A different way to detect overflow?
Try this:
if you want to keep full name then, just remove text-overflow:ellipsis; from the selected class or id.
if you want to keep name in one line and no ... in last position, then set white-space: nowrap !important;overflow: hidden; in selected class
In my Firefox browser: (with center align and without text-overflow:ellipsis;)
(with center align and with text-overflow:ellipsis;)
you can choice any one.
I've noticed two things with your website. You are using white-space:nowrap and you have a transition: all on the cell class. I changed those to white-space:normal and disabled the transition and it worked fine with the wrapping.
The reason i disabled the transition is that I found that sometimes it takes a moment to change the text and break it to two lines :)
Give it a try and let me know if that works.
...also keep in mind that having an ellipsis for overflown elements may force the ellipsis to appear because it might be larger in width than the last character. I have encountered some times where without ellipsis the whole text could be shown, while using ellipsis removed my last character.
Please try this CodePen sample.
<div id='mydiv'>Some relatively long line of text to test an interesting question about Firefox behavior.</div>
<br><br><br>
<div id='dbgmsg'></div>
#mydiv {
width: 33%;
border: solid 1px gray;
white-space: nowrap;
overflow: hidden;
}
$(document).ready(function insertAds() {
function printWidthes(){
var clientWidth = $('#mydiv').get(0).clientWidth;
var scrollWidth = $('#mydiv').get(0).scrollWidth;
$('#dbgmsg').html("clientWidth = " + clientWidth + "<br>scrollWidth = " + scrollWidth);
}
$(window).resize(function(){
printWidthes();
});
printWidthes();
});
I've tested it on the latest Firefox version (35.0.1) on Window 7 and its behavior is absolutely correct. When the div size is less than the text size by even only one pixel then clientWidth becomes less than scrollWidth.
Try to test it on your computer; probably you have different Firefox version that causes the problem. BTW, did you saw that the numbers are wrong in debugger / print or it's just your guess? May be your site works wrong because any other reason?
I think this may be related to a (now resolved) bug in firefox.
Perhaps a different way of determining the scrollWidth and clientWidt is the answer (as brilliantly stated in why scrollwidth doesnt work) :
Apparently by hiding the element before reading the scrollWidth gives a different value than when visible.
element=document.getElementById("my_div");
var scrollWidth = $(element).css("overflow", "hidden")[0].scrollWidth;
alert('clientWidt h = ' + element.clientWidth + ', scrollWidth = ' + scrollWidth );
$(element).css("overflow", "visible");

How to get updated width of content after a css change?

I'm trying to modify the css class of my body element.
Before modifying the class, I check the scroll width of my content:
$(window.document.body).prop('scrollWidth'); // 800px
Now I modify the css class and check the scroll width again:
$(window.document.body).prop('class', someCssClassName);
$(window.document.body).prop('scrollWidth'); // still reports 800px
I know the scroll width should not be 800px after this particular change. I start a timer and keep printing the scroll width, and after a few ms I see it change to 600px.
So it seems like I can't immediately get the updated content width (or I'm misinterpreting what's going on).
Is there a way to get notified when the re-flow is complete, so that I might get the updated width?
I don't want to set a timer and keep checking, if possible.
I'm trying this in an android WebView.. browser.. . So I'm not sure if this behavior will be the same if I try in a desktop browser.
Thank you
To answer the question: accessing the scrollWidth property automatically flushes any style change (forces a reflow) and then returns the computed value. This happens synchronously, hence you don't need to "wait" for the reflow to complete -- the JS will simply freeze while the reflow happens and then return the correct scrollWidth value.
You are actually facing a very specific Blink/WebKit bug in their scrollWidth implementation regarding the body element.
I've simplified your code a bit by removing some unnecessary jQuery abstraction (fiddle):
document.body.className = 'w600px';
console.log(
document.body.scrollWidth, // Firefox: 600, Chrome: viewport width
$(document.body).width() // 600 in both browsers
);
.w600px {
width: 600px;
}
From the CSSOM element.scrollWidth spec:
3. If the element is the HTML body element, the Document is in quirks mode and the element has no associated scrolling box, return max(viewport scrolling area width, viewport width).
It seems like Chrome is not checking whether the document is in Quirks mode and returning the viewport (scrolling) width independent of the document mode.
You should open a Chromium issue in these cases.
Workarounds
It really depends on your use case. $(document.body).width() is usually fine, unless the content overflows the body element's width.
Alternatively, wrap all the page's contents inside of a div and use it to apply the class and to retrieve the scrollWidth from.
Try
function getprop( el, prop ) {
var props = window.getComputedStyle (
$(el).get(0)).getPropertyValue(prop);
return String(props);
};
console.log(getprop("body", "width"))
http://jsfiddle.net/guest271314/6uKH6/5/

Error with computed size of relative-size HTML elements in javascript

My window object has a width of 1361px.
A container div has its width set to 90%, that theorically makes 1224.9px.
However, the computed size of it ( $("#mycontainer").width() ) returns 1225px. FYI, the computed number seems to come from the browser itself, not jQuery.
Now, the problem is that if I put two floating divs in it, respectively 1000px and 225px, they will NOT fit on the same line, allegedly because 1225px > 1224.9px. At least in FF and Chrome, not tested elsewhere.
If I set the container a fixed size of 1225px, then the two divs will be back on the same line, which confirms in my mind that the browser does not use the superior-rounded computed size to know how much space is actually available for children to occupy.
I wanted to know if anybody knew how to solve this. I am not even sure how to get the percentage size of the container to do the maths myself like this :
var width = Math.floor($(window).width * $("#mycontainer").percentageWidth() / 100)
CSS display: flex; is a good way to fix these quirks nowadays.

Getting div height

Firebug tells me the computed style of my_div:
width 300px
height 453.167px
Yet when I execute console.log(mydiv.style.height), it gives me an empty string, even though console.log(mydiv) logs the correct element. I am sure the page has loaded by the time this logging code is called. I'd appreciate a solution that does not use jQuery.
Depending on the browser of choice, one of these will do:
mydiv.offsetHeight
mydiv.clientHeight
Get full height of a clipped DIV
Getting the height of a div
UPDATE:
Many browser inconsistencies have been fixed since my original answer. Now the clientHeight property of a DOM element is reliable.
var height = element.clientHeight;
The Element.clientHeight read-only property is zero for elements with no CSS or inline layout boxes, otherwise it's the inner height of an element in pixels, including padding but not the horizontal scrollbar height, border, or margin.
clientHeight can be calculated as CSS height + CSS padding - height of horizontal scrollbar (if present).
Note: This property will round the value to an integer. If you need a fractional value, use element.getBoundingClientRect().
Source: https://developer.mozilla.org/en-US/docs/Web/API/Element/clientHeight
Original answer:
If you use the jQuery JS library, you can just do this:
var computed_height = $('#my_div').height();
If you use the Prototype JS library, it's similar:
var computed_height = $('my_div').getHeight();
Using a library is often the easiest & most cross-browser way to do something. Getting computed styles with vanilla js is unreliable because the properties are different across browsers.

JavaScript - Need a way to set OuterHeight of the Element

I have an container element which is sort of a layout container for its children and based on some attributes I have to arrange children.
I need simple way to set outerHeight of an element, something like,
$(e).setOuterHeight(200);
jQuery's outerHeight does not set the height at all, indeed its a readonly method.
$(e).height(200); // this clips my element
In above method, I loose borders of input of type text.
My element's children are docked based on available space and some other criteria based on data that it holds, simple layouts like float,clear etc will not work because padding etc change dynamically based on sizes. I will finally end up using Table, even if I dont want to but have no choice, but anyway thanks for the help.
Now when element is sized to more then children then there is no problem, but sometimes container element may have lesser height then the children and that time, I need to increase the size.
function calculateSize(e){
var s = {
width: $(e).innerWidth(),
height: 0
};
var ae = new Enumerator(e.children);
while(ae.next()){
var child = ae.current();
// I have tried all alternatives
// for following lines
// child.clientHeight || child.offsetHeight
// $(child).outerHeight()
// $(child).innerHeight()
s.height += $(child).outerHeight();
}
if(s.height > $(e).height()){
$(e).height(s.height);
}
}
function layoutChildren(e){
....
/// for every child c
/// some steps before
var heightForChildren =
calculatedWithPadMarginBorder(availableHeight,c);
/// tried combinations
$(c).height(heightForChildren);
/// last statement fails for button
/// as button's padding cuts itself
/// removing padding in calculation
/// cuts other input elements !!
/// some steps after
....
}
I need some explanation of how to calculate runtime height/width including/excluding padding/margin/border etc and how to set it correctly so that I dont run into problems. I cant keep on trying all permutations combinations as I dont see a correct documentation even on jQuery website.
Fixed height calculations are fine, but this is kind of a dynamic element which resizes itself and arranges children in specific order.
Problem is there is no way to set outerHeight, when we set height/width of an element, the height/width is actually inner height/width without taking margin into consideration, while when we want to resize parent, we need outerHeight, but we cannot set back the outerHeight that easily.
My calculateSize and layoutChildren are two separate methods and two separate algorithms because parent will be resized to sum of all children's height. And then height is simply divided by no. of children stacked one above other. My calculation is perfect, but in my layoutChildren method I have "outerHeight" and "outerWidth" of element and have no idea on how to set it correctly by using jQuery or any other way.
.outerHeight( value )
version added: 1.8.0
you can use jQuery.outerHeight(value) to set the value of an element's outer height. Ex: $foo.outerHeight( 200 )
If you don't have a special requirement, a standard element by default sizes its height to match its children. If you style the to float:left or float:right its default width will then also be that to contain all its children.
Ok, this is strange but this is the Answer.
There are weird controls,
SELECT
BUTTON (INPUT[type=submit|reset|button])
WebKit Browsers
Padding and Border are considered as part of OuterWidth for all controls
Padding and Border must be added to Width as OuterWidth for all controls
Padding and Border are considered as part of InnerWidth for "weird controls"
Padding and Border must be subtracted from Width before setting the Width for all "non weird controls"
Non WebKit Browsers
Padding and Border are considered as part of OuterWidth for all non "weird controls"
Padding and Border must be added to Width as OuterWidth for all non "weird controls"
Padding and Border are considered as part of InnerWidth for all non "weird controls"
Padding and Border must be subtracted from Width before setting the Width for all "non weird controls"
I would be happy to help, but I simply do not understand your question.
In regards to the documentation of the dimensions methods of jQuery I found that http://api.jquery.com/category/css/ holds documentation on both innerWidth(), innerHeight(), outerWidth() and outerHeight().
I hope this helps, otherwise, try reading through your question, making it more obvious what you need the answer for.

Categories

Resources