Element position is being changed on hover - javascript

I have a div with a text. I want to create a yellow circle background when hovering the div instead of the cursor.
Here is what I got so far: JsFiddle Demo
HTML:
<div id="board">
<div id="ball"></div>
Lorem ipsum dolor sit....
</div>
JQuery:
$(function(){
$("#board").mousemove(function(e){
var ball = $("#ball");
var ballRadius = parseInt(ball.css("width"))/2;
var parentOffset = $(this).offset();
var relX = e.pageX - parentOffset.left - ballRadius;
var relY = e.pageY - parentOffset.top - ballRadius;
ball.css("top",relY + "px");
ball.css("left",relX + "px");
ball.css("display","inline-block");
});
});
I manage to do it, but, when hovering, all my text is being shifted.

Add position: relative to the #board and change #ball from position: relative to position: absolute.

The issue is your positioning. DEMO
#board{
position:relative;
#ball{
position: absolute;
The reason is that relative positioning just lets you moving things around with top and left but the element still effects the layout and positioning of its siblings. Position, absolute ultimately does the same thing, but it removes that element from the layout, so it does not effect any of its siblings or other's positioning.
The other thing both relative and absolute positioning do is they make the element an offsetParent. In other words other absolute or relatively positioned elements contained within will be positioned based on that element. Because of this you need to make the #board either relative or absolute, so that the positioning of #ball will be based on #board.
PS. When storing references to a jQuery object var ball = $('#ball); its considered a good practice to put a $ on your variable. So... var $ball = $('#ball);. That way other developers can easily tell what variables are actually jQuery objects.

You will want to set both the ball and the boards position to absolute
#board{
position:absolute;
margin: 0 auto;
margin-top: 50px;
padding: 15px;
width: 500px;
height: 300px;
border: 1px solid black;
overflow: hidden;
cursor: none;
font-size: 20px;
}
#ball{
position: absolute;
width: 40px;
height: 40px;
background-color: yellow;
border-radius: 100%;
top: -50px;
left: -50px;
display: none;
z-index: -1;
/* transition: all 0.1s;
-webkit-transition: all 0.1s;*/
}
http://jsfiddle.net/Zt7h3/18/

I managed to change it up a bit.
http://jsfiddle.net/Zt7h3/19/
var relY = e.pageY - parentOffset.top - ballRadius - $(this).height();
I put the ball div at the bottom, and then subtract the height of the div to determine current Y.

Related

Video and z-index inside scaled element: some divs disappear

I have a somewhat strange behaviour in Chrome and Safari. I have a scaled (transform: scale()) container with a video and other elements inside of it. At some scalings the absolute positioned elements with a high z-index disappears and does not come back again.
How can I fix this?
Note that I cannot give the video element a negative z-index and I need to use overflow: hidden;.
Example
I have made an example that scales the outermost container up and down. At a specifik scale value the element with class .on-top (and text "I should always be on top.") disappears. When scaling down again it suddenly appears.
Link to exmaple: https://jsfiddle.net/iafiawik/Lcox1ecc/
Conclusions
It seems like the size of the element matters. The larger I make it, the larger is the scale value before it disappears.
I have also tested to set transform: scale(1.4) with CSS directly on the element and the behaviour is the same.
The issue does not exist if I:
Replace the video tag with a div
Remove position: absolute; from siblings to .on-top (that is, .below)
Remove overflow: hidden; from .content
If I move .on-top so it is placed after the video tag in the document flow
(But of course none of these workarounds work for me in reality because of project specific reasons. I also cannot give the video element a negative z-index and I need to use overflow: hidden;.)
Suggested workarounds from the community (thanks!)
Give the video tag a negative z-index (can't do this because I sometimes have elements placed behind the video)
Remove overflow: hidden; (I can't remove overflow: hidden;)
Browsers
I have seen this issue in Chrome (Mac) and Safari (Mac).
Update 1
Seems like this bug report pretty much covers my problem. However, it does not provide a fix for it.
Update 2
I've answered my own question by providing my solution to this problem.
Update 3
There are a lot of answers coming in that either modify the z-index of the video or adds translateZ to the .on-top element. Demos have shown that both of those approaches do fix the issue.
However, since my HTML structure is the output from a visual HTML editor (long story ...), I do not know what elements will be there or if they should be in front, below or next to a video. Therefore I am looking for a solution that does not require changes to individual elements that are inside the scaled element.
It looks like a bug in Chrome. Notice that when you scale the image, the element inspector keeps telling you that the size of #scaled is 1024x768:
Where as in Firefox:
Now, apparently, Chrome uses the wrong size to conclude that .on-top is completely outside .content and hides it because of hidden overflow (it should not be doing this but apparently it is trying to optimize away any element that displays above a video). Examples:
Scale: 1.225
Parent width: 1254.40
Child left: 1254.40 - (100 + 90) * 1.225 = 1021.65
Result: less than 1024 (partially inside)
Scale: 1.230
Parent width: 1259.52
Child left: 1259.52 - (100 + 90) * 1.230 = 1025.82
Result: greater than 1024 (completely outside)
Unfortunately I could not find an elegant solution. Ideally you should revise your HTML markup and CSS, perhaps align the top element with left edge. As a last resort, you can move the elements more towards left using transparent border:
var goalScale = 140;
var startScale = 100;
var currentScale = 100;
var shouldScaleUp = true;
var container = document.getElementById("scaled");
var scaleInfo = document.getElementById("scale-info");
function step() {
container.style.transform = "scale(" + (currentScale / 100) + ")";
scaleInfo.innerText = "Scale: " + (currentScale / 100);
if (currentScale === goalScale) {
shouldScaleUp = false;
}
if (currentScale === startScale) {
shouldScaleUp = true;
}
if (shouldScaleUp) {
currentScale += 0.5;
} else {
currentScale -= 0.5;
}
window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
.scale-info {
position: fixed;
left: 0;
top: 0;
}
#scaled {
background: #cccccc;
width: 1024px;
height: 768px;
position: fixed;
left: 200px;
top: 200px;
}
.content {
height: 100%;
overflow: hidden;
position: relative;
margin-left: auto;
margin-right: auto;
background: rgba(34, 34, 56, 0.2);
}
.below {
position: absolute;
width: 300px;
height: 300px;
right: 0px;
top: 100px;
background: purple;
z-index: 1;
opacity: 0.8;
}
.below-2 {
z-index: 3;
right: 100px;
}
.below-3 {
z-index: 4;
right: 400px;
}
.on-top {
position: absolute;
width: 50px;
right: 100px;
top: 150px;
background: pink;
z-index: 5;
padding: 20px;
/* a 200px border moves the element towards left */
border-left: 200px solid transparent;
background-clip: padding-box;
}
.on-top h1 {
font-size: 20px;
}
#video {
position: absolute;
z-index: 4;
width: 1024px;
height: 768px;
background: rgba(0, 0, 0, 0.4);
}
<div id="scale-info"></div>
<div id="scaled">
<div class="content">
<h2 class="below below-1"> I have z-index 1</h2>
<div class="on-top">
<h1> I should always be on top.<br> I have z-index 5</h1>
</div>
<h2 class="below below-2"> I have z-index 3</h2> <video id="video" src="https://www.w3schools.com/html/mov_bbb.mp4"></video>
<h2 class="below below-3"> I have z-index 4</h2>
</div>
</div>
Here you go: https://jsfiddle.net/Lcox1ecc/423/
You just need to add -webkit-transform: translateZ(0); to the .on-top class.
Happy Coding!
After spending a lot of time researching this problem and trying a lot of different approaches I've come to the conclusion that no solution fixes my problem. There are solutions that fix the problem if you are able to control the z-indexes of the elements that disappear, but I am unable to do so since the structure of the HTML is not known to be (it is the output of the HTML editor). I was looking for a solution that would not require changes to individual children to the scaled parent, but I have not found any so far.
This bug report pretty much covers my problem but it does not provide a fix for it.
I can confirm that this happens because the element is outside of the scaled containers original width and height:
The element is visible at scale(1.227) (red border indicates the original size of #scaled):
... but not at scale(1.228):
My solution is therefore to add another wrapping element outside the scaled element that is not scaled, but get its width and height properties updated according to its first child scale values. This element has overflow: hidden; and prevents elements from being visible.
This is not a perfect solution as one might experience a small gap between the scaled element and the outermost wrapping element (rounding issues), but it is the best I can do given the circumstances.
var goalScale = 140;
var startScale = 100;
var currentScale = 100;
var shouldScaleUp = true;
var container = document.getElementById("scaled");
var scaledContainer = document.getElementById("resized-container");
var scaleInfo = document.getElementById("scale-info");
function step() {
var contentWidth = 1024;
var contentHeight = 768;
container.style.transform = "scale(" + (currentScale / 100) + ")";
scaledContainer.style.width = contentWidth * ((currentScale / 100)) + "px";
scaledContainer.style.height = contentHeight * ((currentScale / 100)) + "px";
scaleInfo.innerText = "Scale: " + (currentScale / 100);
if (currentScale === goalScale) {
shouldScaleUp = false;
}
if (currentScale === startScale) {
shouldScaleUp = true;
}
if (shouldScaleUp) {
currentScale += 0.5;
} else {
currentScale -= 0.5;
}
window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
#resized-container {
position: fixed;
width: 1024px;
height: 768px;
overflow: hidden;
border: 10px solid red;
top: 200px;
left: 200px;
}
#scaled {
background: #cccccc;
width: 1024px;
height: 768px;
position: absolute;
transform-origin: left top;
}
.content {
height: 100%;
position: relative;
margin-left: auto;
margin-right: auto;
background: rgba(34, 34, 56, 0.2);
}
.below {
position: absolute;
width: 300px;
height: 300px;
right: 0px;
top: 100px;
background: purple;
z-index: 1;
opacity: 0.8;
}
.below-2 {
z-index: 3;
right: 100px;
}
.below-3 {
z-index: 4;
right: 400px;
}
.on-top {
position: absolute;
width: 50px;
right: -30px;
top: 150px;
background: pink;
z-index: 5;
padding: 20px;
}
.on-top h1 {
font-size: 20px;
}
#video {
position: absolute;
z-index: 4;
width: 1024px;
height: 768px;
background: rgba(0, 0, 0, 0.4);
}
<div id="resized-container">
<div id="scaled">
<div id="scale-info">
</div>
<div class="content">
<h2 class="below below-1">
I have z-index 1
</h2>
<div class="on-top">
<h1>
I should always be on top.<br /> I have z-index 5
</h1>
</div>
<h2 class="below below-2">
I have z-index 3
</h2>
<video id="video" src="https://www.w3schools.com/html/mov_bbb.mp4"></video>
<h2 class="below below-3">
I have z-index 4
</h2>
</div>
</div>
</div>
One approach, if you can modify a bit your html, is wrap your problematic elements in a container that is the same size as the video and container, with the proper z-index. That way you would have clear layers of the same size and positions, into which you can position more complex elements. Like this for example:
<div id="top-container">
<div class="on-top">
<h1>
I should always be on top.<br /> I have z-index 5
</h1>
</div>
</div>
#top-container {
width: 100%;
height: 100%;
position: absolute;
z-index: 5;
}
https://jsfiddle.net/06oykj8o/4/
I made this workaround by puttingz-index:-1; on video.
https://jsfiddle.net/Lcox1ecc/312/
I really like the answer from Salman A.
The only thing that comes to mind, would be rewriting with position: relative.
But I don't know if that is an option.
I stumbled across something similar to this last week with positioning absolute elements and transforms...
I dunno if this will help you out but here is a link.
CSS transform: translate moves postion:fixed inner Div
In the end I fixed it by using a transform: translateX(none) vs translateX(0).
Super strange behavior for sure, but the link gives some more links to help make things more clear - as in its behaving per spec.
It is happening because of overflow is hidden.Here is working link
https://jsfiddle.net/Lcox1ecc/322/
.content {
overflow:visible;
}
It might be late but just posting in case somebody finds it helpful.
Add an empty div under the parent container element with transform animation and nothing will disappear anymore. The animation does not do anything but it forces the browser to render all the elements using hardware acceleration.
<div class="emptydiv"></div>
.emptydiv{
transform:scale(1);
animation:fix 3s infinite;
}
#keyframes fix{
50%{
transform:scale(1);
}
}

How to add pixels to a current position of an element?

I want to move an image from its current position to the right, so I need to add pixels to the left position that it has right now.
I have a flex container in which I have an image and a div. Both of them are centered on the container with justify-content: center; property.
The problem I have is that when I try to move the image that has position absolute, it goes back until its nearest parent that has position relative (its container) and start to add pixels there and it makes a strange visual effect.
HTML code:
<button type="button" onclick="moveImage()">Move image</button>
<div id="container">
<div id="left" class="block">Left</div>
<div id="center" class="block">
<img id="image" src="https://appharbor.com/assets/images/stackoverflow-logo.png" alt="stackoverflow">
</div>
<div id="right" class="block">Right</div>
</div>
CSS code:
html, body{
width: 100%;
height: 100%;
}
#container{
display: flex;
height: 100%;
}
.block{
flex: 1;
}
#left{
background-color: red;
}
#center{
position: relative;
display: flex;
background-color: yellow;
justify-content: center;
}
#right{
background-color: orange;
}
#divCentered{
width: 50%;
height: 100px;
background-color: brown;
}
Javascript code:
$( document ).ready(function() {
var divParent = document.getElementById('center');
var div = document.createElement("div");
div.setAttribute("id", "divCentered");
divParent.appendChild(div);
});
function moveImage(){
$("#image").animate({
left: "+=300px"
}, 1000);
}
JSFiddle in which you can see how the image goes back until its parent and start adding pixels there.
Is there a way to avoid that the image back some pixels to its parent and start add pixels in its current position?
Thanks in advance!
Finally, after a lot of proves, I have got a workaround to get this.
I have to use .offset() property to get the container and the image left property taking as reference the document.
Then, I have to set the left property of the image to 0 because it would be positioned when the container is positioned on the left (as the container is the relative parent of the absolute image).
After that, just substract both values to get the differences between the offset of the container and the image to get the actual position of the image regard its container and set this value to the left property of the image.
Here is the code that I have added:
var leftCenterDiv = $("#center").offset().left;
var leftImage = $("#image").offset().left;
$("#image").css("left", 0);
$("#image").css("left", leftImage - leftCenterDiv);
And the updated JSFiddle.
Give the image an absolute horizontal position to start from:
#image {
position: absolute;
z-index: 2;
height: 50px;
width: 100px;
left: 45px;
}
Try to keep the image with initial position so that even adding the pixel it wont change i.e. left:45px. but when you add pixel to existing one and to avoid moving position can be done adding!important` to the left
#image {
position: absolute;
z-index: 2;
height: 50px;
width: 100px;
left: 45px !important;
}
Jsfiddle

How to make an absolute positioned div fill the entire document area

I need to have an absolute div that is a child of only body fill the entire document area (window + any scroll area)
-- width: 100% only fills the viewable screen
I prefer a CSS only solution but pure javascript is ok. I tried without success setting:
opaque.style.minHeight = Math.max(document.body.offsetHeight, document.body.scrollHeight);
I made a jsFiddle of the code below. If you scroll down the output, you will see that the opaque div stops at whatever height the output window was when it was rendered.
In case you are wondering... it is to make an opaque overlay of all content in the div behind it (think slideshow). My only other solution is to disable scrolling, but this is problematic.
Thanks for any help.
<div class="page-container"></div>
<div id="opaque"></div>
body {
width:100%;
}
.page-container {
position: relative;
max-width:978px;
width: 100%;
min-height:2500px;
margin:0 auto -50px auto;
border:solid #999;
border-width:2px;
background: lightblue;
}
#opaque {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
z-index: 100;
background: grey;
filter: alpha(opacity=70);
opacity: 0.7;
}
Can use
#opaque {
position: fixed;
top: 0;
left: 0;
right:0;
bottom:0;
}
remove width:100% from body due to creates horizontal scrollbar
Depending on use case it is often common to add class to body when using such an overlay that sets body overflow to hidden
DEMO
You can put a position: relative on your body so that the body will be used as a reference point by the child element in terms of height (as opposed to the document object).
Using javascript to set one elements height equal to anothers
var o = document.getElementById('opaque');
var p = document.querySelector('.page-container');
o.style.height = window.getComputedStyle(p).getPropertyValue("height");
FIDDLE

Tooltip moving with cursor

Image
ul#listcontainer .li1 {
display: block;
width: 210px;
height: 130px;
border: 1px solid red;
position: relative;
}
.li1 span {
position: absolute;
top: 140px;
left: 0px;
right: 0;
width: 220px;
padding: 2px 0;
background-color: #000;
background-color: rgba(0, 0, 0, 0.65);
color: #fff;
opacity: 0;
transition: opacity .5s ease-in-out;
text-align: center;
font-family: Arial;
font-size: 14px;
}
.li1:hover span {
opacity: 1;
}
.li1:hover span:hover {
opacity: 0;
}
<ul id="listcontainer">
<li class="li1">
<img src="images/li1.png"><span><b>Exteriors:</b> <br>Minimal Wear, Battle Scarred<br><br><img src="images/tick.png"><br> </span>
</li>
</ul>
Hello everyone. So I made a tooltip showing after I hover the box with red border. The thing I want is that when I hover over the div with red border - the tooltip begin to moving/following with the mouse. Tried to search how to do it but I didn't found answer. I think it will be some jQuery code... I let you guys tell me. Thanks.
Try this code and no need to change the css as shown in this http://jsfiddle.net/bo113jxu/8/ :
$('.li1').mousemove(function (e) {
$('span', this).css({left: e.pageX - 100, top: e.pageY + 10});
});
EDIT:
The position:absolute will work good as long as there's only one .li1 element, but in case we have more .li1 elements we'd face a problem shown in this jsfiddle demo1; TO fix this the position of .li1 should be set to fixed jsfiddle demo2.. just like what #ViktorMaksimov kudos said in his answer which I was wrong about it.
CSS code:
.li1 span {
position: fixed;
margin-left: -110px;
}
jQuery code:
$(document).ready(function() {
$('.li1').mousemove(function( event ) {
$(this).find('span').css({ //Position the tooltip
'left' : event.pageX + 'px', //Left position - the X position of the mouse
"top" : (event.pageY + 20) + 'px' //Top position - the Y position of the mouse
});
});
});
Firstly the tooltip should be positioned fixed.
When you are moving the mouse inside the <li> element the tooltip will have left position - the position on X of the mouse to the window, and top position the position on Y of the mouse + 20, because the tooltip not to be exactly next to the mouse, because if you move your mouse fast enough the tooltip will hide.
And we are setting margin-left to the tooltip - negative value half of its width to make the tooltip centered to the mouse.

How to find the center of the screen?

I have a div,I need to show this div on the center of the screen (ie viewable area) even while the user scrolled through the page.
so its style should be (for example)
{position:fixed; top:90px; left:150 px; z-index:9999; overflow:hidden;}
Now i need to find the value of left and top, so that the div will place in the center of the screen (ie viewable area), for any page .
How can i find the value of left & top with a javascript or jquery ?
left:50%; top:50%; puts you in the middle, then you apply a fixed width and height and set margin-top and margin-left to negative a half of that width and height.
In order to center something with fixed positioning then you will need to know the height and width of the element.
You then just need to margin-top and margin-left to negative half of the width and height in order to center it.
E.g. this class would center and element that has 100px height and 200px width.
.centered {
position: fixed;
top: 50%;
left: 50%;
margin-top: -50px;
margin-left: -100px;
}
http://css-tricks.com/quick-css-trick-how-to-center-an-object-exactly-in-the-center/
Update:
If you don't know the height and width of the element that needs to be centered ahead of page load then you'll need to use JavaScript to detect the size.
Here's a working example of how this can be done - http://jsfiddle.net/3Ag97/1/
You can use the flexbox module, although it's not widely supported yet: http://jsfiddle.net/b7nrS/.
.container {
display: flex;
align-items: center;
justify-content: center;
}
Try this:
var $box = $('#box');
var bw = $box.width() / 2;
var bh = $box.height() / 2;
var wh = $(window).height() / 2;
var ww = $(window).width() / 2;
$box.css({'left': ww-bw, "top": wh-bh})
http://jsfiddle.net/mqMwj/
function centerObject(selector) {
var x = $(window).height() - $(selector).height();
var y = $(window).width() - $(selector).width();
$(selector).css("left", y / 2).css("top", x / 2);
};
#divX {
position: fixed;
left: 50%;
top: 50%;
width: 100px;
height: 100px;
margin-left: -50px;
margin-top: -50px;
background-color: #0000FF;
}

Categories

Resources