Covering full page on dragover - css

I got drag and drop to work nicely in my web application, but there is a problem I am not able to solve: I searched around and I found similar questions, also a few having referring to the opposite of my problem, but I wasn't able to understand what is going on.
The problem concerns the visual effect on dragover. On the dragover event, I add a dragging class which has a :before element, set in a way which should cover all the body, but as a matter of fact it only covers the viewport, so that if I scroll the window the rest of the body is not covered. Here is the CSS I used:
.dragging:before {
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 200;
background-color: rgba(0,0,0,0.2);
}
I also created a jsfiddle to demonstrate the problem; for the sake of simplicity, I bound the addition of the class to the click event. If you click on the yellow body it gets slightly darker; if you scroll down, you'll see the regular backgrund reappearing. In my application, I cannot click on the content of the page below the div, but if I scroll down I can click on the remaining content.
The "opposite" of my problem I mentioned above was that somebody wanted to a div to cover the viewport rather than the full body, and he was suggested to use 100vh rather than 100%, so I guess there is something I am missing...

There are two ways to do this.
a. The general case
Parent (i.e. .draggable):
{
position:relative
}
Child (i.e. .draggable::before):
{
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
It's general in the sense your parent can be any element, have any size. It works as long as there is no other intermediate positioned element between parent and child (where positioned means having a set position value other than default one - static; if such an element exists, it will become the parent/reference element).
b. The exception (the viewport)
Sometimes it makes more sense give the child the size of the viewport instead of the size of its closest positioned ancestor in DOM. In this case, all you need is to apply the following to child (and the parent will be the viewport):
{
position: fixed;
top: 0;
left: 0;
width; 100%;
height: 100%;
/* you could also use right:0; bottom:0;, as above
* you don't need to set width and height
* but, since it was present in your code, I used it
*/
}
Please note the viewport is not always the browser window. For example, 3d transformed elements act as viewports for their children.
In your case, the general case would be: https://jsfiddle.net/v7bu6czy/11/
$("body").click(function(event) {
event.preventDefault();
event.stopPropagation();
$("body").addClass('dragging');
console.log('using position:absolute (general solution), ::before height is: ' + window.getComputedStyle(document.querySelector('.dragging'), ':before').height)
});
body {
margin: 0;
}
.longdiv {
height: 3000px;
background-color: yellow;
}
.dragging {
position: relative;
}
.dragging:before {
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
z-index: 1;
background-color: rgba(0,0,0,0.2);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<head lang="en">
</head><body>
<div class="longdiv">
</div>
</body>
And the exception would be: https://jsfiddle.net/v7bu6czy/9/
$("body").click(function(event) {
event.preventDefault();
event.stopPropagation();
$("body").addClass('dragging');
console.log('using position:fixed, ::before height is: ' + window.getComputedStyle(document.querySelector('.dragging'), ':before').height)
});
html, body, document { height: 100%; margin: 0; }
.longdiv {
height: 3000px;
background-color: yellow;
}
.dragging:before {
content: "";
display: block;
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 200;
background-color: rgba(0,0,0,0.2);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<head lang="en">
</head><body>
<div class="longdiv">
</div>
</body>

Related

Why does the child element not stay at the bottom of a fixed parent?

Update: it's a Chrome-only bug, as Josh Crozier figured it out.
Resize the window vertically, to see why the code below does not work. The child element does not stay at the bottom of the parent. Why?
header {
background: red;
height: 50%;
left: 0;
position: fixed;
width: 300px;
}
header div {
bottom: 0;
position: absolute;
}
<header>
<div>Lorem</div>
</header>
This is currently a Chrome bug (as of version 47 and maybe earlier versions).
It only seems to apply to elements with fixed positioning. The issue is that the elements are repainted/rending incorrectly when resizing or scrolling. It's worth pointing out that the elements are definitely repainted/rendered, but it seems like they are rendered relative to their initial position when the DOM loaded.
This behavior is likely related to issues 454216, 153738, and 20574.
One work-around would be to wrap the element and absolutely position it relative to the parent element with the same height as the header ancestor element:
header {
height: 50%;
left: 0;
position: fixed;
width: 100%;
}
header .wrapper {
background: red;
height: 100%;
width: 300px;
position: relative;
}
header .wrapper > div {
bottom: 0;
position: absolute;
}
<header>
<div class="wrapper">
<div>Lorem</div>
</div>
</header>
Because <h1> has its own margin. Try
header h1 {
bottom: 0;
position: absolute;
margin-bottom: 0;
}

z-index for child elements higher than that of the parent div

I have a parent div which has its position as fixed. What i'm trying to do is to get the child div1 to stand out when I blur the page but the entire parent div stands out. After having read a lot of posts which said that the parent div overrides the z-index and the child's z-index has no meaning, I'm stuck here not knowing how to make this work.
If not getting this to work, can anyone help me with a solution for this?
This is easily achievable when you don't actually contain the intended children in the parent element, but instead fake hierarchy visually while keeping the DOM layout flat. A sample is built below:
http://jsfiddle.net/4KLRU/1/
HTML:
<div id="container">
<div class="child">Something</div>
<div class="child behind_parent">Something else</div>
<div class="child">Something else entirely</div>
<div id="parent"></div>
</div>
Notice that the parent element isn't actually around the so-called children elements.
CSS:
#container {
position: fixed;
padding: 10px;
}
#parent {
background: orange;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1;
}
.child {
position: relative;
background: red;
margin: 5px;
z-index: 2;
}
.behind_parent {
z-index: 0;
}
Without knowing exactly what your markup looks like, you could try the following approach:
#parent {
position: fixed;
...
}
#child {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
...
}

Hover on multiple concurrent DIVs

I am messing around with some navigation for a site and I want three images floating on the right of the screen (which I have). I then want to be able to hover over one of the images and have a menu pop-up next to that image. I can do this with one, but as soon as I introduce the next image in the vertical sequence, the first one stops working. Why?
My HTML:
<DIV id="parent"><img src = "images/parent.png"></DIV>
<DIV id="student"><img src = "images/student.png"></DIV>
<DIV id="teacher"><img src = "images/staff.jpg"></DIV>
<DIV id="pnavi"> <img src = "images/parent.png"></DIV>
My CSS:
#parent {
width: 50px;
position: fixed;
top: 20px;
right: 0;
z-index: 1;
}
#student {
width: 50px;
position: fixed;
top: 70px;
right: 0;
z-index: 1;
}
#teacher {
width: 50px;
position: fixed;
top: 120px;
right: 0;
z-index: 1;
}
#parent:hover + #pnavi {
visibility: visible;
}
#pnavi {
position: fixed;
float: right;
width: 100px;
height: 50px;
top: 20px;
right: 0px;
z-index: 1;
visibility: hidden;
}
If I comment out the student and teacher DIV, hover on parent shows #pnavi. Remove the comment (or even add a break after the DIV) and it all stops.
Fiddle is here
I have the second two DIVs currently commented out so that the hover works (first time using Fiddle so I hope I did it right..).
When you use + (direct adjacent combinator), the elements on each side must be adjacent siblings. So, on your case, #pnavi must be right after #parent on the markup (and, by consequence, on the DOM).
There is also an indirect adjacent combinator, ~, that only requires the elements to be siblings, but not directly next to each other. So you might use #parent:hover ~ #pnavi. I'm not sure about browser support, though. It works in Chrome on my mac. See demo.

div height and width 100% follows page screen size not the element size inside

I have
<div id=overlay>
<div></div>
</div>
the height and width of the outer div is set to 100%.
What happens here is, the 100% refers to the size of the element inside (inside div).
I have a dynamically changing element on inside div, and I wanted to be my outer div got the size of the page screen.
NOTE that these div (outer and inside) are a popup element. So I wanted to cover all other elements behind the popup that's why I need the 100% of the page behind.
this is my css for the outer div
#overlay {
visibility: hidden;
position: absolute;
left: 0px;
top: 0px;
width:100%;
height:100%;
min-height: 100%;
min-width: 100%;
height: auto !important;
width: auto !important;
text-align:center;
z-index: 1000;
background-image:url(template/popup-bg.png);
}
my js
function overlay(e)
{
el = document.getElementById("overlay");
el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";
}
Simply change the HTML to this
<div id='overlay' class='hideOverlay'>
<div></div>
</div>
Now on clicking simply change the class.
Change your js to this
function overlay(e)
{
$('#overlay').attr('class', 'showOverlay');
}
Check the following style
.showOverlay
{
background-color: red;
height: 100%;
left: 0;
top: 0;
opacity: 0.2;
position: fixed;
width: 100%;
z-index: 1001;
}
.hideOverlay
{
display:none;
}
Background-color is given just to check the div's visibility. Change it as per your choice.
It is nice to have some opacity for overlays to have a better look and feel effect.
Try to set:
position: absolute;
Something like this...
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;

CSS property width: 100%; make a page longer

I have a totally simple layout, in the page is only a silver background and the red DIV, as is possible to see on the image below. My problem is, that when I add the red DIV into my layout page, the page is longer on the length than 100% (bottom on the right corner - slider). Where could be a problem that caused this?
The CSS properties of the red DIV are:
html, body {
background-color: silver;
margin: 0;
padding: 0;
}
.red-div {
overflow: hidden;
width: 100%;
position: absolute;
top: 0;
left: 0;
}
.red-div {
overflow: hidden;
position: absolute;
top: 0;
left: 0;
right:0; /* This is what you need */
}
That way, you can force it to go to the end of the browser. When you do 100%, you do not account for the scrollbars. Which add the extra space and thus the annoying side-scroll

Resources