Closed
Bug 180552
Opened 22 years ago
Closed 22 years ago
Setting body overflow to "hidden" breaks document.body.clientHeight and clientWidth
Categories
(Core :: DOM: Core & HTML, defect, P1)
Core
DOM: Core & HTML
Tracking
()
RESOLVED
FIXED
mozilla1.3beta
People
(Reporter: telematx, Assigned: jst)
References
()
Details
(Keywords: topembed+, Whiteboard: [HAVE FIX?])
Attachments
(1 file, 1 obsolete file)
4.50 KB,
patch
|
caillon
:
review+
peterv
:
superreview+
|
Details | Diff | Splinter Review |
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.1) Gecko/20020826 Build Identifier: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.1) Gecko/20020826 If in a stylesheet I set the document overflow to "hidden", then in javascript document.body.clientHeight and clientWidth are "0". Moreover, if the document body is empty, or contains only absolutely positioned blocks, then offsetHeight and offsetWidth are are also "0". If I remove the overflow line from the stylesheet, then all these properties are their correct values. This behavior is different from Internet Explorer -- in IE, setting body overflow to hidden just means that clientWidth and clientHeight get slightly larger, as there are no scrollbars displayed. Additionally, if the document body is empty (ie, there is nothing between the BODY tags), or if overflow is set to hidden and all page content is absolutely positioned, then in IE offsetHeight and offsetWidth are equal to the displayed "whitespace". Reproducible: Always Steps to Reproduce: 1. 2. 3.
Comment 1•22 years ago
|
||
can you attach a testcase ? Does it also happen with latest 1.2 ? http://ftp.mozilla.org/pub/mozilla/nightly/latest-1.2/
Here's a demonstration page: http://thisoldhaus.com/tests/moz_test/ I'll download 1.2b and try it out...
Okay, it seems to be even more broken in 1.2b If I set body overflow=hidden, body padding=0px, and only have absolutely positioned content, then in 1.1 the content is visible, but offsetHeight/Width and clientHeight/Width are all zero. In 1.2b all values are still zero, *and* the content is not displayed.
Comment 4•22 years ago
|
||
-> Layout (Forms ?)
Assignee: asa → float
Component: Browser-General → Layout: Floats
QA Contact: asa → ian
The content not being displayed is bug 170011. Please don't discuss that issue further here. The rest seems to be the implementation of clientWidth / clientHeight, although there could be a layout problem. ->Dom Style.
Component: Layout: Floats → DOM Style
.
Assignee: float → jst
![]() |
||
Comment 7•22 years ago
|
||
So... I have a few questions. 1) What should clientHeight/clientWidth in general be for non-positioned elements with no overflow set? (the msdn doc says nothing on the topic) 2) Perhaps we should be applying our "if it's the body, munge the numbers" hack even in cases when the body's primary frame implementes nsIScrollFrame?
Status: UNCONFIRMED → NEW
Component: DOM Style → DOM Mozilla Extensions
Ever confirmed: true
OS: Windows 2000 → All
Hardware: PC → All
> What should clientHeight/clientWidth in general be for non-positioned > elements with no overflow set? (the msdn doc says nothing on the topic) Here's the MSDN page illustrating Element Dimension and Location: http://msdn.microsoft.com/workshop/author/om/measuring.asp In Internet Explorer, clientHeight/clientWidth and offsetHeight/offsetWidth for the document body are actually reflective of the browser window's "page display area" (not sure the actual name), rather than the contents of the page. offsetHeight/offsetWidth reflect the overall dimensions of the page display area, and clientHeight/clientWidth are the dimensions of the display area minus the scrollbars and document body border (if present). (This also means that offsetHeight and offsetWidth can never be smaller than clientHeight and clientWidth). An example: in Internet Explorer, if I have a page with body overflow set to hidden, then offsetHeight and clientHeight are equal (say, 550px). offsetWidth and clientWidth are also equal (say, 750px). If I take this same page and change body overflow to scroll, then offsetHeight and offsetWidth stay the same (550px and 750px), but clientHeight and clientWidth shrink by the height and with of the scrollbars (becoming something like 525px and 725px). In IE this behavior (and the numbers) are consistent, no matter if the content is absolutely positioned, relatively positioned, or even if there is no page content at all. If you try my test page ( http://thisoldhaus.com/tests/moz_test/ ), and compare Mozilla's behavior to that of IE, you'll see there's a big difference between the two.
![]() |
||
Comment 9•22 years ago
|
||
OK. So IE treats <body> as special in all cases.... (makes sense in IE's rendering model, and is pretty odd in Mozilla, since you can have stuff rendering that's not part of the <body>). Notice that if you set overflow:scroll then the numbers are different, but so is the _rendering_. The problem is that we shouldn't be returning those zeroes in the hidden case, but we _do_ want to return the correct values for <body> (which will differ from IE's) in the scroll case. Right?
Reporter | ||
Comment 10•22 years ago
|
||
> Notice that if you set overflow:scroll then the numbers are
> different, but so is the _rendering_. The problem is that
> we shouldn't be returning those zeroes in the hidden case,
> but we _do_ want to return the correct values for <body>
> (which will differ from IE's) in the scroll case. Right?
I suppose so. However, it makes no sense to me how, if body overflow is not
set, that clientHeight is the total available height of the display area, but
if overflow is set to scroll, then suddenly clientHeight is only the height of
the <body> minus the scrollbars (which, if the page only consists of a
paragraph or two, is much less than the total available height). It doesn't
seem consistent.
But in any case, as a site developer, I need to be able to find out the
browser's available display area (minus scrollbars and the like, if displayed),
and I need these numbers to be consistent regardless of what overflow is set
to, and regardless of of the page contents. And even when this bug is fixed,
it appears I won't always be able to use document.body.clientHeight/clientWidth
to find these dimensions - correct? If this is the case, what do I use?
![]() |
||
Comment 11•22 years ago
|
||
Well... this is why I asked what IE's definition of clientHeight is for a div that does not have overflow. That's the situation we have with <body>. The heart of the problem is that in IE the <body> is the entire rendering area. In Mozilla it is not. So if you set "overflow:scroll; height: 100px" on the body, there will be no content outside that 100px tall strip, whereas IE will ignore the height:100px. It's a matter of whether clientHeight/clientWidth on the body should be consistent with all other scrolled containers or consistent with IE... We can't have it both ways.
Reporter | ||
Comment 12•22 years ago
|
||
> Well... this is why I asked what IE's definition of > clientHeight is for a div that does not have overflow. AFAIK, in IE, if you have a 100px tall <div>, with a border of 5px, and scrolling content (overflow could be "auto", "scrolling", or not even specified), then: offsetHeight = 100px clientHeight = (offsetHeight - border - scrollbar) = ~65px If you take the same <div> and set overflow:hidden (or if overflow is not set, and there isn't enough content to scroll), then: offsetHeight = 100px clientHeight = (offsetHeight - border) = 90px; > The heart of the problem is that in IE the <body> is > the entire rendering area. In Mozilla it is not. So > if you set "overflow:scroll; height: 100px" on the body, > there will be no content outside that 100px tall strip, > whereas IE will ignore the height:100px. > It's a matter of whether clientHeight/clientWidth on the > body should be consistent with all other scrolled containers > or consistent with IE... We can't have it both ways. But even in Mozilla, <body> doesn't consistently behave like other objects. If in a stylesheet you have... BODY { height: 200px; width: 200px; border: solid 1px black; background-color: blue; } ...you'll get a 200x200px <body> object with border, but the background color is set for the *entire* rendering area. If <body> is treated the same as <div>, shouldn't the background only apply within the boundaries of the <body> object, just like border? In my opinion, IE makes more sense in this regard -- <body> should be an "alias" for the entire rendering area. If I set a <body> background, it applies to the whole area. If I set BODY { overflow:scroll; }, then scrollbars should appear for the entire rendering area. The same for border. And document.body.offsetHeight/offsetWidth, document.body.clientHeight/clientWidth, and document.body.scrollHeight/scrollWidth should tell me information about the entire rendering area and its contents, so that I can use javascript to position content within the entire available area. What's the rationale for treating <body> as independent of the rendering area? And is there any way to retrieve the dimensions of the rendering area, or to force it to display or hide the scrollbars, independent of the <body> object and its contents?
![]() |
||
Comment 13•22 years ago
|
||
That <body> background is painted on the canvas if the <html> background is not set as a backwards compatibility hack and only in legacy HTML documents (not in XHTML or any other XML). See http://www.w3.org/TR/CSS21/colors.html#q2, paragraph 3 and 4. > What's the rationale for treating <body> as independent of the rendering area? Because the rendering area is the canvas. Inside that is the root element (<html>), inside which is the <body>. As a simple test: <html> <head> <title>The title</title> <style> head, style, title { display: block } style { white-space: pre; font-family: monospace } head { border: 2px solid green } body { border: 2px solid blue } html { border: 2px solid red } </style> </head> <body> There is content outside the body </body> </html> As far as CSS is concerned, content inside <head> is in no way special; it just happens to be set display:none in the UA stylesheet. > And is there any way to retrieve the dimensions of the rendering area For now, getting the computed height and width of document.documentElement will work (using getComputedStyle). I would have thought that clientWidth/clientHeight would work on it as well, but they do not. That's buggy, just like us returning 0 for overflow:hidden <body> is buggy.... You can force hiding of the scrollbars by setting overflow:hidden on the <body> or <html> (sorta hacked in for limited IE compat). There's no way to force them to show, to my knowledge.
Reporter | ||
Comment 14•22 years ago
|
||
> As far as CSS is concerned, content inside <head> > is in no way special; it just happens to be set > display:none in the UA stylesheet. :o Looks like I need to do some reading; I didn't know about that. > I would have thought that clientWidth/clientHeight > would work on it as well, but they do not. That's > buggy, just like us returning 0 for overflow:hidden > <body> is buggy.... Yes -- if I now understand correctly for Mozilla, if Body Overflow is set to Hidden, clientWidth/clientHeight should only be zero if: a) the <body> has no border and contains no content, or b) the <body> has no border, and all it's content is absolutely positioned, and thus "magically" becomes independent of the body object. Also, clientWidth/clientHeight are currently incorrect if Body Overflow is not specified -- they should be equal or less than offsetWidth/offsetHeight, but instead are equal to the canvas width and height. This is part of what confused me -- I had assumed that clientWidth/clientHeight for the <body> represented the same things in Mozilla as in IE -- in this one case they do, but it's a bug, and should be fixed so as to be consistent with Mozilla's rendering model.
Updated•22 years ago
|
Keywords: mozilla1.3
Comment 15•22 years ago
|
||
*** Bug 184976 has been marked as a duplicate of this bug. ***
Comment 17•22 years ago
|
||
FYI because this is such a huge bug in breaking SBC signup (and SBC broadband users may be using Netscape 7), we are going try to get them to implement a workaround. I have added topembed, nsbeta1 anyway and ? for blocking 1.3b.
Comment 18•22 years ago
|
||
Re: comment #8 and #9: Do not trust too much the image describing the MSIE DHMTL object model for several reasons. 1- They changed the image while working on MSIE 6 beta 1 but they never actually use MSIE 6 in standards compliant rendering mode to do the new, latest image. I can prove that. 2- There is a contradiction between the applied box model (conforming to the CSS1 box model) and the image gif http://msdn.microsoft.com/workshop/graphics/dhtmlpos.gif coming from http://msdn.microsoft.com/workshop/author/om/measuring.asp and this image http://msdn.microsoft.com/workshop/graphics/boxdim.gif found at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnie60/html/cssenhancements.asp as the div's top value is within the margin when the image show it should be outside. Blatant contradiction here that anyone, everyone can see. 3- When I started my javascript section, I saved this image: http://www.geocities.com/Area51/Realm/8655/GRAPHICS/GIF/MSIEdhtmlpos.gif just in case the MSDN page would change or the image disappear. Several months later, they changed the image to this http://www.geocities.com/Area51/Realm/8655/GRAPHICS/GIF/MSIEdhtmlposNew.gif 4- I even tried to construct in standards compliant rendering mode the MSIEdhtmlposNew.gif while applying the unique idiosyncratic logic in their image and I never could. They just updated the image with a change on the clientLeft, clientTop values and that's it. They never updated their DHTML object model schema according to their claimed full compliance with CSS1 box model and according to their "When you use the !DOCTYPE declaration to specify standards-compliant mode, this element represents the canvas葉he entire surface onto which a document's contents can be rendered." For many reasons, the DHMTL object model gif image at MSDN should not be trusted blindly. Despite all this, I really think people should vote for bug 156388 Thanks :)
Comment 19•22 years ago
|
||
Re: comment #12: "documentElement of type Element, readonly This is a convenience attribute that allows direct access to the child node that is the root element of the document. For HTML documents, this is the element with the tagName 'HTML'." read at http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-87CD092 MSIE 6 for Windows is compliant with DOM level 1 Core and DOM level 2 Core. Mozilla is still not compliant. Re: comment #13: >> And is there any way to retrieve the dimensions of the rendering area >For now, getting the computed height and width of document.documentElement will work (using getComputedStyle). I would have thought that clientWidth/clientHeight would work on it as well, but they do not. That's because bug 156388 has not been fixed yet. The dimensions of the rendering area are easy to get as soon as you fix bug 156388. After 3 months of waiting, I personally insisted that Mr. Zbarsky confirm bug 156388. Also after reading that "the _correct_ width of the rendering area in Mozilla can be gotten by looking at document.body.clientWidth just like in IE." http://bugzilla.mozilla.org/show_bug.cgi?id=48634#c52 MSIE 6 has 2 rendering modes, therefore 2 answers to how to get the dimensions of the browser viewport. Everywhere in this bugfile and in other bugs, if you do not use a doctype declaration with a full url in the system id part, then you trigger the browser into backward compatible rendering mode (document.compatMode == "BackCompat") where body is the element representing the canvas of the document. Canvas according to W3C: "the space where the formatting structure is rendered; the canvas is infinite for each dimension of the space." The canvas is the entire "surface" on which the document is laid out.
![]() |
||
Comment 20•22 years ago
|
||
Most of comment 19 (especially the first part, about documentElement) is factually incorrect. Please stop spamming bugs with such comments.
Comment 21•22 years ago
|
||
http://thisoldhaus.com/tests/moz_test/ case: Content Position: absolute Body Overflow: hidden Expected Results: offsetHeight : 0 clientHeight : 0 Actual Results: offsetHeight : 0 clientHeight : 0 If I set BODY { overflow:scroll; }, then scrollbars should appear for the entire rendering area. No, the body is a block level element in normal flow. HTML{overflow:auto;} is the currently broken feature your seeking. comment 10 >It doesn't seem consistent. It *is* inconsistent. IE is trying to keep this property for historical reasons. Mozilla does not need to do this. We have window.innerHeight/Width. I'd like window.hScrollbarSize and window.vScrollbarSize. This would make more sense than incosistantly using body.offsetHeight/Width. comment 13 >> And is there any way to retrieve the dimensions of the rendering area >For now, getting the computed height and width of document.documentElement will >work (using getComputedStyle) That should give the height of the documentElement, not the viewport. For the viewport, you need window.innerHeight - (isVScrollbarPresent ? 15 : 0); Detecting isVScrollbarPresent is not a simple task. Ideally, Mozilla will expose this property to scripting environments (JavaScript). javascript:alert(document.defaultView.getComputedStyle(document.documentElement,"").getPropertyValue("height")) javascript:alert(window.innerHeight) >It's a matter of whether clientHeight/clientWidth on the body should be >consistent with all other scrolled containers or consistent with IE... We >can't have it both ways. Be consistent with the property, not Internet Explorer's incorrect implementation of the property. This is a fundamental problem with Internet Explorer. It should not be copied.
Comment 22•22 years ago
|
||
>Detecting isVScrollbarPresent is not a simple task. Ideally, Mozilla will expose this property to scripting environments (JavaScript). If the html element does not have a margin (and that is easy to verify and to measure), then a simple comparison will indicate, reveal if the html element uses scrollbars. The code and everything is already in attachment 91255 [details] (bug 140308). Of course, this is assuming that other css property values are set to default values like overflow set to visible or auto, height set to auto. If it's set to scroll, then that's easy to know. There is also another indirect way to verify this. If the scrollHeight value of an element is greater than its offsetHeight + 15px, then you know that there is an vertical scrollbar: that's absolutely necessary by definition of the DHTML object model, and this, in both rendering modes. If the scrollWidth value of an element is greater than its offsetWidth + 15px, then you know that there is an horizontal scrollbar. Of course, all this is assuming Mozilla implements the DHTML object model and its properties for the document root element. ---- Mozilla does not implement clientWidth, clientHeight, scrollLeft, scrollTop, clientLeft and clientTop for the document root element, for documentElement. MSIE 6 for Windows does accordingly in standards compliant rendering mode. This is what my previous comment should have said. I'm sure Boris understands :); anyway, a lot of people already have in bug 62536, bug 111207, in this bug notwithstanding bug 156388.
Updated•22 years ago
|
Updated•22 years ago
|
Target Milestone: --- → mozilla1.3beta
Updated•22 years ago
|
Flags: blocking1.3b? → blocking1.3b-
Comment 23•22 years ago
|
||
Bug 169677 [ document.body.clientHeight = 0 if no scrollbars=1 passed to window.open() ], related or even a dupe?
Assignee | ||
Comment 24•22 years ago
|
||
*** Bug 169677 has been marked as a duplicate of this bug. ***
Assignee | ||
Comment 25•22 years ago
|
||
This makes body.client* be the size of the body frame even if there's no scrollbars (or possibility for scrollbars) in the body frame. Thoughts?
Assignee | ||
Comment 26•22 years ago
|
||
Ignore the bogus param descriptions in the comment above the declaration of GetClientAreaSize() in nsGenericHTMLElement.h.
Status: NEW → ASSIGNED
Priority: -- → P1
Whiteboard: [HAVE FIX?]
Assignee | ||
Updated•22 years ago
|
Attachment #111662 -
Flags: superreview?(peterv)
Attachment #111662 -
Flags: review?(bzbarsky)
Comment 27•22 years ago
|
||
Comment on attachment 111662 [details] [diff] [review] Proposed fix. >Index: content/html/content/src/nsGenericHTMLElement.cpp >=================================================================== >+ if (border) { >+ nsStyleCoord coord; >+ >+ if (eStyleUnit_Coord == border->mBorder.GetTopUnit()) { >+ size.height -= border->mBorder.GetTop(coord).GetCoordValue(); >+ } >+ if (eStyleUnit_Coord == border->mBorder.GetTopUnit()) { >+ size.height -= border->mBorder.GetTop(coord).GetCoordValue(); >+ } Shouldn't this be GetBottomUnit and GetBottom? Do we want to comment the code about special-casing body?
Attachment #111662 -
Flags: superreview?(peterv) → superreview+
Comment 28•22 years ago
|
||
Comment on attachment 111662 [details] [diff] [review] Proposed fix. >+ if (border) { >+ nsStyleCoord coord; >+ >+ if (eStyleUnit_Coord == border->mBorder.GetTopUnit()) { >+ size.height -= border->mBorder.GetTop(coord).GetCoordValue(); >+ } >+ if (eStyleUnit_Coord == border->mBorder.GetTopUnit()) { >+ size.height -= border->mBorder.GetTop(coord).GetCoordValue(); >+ } >+ >+ if (eStyleUnit_Coord == border->mBorder.GetLeftUnit()) { >+ size.width -= border->mBorder.GetLeft(coord).GetCoordValue(); >+ } >+ if (eStyleUnit_Coord == border->mBorder.GetRightUnit()) { >+ size.width -= border->mBorder.GetRight(coord).GetCoordValue(); >+ } >+ } Since you don't care about the origin (x and y values) you can just do the following (you might want to call |nsStyleBorder::CalcBorderFor(const nsIFrame*, nsMargin&)| first, if for some reason the border is not cached): if (border) { nsMargin theBorder; if (border->GetBorder(theBorder)) { size.Deflate(theBorder); } } Or, keep your existing code and use nsSize as the return value for GetClientAreaSize(). But if you do, fix what peterv said.
Assignee | ||
Comment 29•22 years ago
|
||
Assignee | ||
Updated•22 years ago
|
Attachment #111662 -
Attachment is obsolete: true
Assignee | ||
Updated•22 years ago
|
Attachment #112208 -
Flags: superreview?(peterv)
Attachment #112208 -
Flags: review?(caillon)
Comment 30•22 years ago
|
||
Comment on attachment 112208 [details] [diff] [review] Better fix. Nice. less code is always good. :-)
Attachment #112208 -
Flags: review?(caillon) → review+
Updated•22 years ago
|
Attachment #112208 -
Flags: superreview?(peterv) → superreview+
![]() |
||
Updated•22 years ago
|
Attachment #111662 -
Flags: review?(bzbarsky)
Assignee | ||
Comment 31•22 years ago
|
||
Fix checked in last night, marking FIXED. Please re-open if you disagree with how this works in Mozilla now.
Status: ASSIGNED → RESOLVED
Closed: 22 years ago
Resolution: --- → FIXED
Updated•11 years ago
|
Component: DOM: Mozilla Extensions → DOM
Updated•5 years ago
|
Component: DOM → DOM: Core & HTML
You need to log in
before you can comment on or make changes to this bug.
Description
•