jQuery mouse enter/leave not correctly detecting hovering area - javascript

I looked around what I would like to achieve, but I wasn't able to find any suitable answer.
Basically I can't make the code to correctly detect mouse entering and leaving a div that is overlapping another div.
This is my current situation:
Working demo: http://jsfiddle.net/2f5xx73y/
HTML:
<div style='height: 100%; width: 100%;padding: 30%;'>
<div class='box'>
<div class='inner-box'>Merry xmas!</div>
</div>
<div class='box'>
<div class='inner-box'>Happy new year!</div>
</div>
</div>
CSS:
.box {
height: 100px;
width: 100px;
display: inline-block;
position: relative;
background-color: green;
}
.inner-box {
height: 100%;
width: 100%;
position: absolute;
opacity: 0;
z-index: 1;
}
.zoomed-inner-box {
height: 160%;
width: 160%;
top: -30%;
left: -30%;
position: absolute;
background-color: red;
z-index: 1;
}
JS:
$(".inner-box").mouseenter(function () {
$(this).attr("class", "zoomed-inner-box");
});
$(".inner-box").mouseleave(function () {
$(this).attr("class", "inner-box");
});
As you can see there are two boxes which become bigger when hovered overlapping the other box.
Going right to left everything works fine, in fact the red div goes away as soon as the mouse leave it. This doesn't happen in the opposite direction, where a mouseleave event it's fired as soon as the cursor enters the green div behind the red one, while I want the red div to go away when the mouse completely leave it.
I also tried using the :hover selector for the inner-box class but it has the exact same behaviour. Do you know a nice solution to this problem?

Just change the z-index on .zommed-inner-box to overwrite the .inner-box's z-index. That way the currently hovered box has a higher z-index than .inner-box :
.inner-box {
height: 100%;
width: 100%;
position: absolute;
opacity: 0;
z-index: 1; <---- original z-index
}
.zoomed-inner-box {
height: 160%;
width: 160%;
top: -30%;
left: -30%;
position: absolute;
background-color: red;
z-index: 2; <---- higher z-index
}
FIDDLE

Related

How to prevent get over other divs?

I have a problem...In the following example i don't want that the div who is fixed get over the div with the background red.
Here is the example:
http://jsfiddle.net/HFjU6/3645/
#fixedContainer
{
background-color:#ddd;
position: fixed;
width: 200px;
height: 100px;
left: 50%;
top: 0%;
margin-left: -100px; /*half the width*/
}
Alright, I think I get what the OP wants. He wanted a container that stays fixed on the top of the viewport, but remains confined by a parent. This behaviour is known as a conditional sticky behaviour, and is actually implemented in both Firefox (without vendor prefix) and macOS/iOS Safari (with -webkit- prefix): see position: sticky.
Therefore the easiest (but also the least cross-browser compatible) way is simply to modify your markup, such that the sticky element stays within a parent, and you declare position: sticky on it:
* {
margin: 0;
padding: 0;
}
#fixedContainer {
background-color: #ddd;
position: -webkit-sticky;
position: sticky;
width: 200px;
height: 100px;
left: 50%;
top: 0%;
transform: translate(-50%, 0); /* Negative left margins do not work with sticky */
}
#div1 {
height: 200px;
background-color: #bbb;
}
#div1 .content {
position: relative;
top: -100px; /* Top offset must be manually calculated */
}
#div2 {
height: 500px;
background-color: red;
}
<div id="div1">
<div id="fixedContainer">I am a sticky container that stays within the sticky parent</div>
<div class="content">Sticky parent</div></div>
<div id="div2">Just another element</div>
An alternative would be to use a JS-based solution. In this case, you do not actually have to modify your markup. I have changed the IDs for easier identification of the elements, however.
The gist of the logic is this:
When the scroll position does not exceed the bottom of the parent minus the outer height of the sticky content, then we do not do anything.
When the scroll position exceeds the bottom of the parent minus the outer height of the sticky content, we dynamically calculate the top position of the sticky content so that it remains visually in the parent.
$(function() {
$(window).scroll(function() {
var $c = $('#sticky-container'),
$s = $('#sticky-content'),
$t = $(this); // Short reference to window object
if ($t.scrollTop() > $c.outerHeight() - $s.outerHeight()) {
$s.css('top', $c.offset().top + $c.outerHeight() - $t.scrollTop() - $s.outerHeight());
} else {
$s.css('top', 0);
}
});
});
* {
margin: 0;
padding: 0;
}
div {
height: 500px;
background-color: red;
}
#sticky-container {
background-color: #bbb;
height: 200px;
}
#sticky-content {
background-color: #ddd;
position: fixed;
width: 200px;
height: 100px;
margin-left: -100px;
left: 50%;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="sticky-content">Sticky content that stays within the bounds of #div1</div>
<div id="sticky-container">Sticky confinement area</div>
<div>Other content</div>
Old answer before OP clarified the question appropriately:
Just give them the appropriate z-index values. In this case, you want to:
Do not use static positioning. This can be done by using position: relative for the large elements, in conjunction with the originally position: fixed element.
Assign the appropriate stacking order. The grey <div> element to have the lowest z-index, followed by the position fixed element, and then by the red element.
There are some catchalls to stacking though: the stacking context is reset when you traverse up or down the node tree. For example, the example will not work if the elements are not siblings.
Here is a proof-of-concept example, modified from your fiddle so that inline CSS is removed.
* {
margin: 0;
padding: 0;
}
#fixedContainer {
background-color: #ddd;
position: fixed;
width: 200px;
height: 100px;
left: 50%;
top: 0%;
margin-left: -100px;
z-index: 2;
}
#div1 {
height: 200px;
background-color: #bbb;
position: relative;
z-index: 1;
}
#div2 {
height: 500px;
background-color: red;
position: relative;
z-index: 3;
}
<div id="fixedContainer">z-index: 2</div>
<div id="div1">z-index: 1</div>
<div id="div2">z-index: 3</div>
Just give the z-index.
Hope it helps...
http://jsfiddle.net/HFjU6/1/#run
#fixedContainer {
background-color:#ddd;
position: fixed;
width: 200px;
height: 100px;
left: 50%;
top: 0%;
margin-left: -100px; /*half the width*/
z-index: 2;
}
.div-red {
position: relative;
z-index: 5;
}
<div id="fixedContainer"></div>
<div style="height:200px;background-color:#bbb;"></div>
<div style="height:500px;background-color:red;" class="div-red"></div>

Overlay the Contents of a DIV

I am trying to overlay 2 DIV's in my main parent DIV:
I want to overlay the the second div over on top of the first one. I have a problem overlaying it as I cannot keep it in the middle of the screen.
I have tried this to overlay:
The overlay works fine here, but my container is no longer center when I do this. How can I overlay and keep it center ?
div {
border: 5px solid red;
}
#first {
position: absolute;
z-index: 1;
border-color: orange;
}
#second {
position: absolute;
z-index: 2;
border-color: green;
}
<div id="container" class="container text-center">
<div id="first">Hi</div>
<div id="second">Hello</div>
</div>
Here is what you need to do (see width of both divs and text-align properties):
You can give them background color to see z-index works perfectly :)
#first {
text-align: center;
height: 300px;
width: 100%;
position: absolute;
z-index: 1;
}
#second {
text-align: center;
height: 300px;
width: 100%;
position: absolute;
z-index: 2;
}
<div id="container" class="container text-center">
<div id="first">Hi</div>
<div id="second">Hello</div>
</div>
When you position absolute, the positioned element is taken out of the document flow and positioned relative to the next highest parent element that is not the default position, i.e. not position: static;
The following will cause the absolute positioned children to stay within the containing div:
#container {
position: relative;
}
Your container's text is no longer centered because you have removed its children from the document flow. In essence, it has no content and collapses, and therefore, has no width to which to align the text.
One thing you could do is set the container to position: relative and full-width (i.e. width: 100vw), then set its children to width: 100%.
Then the inner divs will take on the width of their parent.
See this working JSFiddle.
#container {
position: relative;
width: 100%;
height: 100px;
background-color: yellow;
display: flex;
justify-content: center;
align-items: center;
}
#first{
position: absolute;
}
#second{
position: absolute;
}
<div id="container" class="container">
<div id="first">Hi</div>
<div id="second">Hello</div>
</div>
Your main issue is that the divs will not have any relative width to the parent div.
Therefore the text is still technically "centered" in each corresponding div because they're inheriting text-align: center from the container div.
However, the divs' widths will automatically be as wide as they needs to be (i.e. to fit the text, in this case).
You can remedy this one of two ways:
Force the divs to be centered
Give both divs the following (extra) CSS:
left: 50%;
width: 100%;
margin-left: -50%;
This will literally center them in their parent div.
or
Force the divs to be the same size as their parent
Give both the divs the following (extra) CSS:
top: 0;
bottom: 0;
left: 0;
right: 0;
This sets the divs to span their entire parent's height and width.
In both situations, you might need to make the .container class use position: relative, in order for the child divs to have something to be absolute to.
If you're using Bootstrap, there is no need to worry about this, as .container class already has this applied.
Hope one of these solutions helps you :)
Try this style:
#first,
#second {
left: 50%;
transform: translate(-50%, 0);
}
div {
border: 5px solid red;
}
#first {
position: absolute;
z-index: 1;
border-color: orange;
}
#second {
position: absolute;
z-index: 2;
border-color: green;
}
#first,
#second {
left: 50%;
transform: translate(-50%, 0);
}
<div id="container" class="container text-center">
<div id="first">Hi</div>
<div id="second">Hello</div>
</div>

Put a fixed div outside a draggable div (draggable.js)

Im working around with the draggable.js and I am trying to let some text appear that is connected to the dragged DIV…
So, this works fine, but I want to let the specific text appear in the left-top corner of the browsers window, I tried to give it a position:fixed, but it always stays in the dragged DIV.
I tought it would be the .ui-draggable class that ist added to my .text DIV, but it was not!
<div class="drag axis" id="item_1"><div class="text">Some Text</div></div>
<div class="drag axis" id="item_2"><div class="text">Another Text</div></div>
CSS:
.text {
display: none;
position:fixed;
top: 40px;
left: 40px;}
#item_1 {
position: absolute;
top: 100px;
left: 50%;
width: 500px;
height: 100px;
background-color: blue;
z-index: 0;
cursor: pointer;}
#item_2 {
position: absolute;
top: 125px;
left: 30%;
width: 500px;
height: 200px;
background-color: red;
z-index: 0;
cursor: pointer;}
See my JS Fiddle to understand my problem better:
https://jsfiddle.net/7bzvvpjL/4/
As i said, the text should always appear fixed, 40px, 40px, of the window and not inside the dragged div.
What am I doing wrong, does anybody have an idea?
The problem is that the text position is inside the absolute positioned div.
I slightly modified your code to show how it could work (even there are several solutions). What you need to do is moving your text-divs.
HTML:
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<div class="drag axis" id="item_1"></div><label for="item_1" class="text">Some Text</label>
<div class="drag axis" id="item_2"></div><label for="item_2" class="text">Another Text</label>
CSS:
.text {
position: fixed;
display: none;
top: 40px;
left: 40px;
}
modofoed scripts:
start: function( event, ui ) {
$(this).addClass('color');
//TODO: check if this.id == text.for or find by for property before fadingin
$(".text").fadeIn("slow");//.css('position','fixed');
},
stop: function( event, ui ) {
$(this).removeClass('color');
//TODO (not necessary): check if this.id == text.for or find by for property
$(".text").fadeOut("slow");
},
fiddle: https://jsfiddle.net/7bzvvpjL/7/
…i found a solution in putting the .text div outside the .drag div…
and then writing in the JS
$(this).next(".text").fadeIn("slow");

How can I use toggle("slide") to show a phrase one letter at a time

I am using a `.toggle("slide") function to try and get a piece of text I have to appear as if each letter is sliding in. Unfortunately, it looks as if the text is flying in instead. I tried to squeeze the margins in tight, so that it would start at a closer place, but it still looks as if it is flying in from the left side.
Is there a better way to do this, so it looks as if the letters are sliding in without "flying in"?
$("#home-learn").toggle("slide");
#blue {
background-color: #0085A1;
width: 100%;
height: 300px;
}
#home-learn {
color: #FFF;
display: none;
text-align: center;
position: relative;
margin: 0 40%;
top: 50%;
font-size: 2.3em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="blue">
<div id="home-learn">Learn more...</div>
</div>
For the effect you want, put a div inside your container. Make the div position absolute, make it 100% the height and width of the container, and make it the same background color as the main background. Make the div's z index higher than the container so the div sits over the text like a curtain. Then use toggle() to slide the curtain to the right exposing the text underneath.
Note that this uses jQuery UI, without it, you can't make toggle() slide to the right like this needs.(at least to my knowledge you cant). If you dont want to use jquery UI, you could use .animate() instead of toggle()
$("#curtain-div").toggle("slide", {
direction: "right"
}, 3000);
#blue {
background-color: #0085A1;
position: relative;
width: 100%;
height: 300px;
}
#home-learn {
color: #FFF;
text-align: center;
position: relative;
top: 50%;
font-size: 2.3em;
}
#curtain-div {
width: 100%;
height: 100%;
position: absolute;
background-color: #0085A1;
top: 0;
left: 0;
z-index: 10;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<div id="blue">
<div id="home-learn">
<div id="curtain-div"></div>
Learn more...
</div>
</div>

.toggleClass not toggling a certain class, but is working on all others

So I have a page on my website that has some navigation elements that stick on the page when the user scrolls past a certain point. There are three of them, one on the top, one on the left, and one on the right. HTML and CSS is as follows:
<div id="nav" class="nav">
<!--STUFF CONTAINED IN TOP NAV BAR-->
</div>
<div class="right" id="right">
<!--STUFF CONTAINED IN RIGHT NAV-->
</div>
<div class="left" id="left">
<!--STUFF CONTAINED IN LEFT NAV BAR-->
</div>
.nav {
position: absolute;
top: 108px;
height: 45px;
width: 100%;
left: 0;
right: 0;
}
.nav_sticky {
position: fixed;
top: 0;
height: 45px;
left: 0;
right: 0;
background-image: url(images/backgrounds/stardust_#2X.png);
z-index: 10;
}
.right {
width: 200px;
height: 900px;
position: absolute;
right: 50%;
margin-right: -538px;
top: 153px;
}
.right_sticky {
width: 200px;
height: 900px;
position: fixed;
right: 50%;
margin-right: -538px;
top: 45px;
}
.left {
width: 200px;
height: 900px;
position: absolute;
left: 50%;
margin-left: -538px;
top: 153px;
}
.left_stick {
width: 200px;
height: 900px;
position: fixed;
left: 50%;
margin-left: -538px;
top: 45px;
}
I then use the follow JQuery to cause these elements to stick.
<script>
$(document).ready(function(){
var navPos = $('#nav').offset().top;
$(window).scroll(function () {
var scrollTop = $(this).scrollTop();
if (scrollTop >= navPos) {
var classNamee = $('#nav').attr('class');
console.log(classNamee);
if (classNamee === "nav") {
$("#nav").toggleClass('nav nav_sticky');
$("#right").toggleClass('right right_sticky');
$("#left").toggleClass('left left_stick');
}
}
if (scrollTop <= navPos) {
var className = $('#nav').attr('class');
console.log(className);
if (className === "nav_sticky") {
$("#nav").toggleClass('nav_sticky nav');
$("#right").toggleClass('right_sticky right');
$("#left").toggleClass('left left_stick');
}
}
});
});
</script>
Here's my problem. This works perfectly for the top and right navs, however no matter what I try, the left nav continues to scroll when the others have stopped. I thought it may have been a typo in the css class, but when I looked in the inspector, the .toggleClass function doesn't even change the class on the #left element when it does on the other two. Any ideas as to what could be causing this?
If I copy/paste your sample code as-is to jsFiddle and run it, when you scroll down far enough, it does correctly toggle everything to *_sticky classes, but something about the negative margin-right on the right class element seems to reset the scroll to the top (at least in Chrome) when it flips between .right and .right-stick. When the scroll gets reset, it also reruns your event handeler and changes all the classes back.
Try removing these lines from your CSS and see if the behavior works right (it does in Chrome in a jsFiddle)
.right {
...
/*margin-right: -538px;*/
.right-stick {
...
/*margin-right: -538px;*/

Categories

Resources