HTML - Which element has the page's scrollbar: <BODY> or <HTML>? - html

In a simple, compliant HTML document, where the content in the <BODY> element is of greater height than the browser's viewport, a vertical scrollbar will appear on the right (unless the scrollbar is disabled, of course).
When this happens, which element is the scrollbar attached to: <BODY> or <HTML>?

By default, at least in Chrome, <html>. You can test this by scrolling down on this page and comparing document.body.scrollTop to document.getElementsByTagName('html').item(0).scrollTop.
There is nothing requiring that you maintain this choice, and you are able to override this default behavior using CSS.

If you're asking to know how element attach the CSS property overflow, this doesn't matter. You can attach it to <html> or to <body>, as you prefer.

as David Murdoch described Here this is the best way to know
function getScrollingElement() {
var d = document;
return d.documentElement.scrollHeight > d.body.scrollHeight &&
d.compatMode.indexOf('CSS1') == 0 ?
d.documentElement :
d.body;
}

try Adding:
* {
outline: 1px solid green;
}
Then when you scroll down you can see tall box (big one) after you right click on it to inspect element Then you should see all the information you need.

Related

Document stacking context root element: <body> or <html>?

Here's what I know:
In HTML, the document's root element is <html>
A document's root element creates a stacking context, hence <html> is the root element of the first stacking context created in any HTML document
From this, I'd expect any z-index: -1 element to be positioned behind <body> (though in front of <html>) in a document where no other stacking context comes into play.
The following example, however, demonstrates otherwise in all modern browsers: http://jsfiddle.net/39q2u/
I've dug a little deeper in that second example: http://jsfiddle.net/39q2u/1/
Adding a background-color to <html> somehow makes the rendering engine realize that the z-index: -1 element should indeed be displayed behind <body>, effectively making it invisible since <body> also has a background-color set.
Interestingly, I've given a try to several other CSS properties, an none of them seem to have the same effect.
(The element remains visible in IE 9.)
Removing the background-color from <body> makes the z-index: -1 element appear again, proving it was hidden behind <body>.
The issue I'm having with this is how to make sense of that behavior:
Is <body> subject to additional rules when it comes to stacking contexts?
Why is it needed to set a background-color on <html> for the rendering engine to behave correctly?
Or did I just misunderstand something, somewhere?
The default background-color of html is transparent. Thus, elements with a negative z-index are displayed, because you can see them "through" the html element. The link provided by #thirtydot points toward the right direction, although perhaps this link: http://www.w3.org/TR/css3-background/#background-color might be more on point.
I am not 100% sure but I believe the body tag always follows a z-index which is relative to other elements to make it easier when ordering multiple elements on the page.
If you apply an attribute to html, it suddenly becomes, and behaves like any other element, therefore putting it's child element, tag, into use as an element on the page also. Think of it as if you have toys you can play with, then toys you cannot reach. By assigning an attribute to the html, you are bringing the toys you could not reach into reaching distance. You are allowing the webpage to use the and subsequently the
That made sense in my head but I am stood from a bias stance so I hope that helped!
actually your expectation working as described except for the background property
take a look at this snippet it a prove that p element under body after positioned with negative integer :
html{
border: 20px solid green;
width: 250px
}
body {
padding:0;
margin:0;
width: 200px;
border: 20px solid orange;
overflow: hidden;
background:red;
}
p {
position: relative;
z-index: -1;
background: yellow;
}
<p>helllllllllllllllllllllllllllllllllllllllllllo</p>
so we can now exclude z-index from reasons
and It looks like a weird behavior on background-color property
I think it's better to read about it by following this links :
https://css-tricks.com/just-one-of-those-weird-things-about-css-background-on-body/
Giving background-color to body applying whole page. Why?

How can you make an iframe have pointer-events: none; but not on a div inside that?

I have an iframe with an inherited pointer-events: none; but when I have inserted a <div> inside the iframe with a pointer-events: auto; the div won't react to clicks or any mouse hover events.
The reason for this is that the iframe is inside a <div style="position:fixed;">
so it is kind of like a little menu. but I would like the user to click through the iframe, but not through the links and divs in the iframe.
And yes, it absolutely needs to remain an iframe.
How could I bypass this? Can I even bypass this?
Here's a simple example: jsfiddle.net/MarcGuiselin/yLo119sw/2
You're working with position:absolute, according to the example you've uploaded on jsfiddle... Adding a z-index to the "you can't click me because i'm behind the iframe" button allows me to click it.
Z-Index
EDIT: If you want to do a pointer-events: none; everywhere except in one div, you can add the pointer-events in each element instead of the iframe. According to your example in the fiddle, if you want to save the Nicholas Cage but block the other events, you can do something like this:
switchbutton.onclick=function(){
this.innerHTML="reload to reset";
//iframe.style.pointerEvents="none";
cantclick.innerHTML="You can click me now! :)";
iframe.contentDocument.body.innerHTML="<button>You can't click me now because my parent iframe is click-through! :(</button><br>or save this gorgeous image of your favorite actor which may or may not be relavant to the problem.<br><img id='nicholasCage' src='http://media2.popsugar-assets.com/files/2014/01/06/008/n/1922283/131b4126c7b8738f_thumb_temp_image333458751389045360.jpg.xxxlarge/i/Best-Nicolas-Cage-Memes.jpg'/>";
var iframeBody = iframe.contentDocument,
elements = iframeBody.querySelectorAll("*"),
i,
len = elements.length;
for(i=0;i<len;i++){
elements[i].style.pointerEvents="none";
}
iframeBody.getElementById("nicholasCage").style.pointerEvents="all";
}
If you can use jQuery you can do it faster just using $("iframe *").css("pointer-events","none");
What we want is not allowed by the spec, at least not with an absolutely positioned iframe.
We're all wanting to do the same thing:
Render a container (typically for a Chrome extension), positioned over the page and filling the viewport
Disallow not allow the container itself from capturing pointer events
Allow the container's children to capture pointer events
This lets us "click through" the absolutely positioned box, but still interact with its children, which may be buttons or just boxes with hover events or whatever.
We can achieve this behavior if and only if the boxes share the same document. Disabling pointer events for an absolutely positioned iframe disables them for all of its children.
An alternative approach is rendering the content directly into the document, i.e. into a Shadow DOM for styles sandboxing. This is the only way to achieve this behavior as we are looking for it, and was how I previously approached the problem before trying to refactor to an iframe and finding it can't be replicated this way.
See https://iframe-pointer-events.vercel.app for a demo.
I've searched a lot and figured out a workaround myself.
// the iframe element
const frame = document.getElementsByTagName("iframe")[0];
frame.onload = function () {
const frameDocument = frame.contentDocument;
document.addEventListener("mousemove", onMouseMove, true);
frameDocument.addEventListener("mousemove", onMouseMove, true);
function onMouseMove(e) {
let coord;
if (e.currentTarget === document) {
coord = {
x: e.pageX - frame.offsetLeft,
y: e.pageY - frame.offsetTop,
};
} else {
coord = { x: e.clientX, y: e.clientY };
}
const el = frameDocument.elementFromPoint(coord.x, coord.y);
// you can compare to your own element if needed
frame.style.pointerEvents = !el || el === frameDocument.body ? "none" : "auto";
}
};
The iframe will auto toggle its pointer-events and all events just works seamlessly.
There's no way you can do it, since it would be another security issue along with clickjacking.
Styles inside iframe don't cooperate in any way with styles inside of host site. So if you even set z-index/pointer-events or something else on iframe and would try to override the rule inside of it, it won't apply to host site rules in any way.
So what's the solution?
You have to split your iframe into multiple ones, and tinker with theirs position.
Have you tried this?
pointer-events: inherit;
I know you already got your answer, but I thought this might work, too.
Don't give the whole iframe pointer-events: none. Just inside the iframe put a CSS rule body * { pointer-events: none;}
This way the iframe does not block events, however elements inside the iframe are not clickable.

Always visible div while scrolling

On my aspx page, I have two left and right portions. I want to show always left side (which is actually a 'div' containig treeview) while scrolling the right side (which are actual contents of page). Thanks
You need to put position: fixed; on the div element. That will anchor it to the viewport.
Hi I found the best solution! As always JQUERY saving my life !!
Just put a Div called as you wan, I've chosen the same in the example below: #scrollingDiv.
<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script>
$().ready(function() {
var $scrollingDiv = $("#scrollingDiv");
$(window).scroll(function(){
$scrollingDiv
.stop()
.animate({"marginTop": ($(window).scrollTop() )}, "slow" );
});
});
</script>
I took that code from a website, it works and it's pretty easy to understand.
Fast forward to 2020, and it is now possible to do this with CSS.
<div style="position: sticky; top: 0;"> Tree view </div>
The user npas explains this quite nicely:
top is the distance to the viewport top the div should stay at when you scroll. Specifying top is mandatory. (…)
The sticky div will act like a normal div in all ways except when you scroll past it, then it will stick to the top of the browser.
Here's a jsfiddle to give you an idea.
MDN documentation
Supported by all modern browsers
You need to set the position of the div to Fixed in CSS. See this link for more information. You will need to set position using the top and left in css as well so it knows where to fix it!
The problem is that when the block moves, it gets attention and ability to concentrate on reading.
To remedy this using this function.
This code is perfect :
(change "220" and "46px" if necessary)
var $scrollingDiv = $("#scrollingDiv");
$(window).scroll(function(){
if ($(window).scrollTop()>220) {
$scrollingDiv
.css("position",'fixed' )
.css("top",'46px' )
} else {
$scrollingDiv
.css("position",'' )
.css("top",'' )
}
});

link to anchor near bottom of page

I'm doing some documentation where I make heavy use of anchors for linking between pages on a wiki.
see here:
http://code.google.com/p/xcmetadataservicestoolkit/wiki/ServicesExplained#Platform_Data_Structures
The feature that really makes this work well is when the browser shows the anchor at the absolute top of the pane. When it gets confusing is when linking to an anchor shows the anchor half-way down the page since the page is scrolled down all the way
see here:
http://code.google.com/p/xcmetadataservicestoolkit/source/browse/trunk/mst-common/src/java/xc/mst/utils/Util.java#227
My solution in the wiki (first link) was to put a blank image at the bottom of the page simply to make the browser show the anchor right at the top. Is there a better way to do this? Is there a way to do it in the second link (in which I can't add a blank image)?
Putting a blank image at the bottom of your page is a bad idea, since it will expand your document to a unnecessary height.
You could throw in some javascript to apply an effect to the anchor you just travelled to, to highlight it wherever it is.
Without altering the height of your document (i.e. adding extra padding at bottom), you'll always have this issue.
However, using bit of JS/jQuery, the user experience can be improved considerably:
On clicking a named anchor:
Instead of jumping in a flash (broswer's default behavior), add a smooth scroll
add an highlight to indicate current selection (this helps tremendously in 2nd case as the user can clearly see what is current)
Created a demo to illustrate the concepts: http://jsfiddle.net/mrchief/PYsyN/9/
CSS
<style>
.current { font-weight: bold; }
</style>
JS
function smoothScroll(elemId) {
// remove existing highlights
$('.current').css({backgroundColor: "transparent"}).removeClass('current');
var top = $(elemId).offset().top;
// do a smooth scroll
$('html, body').animate({scrollTop:top}, 500, function(){
// add an highlight
$(elemId).animate({backgroundColor: "#68BFEF" }, 500, function () {
// keep tab of current so that style can be reset later
$(elemId).addClass('current');
});
});
}
// when landing directly
if (document.location.hash) {
smoothScroll(document.location.hash);
}
$('a[href*="#"]').click(function() {
// utilizing the fact that named anchor has a corresponding id element
var elemId = $(this).attr('href');
smoothScroll(elemId);
});
You can create a absolutre positioned pseudo-element with a great height to targeted block using just the following CSS (for the second link in your post:
#nums td:target a::before {
content: '';
position: absolute;
height: 700px;
}
The height must be around the height of the viewport, so the best solution is to create these styles on the fly using js. But if you don't wan't to use js, just use height: 1000px or more — if you don't mind a gap at the bottom of course.
The best part: it's only CSS and there would be no gap when no anchors are targeted.
Edit: just a sneak peek into the future: if the vw/vh units would come to other browsers (now it's only in IE9), this could be awesomely done with just CSS using height: 100vh :)
You could use Javascript / jQuery to create a white div that has the necessary height needed to put your element at the top of the browser window, and you could even remove this upon scrolling away.
However I would highly recommend against doing so as this will expand your page where it isn't needed. It's a lot smarter to simply style the tag upon going there (through Javascript / jQuery) so it pops out to the viewer, for instance by setting the font-weight to bold or changing the background-color.
I would probably use a combination of jQuery and PHP for this:
PHP(somewhere right after your <body> element):
<?php
$anchor = explode('#', $_SERVER['REQUEST_URI']);
$anchor = $anchor[1];
echo '<div id="selected-anchor" anchor="'.$anchor.'"></div>';
?>
And then the jQuery:
<script type="text/javascript">
$(function(){
$('#selected-anchor').css('background-color', '[Whatever highlight color you want]');
});
</script>
Hope this helps.

Printing Scrolled Divs

I have a web page that displays a long line graph inside a div with overflow-x: scroll.
This works well as a web page allowing the use to scroll back and forward through the graph.
However, when printing the page the scroll position is reset to zero.
Is there a way to overcome this?
I think you're going to have to specify an alternate CSS for printing where you somehow need to remove the overflow:
<link rel="stylesheet" type="text/css” href="sheet.css" media="print" />
However, maybe there is an approach with JavaScript or even Flash? If I understand correctly, you only want to have a part of the graph printed (the one "selected" by the user?) and not the full one? I'm pretty sure that's not possible with plain HTML/CSS, but I strongly believe that Flash or maybe JavaScript/AJAX (to only load a part of the image at a time) can solve it.
You can't do this in plain CSS -- you will have to reimplement the scrolling using your Javascript UI library of choice to get what you want.
The user state of the scrollbar isn't used when printing (think about it, if you're scrolled 3 screens down a page and hit "print" does it make sense for the browser to only print the part of the document that's in your window at the time?). However, if you use JS, which actually manipulates the DOM (i.e. sets the x-position offset to -293 if the person has scrolled right 293 pixels, just like style="left: -293px; overflow: hidden;" in CSS), then it will show up as such in printed documents.
My suggestion is, unless the graphs are very wide, just skip all of this nonsense and use a printer stylesheet with width: 100% for the graph's <div> so the graph just shrinks to page width.
A simple approach would be to have some javascript which posts back to your page with the user's selected scroll position on a link saying something like 'setup for printing'. Then the server side returns a page with the graph relatively positioned at the scroll position with overflow:hidden to clip the graph appropriately.
Of course this would not work for users with javascript disabled - if you want to support this you would need the user to specify the scroll position in something like a text input element and submit button which you hid with javascript when enabled.
You need to temporarily turn the scroll position of the parent into a negative margin of the child, and put that parent as overflow:hidden.
Here's how to do it in Javascript (which is the only way, css cannot do that)
Note that you will need something to execute printDone() after the printing to restore everything as normal. You could trigger it with a wheel event e.g. because the user will only have a problem when trying to scroll. Or you can just put a button as I did, and show it only when printGo() is called.
<html>
<head>
<style>
#wrapper {
width:800px;
overflow-x:scroll;
}
#content {
width:2000px;
border:2px solid red;
}
#media print { /* This overwrites the css when printing */
#wrapper {
overflow-x:hidden;
}
}
</style>
</head>
<body>
Print<br>
I'm done printing!
<div id=wrapper>
<div id=content>
Hello this is my content.
</div>
</div>
<script>
var wrapper = document.getElementById('wrapper');
var content = document.getElementById('content');
var scrollPos;
function printGo(){
scrollPos = wrapper.scrollLeft; // Save scroll position
wrapper.scrollLeft = 0;
wrapper.style.overflowX = 'hidden'; // Optional since css does it
content.style.marginLeft = -scrollPos+'px'; // Put it as a negative margin of child instead
window.print();
}
function printDone(){
wrapper.scrollLeft = scrollPos; // Restore scroll position
wrapper.style.overflowX = 'scroll'; // Optional since css does it
content.style.marginLeft = '';
}
</script>
</body></html>