Floating Div Crosshairs - Confine To Div - css

I'm trying to add a crosshair-style cursor effect to a div that contains a D3 Datamap. I've got it working using jQuery but the crosshairs seem to overlap their parent div on the bottom and right, but not the top and left.
I've created this fiddle to demonstrate.
I've tried changing the position property of the crosshair div to no avail.
On my page, changing position to absolute seems to correctly confine the crosshairs to the container, but the center point is offset from the cursor (e.pageX, e.pageY). However, I cannot recreate this in the fiddle, as fixed, static, relative, absolute make no difference.
One solution I've found is to set the width and height properties of the container and hairs to fixed values. However, I need the container to be responsive.

First, the vertical and horizontal lines also overlapping the box on the top and left, it was not visible because of the body-viewport ;).
Second, I did some investigation and found out that the best solution would be to place the crosshair-lines inside the map-container which are positioned absolute to the map-container. Therefore we have better control of the position and behavior of the crosshair-lines and the map-container can be flexible aswell!
I added the default cursor for better testing. — https://jsfiddle.net/9r4rtcz9/6/ – code snippet below
//Map Hover Crosshairs
$(function() {
var cH = $('#crosshair-h'),
cV = $('#crosshair-v');
$('.map_wrapper').on('mouseover', function() {
cH.css('visibility', 'visible');
cV.css('visibility', 'visible');
$('.map_wrapper').bind('mousemove', function(e) {
cH.css('top', e.pageY);
cV.css('left', e.pageX);
});
});
$('.map_wrapper').on('mouseout', function() {
cH.css('visibility', 'hidden');
cV.css('visibility', 'hidden');
$('.map_wrapper').unbind("mousemove");
});
});
.map_wrapper {
position: relative;
height: 100px;
width: 300px;
border: 1px solid black;
overflow: hidden;
cursor: default;
}
.hair {
float: left;
position: absolute;
background-color: rgba(100, 100, 100, 0.5);
z-index: 10;
pointer-events: none;
}
#crosshair-h {
width: 100%;
height: 2px;
margin-top: -8px;
visibility: visible;
}
#crosshair-v {
height: 100%;
width: 2px;
margin-left: -8px;
visibility: visible;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="map_wrapper">
<div class="hair" id="crosshair-h"></div>
<div class="hair" id="crosshair-v"></div>
</div>
<p class="datamaps">D3 Data Maps Here</p>

Related

Elements scroll one by one

I'm currently trying something out which i saw on another website.
Imagine many pictures at the same position at the bottom of the website. Now when you scroll up - it will scroll every picture one bye one up - when done you will get eventually to the footer.
I already tried position: sticky etc. but it did not worked as I wanted.
Can someone help me? I would be so happy!
.poster-middle {
width: 100%;
height: 100%;
top: 0;
position:-webkit-sticky;
position:sticky;
}
.poster-middle-img {
margin-top: 500px;
}
.poster-left {
width: 100%;
height: 100%;
top: 0;
position:-webkit-sticky;
position:sticky;
}
.poster-left-img {
margin-top: -700px;
}
.poster-right {
width: 100%;
height: 100%;
top: 0;
position:-webkit-sticky;
position:sticky;
}
.poster-right-img {
margin-top: -700px;
}
<div class="poster-middle"><div class="poster-middle-img"><img src="img/1.jpg"></div></div>
<div class="poster-left"><div class="poster-left-img"><img src="img/2.jpg"></div></div>
<div class="poster-right"><div class="poster-right-img"><img src="img/3.jpg"></div></div>
right now everything is scrolling up together
You can achive this with pure css.
The trick is to use the sticky attribute of the position property and define the bottom property. This way all images are sticking to the bottom of the page. If the value of the bottom property is less than the image height, the top of all the images are visible all the time. The images below the first one are outside of view (technically) but will be visible because of the sticky attribute. Margin-bottom defines the margin between the images.
When the user starts scrolling, one image after the other is scolling into the view and is released from the position at the bottom and will scroll freely to the top.
position: -webkit-sticky;
position: sticky;
bottom: -200px;
margin-bottom: 300px;
The rest is normal positioning.
I created a little fiddle to show a full example. You can build your solution from there very easily.
I said CSS only, but used javascript in the fiddle. The code is only to give all elements a z-index. You can do this when generating the page or with nth-child in the css. But I didn't want to do that. Call it laziness ;)
You can use jquery to do this
var src = ['url_image1.jpg', 'url_imafe2.jpg'];. // Array of source of images
var i = 0;
$(document).ready(function() {
$(window).bind('mousewheel',function() {
$('#imgs').hide().delay(1000).fadeIn();
if (i==1){
$('#imgs').attr('src', src[i]);
i=0;
}
else {
$('#imgs').attr('src', src[i]);
i=1;
}
});
});
<style>
div{height:500px}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<img id="imgs" style="display: none;margin-left: 100px;margin-top: -150px; position: relative" src="https://i.ytimg.com/vi/vl8IxeB0ss4/maxresdefault.jpg">
</div>

how do I get pixel values or windows x/y positions to style accordingly to those coordinates?

How can I get an element to change it's style according to my mouse position in that element during a hover?
For example:
If I hover my mouse on the top-left part (maybe 20% from top and 20% left) of the div, I would like to apply style A on this div but if I hover on the bottom-right part (maybe 20% from bottom and 20% from right) of the div I would like to apply style B instead.
The main question is:
How do I get those
20% from top and 20% left
20% from bottom and 20% from right
coordinates to use with div:hover selector?
For the solutions below, let's say we have an element with 400px of width and 300px of height.
<div class="element"></div>
.element {
height: 300px;
width: 400px;
background: #333;
}
Solution 1: with CSS only
Solving the example you gave, we have to wrap the div in a container element with two spans before the div as auxiliary elements.
<div class="container">
<span class="left-top-20"></span>
<span class="right-bottom-20"></span>
<div class="element"></div>
</div>
Then, we position the <span> elements in the corners. For this we set position: relative to the container and position: absolute to the spans and top, right, bottom and left properties.
Finally, hovering the spans will affect the .element style using general sibling selector ~;
.container {
display: inline-block;
position: relative;
}
.container span {
width: 20%;
height: 20%;
position: absolute;
}
.left-top-20 {
left: 0;
top: 0;
}
.right-bottom-20 {
right: 0;
bottom: 0;
}
.left-top-20:hover ~ .element {
background-color: red;
}
.right-bottom-20:hover ~ .element {
background-color: green;
}
.element {
height: 300px;
width: 400px;
background: #333;
}
A drawback of this is that the spans will be in front of the div element, so they will prevent any interaction with what is underneath, such as selecting text or clicking any button.
Solution 2: with JavaScript
For this solution, you don't need container or auxiliary elements.
First, you add a listener for hovering the element, the mousemove event listener. Every time the mouse moves inside the element, its height and width will be stored, as well as the position of the mouse inside it.
Lastly, the conditional and calculation will be made to check if the position is where you want it to be, adding classes to style the div, or removing them.
.element {
height: 300px;
width: 400px;
background: #333;
}
.red {
background: red;
}
.green {
background: green;
}
document.querySelector('.element').addEventListener('mousemove', function(e) {
var elementWidth = this.offsetWidth;
var elementHeight = this.offsetHeight;
var positionHorizontal = e.offsetX;
var positionVertical = e.offsetY;
if (positionHorizontal <= elementWidth * 0.2 && positionVertical <= elementHeight * 0.2) {
this.classList.add('red');
} else if (positionHorizontal >= (elementWidth - (elementWidth * 0.2)) && positionVertical >= (elementHeight - (elementHeight * 0.2))) {
this.classList.add('green');
} else {
this.classList.remove('red', 'green');
}
});
Another event listener is also needed to check if the mouse has left the element. This is for situations where the mouse was in one of the corners before leaving, so the style will be removed. Otherwise, the style would remain applied even with the mouse out.
document.querySelector('.element').addEventListener('mouseleave', function(e) {
this.classList.remove('red', 'green');
});
A disadvantage of this approach is that it has a worse performance than the first solution.

How to scroll fixed area when footer is reached?

Is it possible to achive the following configuration in CSS please ?
I have a long page with a footer in the bottom (the footer display property is flex)
In the visible area of the page I need the fixed area to be always in the bottom as long as the scrolling has not reached the footer.
Once the scrolling has reached the footer, the fixed area should scroll up to be on the top of the footer like in the following screenshots:
The fixed area is in the bottom of the visible region of the page.
When scrolling, if the footer is not reached, the fixed are will remain at the bottom of the page
When reaching the footer, the fixed position is on the top of the footer
I tried something like:
FixedArea {
position: fixed;
bottom: 0;
width: 100%;
}
but when I scroll until the footer the fixed region disappears.
You can nest the body content together with the fixed content in a element that has a height: 100vh on it, and overflow: auto on the actual content of that page, in that way the content will scroll independently of the fix element, and once reached the end the body scroll will continue on till the end of page (footer)
I created an example. Try: https://jsfiddle.net/pvviana/wwc8LgLm/
I am changing the div css property "position" at the bottom of page.
Code:
<div class="foo">Hello</div>
<footer>OKAY</footer>
Javascript(Jquery):
var $logo = $('.foo');
$(document).scroll(function() {
$logo.css({position: $(this).scrollTop()>100 ? "relative":"fixed"});
});
Css :
.foo {
position: fixed;
bottom: 0px;
}
Here is a (another) possible jQuery solution.
During scroll, calculate the distance remaining until the bottom of the window, and start setting the bottom style property on your fixed area the height of the footer minus the distance remaining, otherwise make sure it's set (back) to the original, as follows (note, I set the height of the content block to 800px, so make sure you try this so that the result window has a smaller height than that):
var originalBottom = 0; // get this depending on your circumstances
var footerHeight = 72; // get this depending on your circumstances
$(window).scroll(function () { // start to scroll
// calculating the distance from bottom
var distanceToBottom = $(document).height() - $(window).height() - $(window).scrollTop();
if (distanceToBottom <= footerHeight) // when reaching the footer
$("#fixed-area").css('bottom', (footerHeight - distanceToBottom) + 'px');
else // when distancing from the footer
$("#fixed-area").css('bottom', originalBottom + 'px'); // only need to specify 'px' (or other unit) if the number is not 0
});
body {
padding: 0;
margin: 0;
}
#content {
height: 800px;
}
#fixed-area {
position: fixed;
bottom: 0;
padding: 5px;
margin: 5px;
border: 1px solid green;
width: calc(100% - 22px); /* padding (2*5) + border (2*1) + margin (2*5) */
text-align: center;
}
#footer {
height: 40px;
position: relative;
bottom: 0;
padding-top: 20px;
margin: 5px;
border: 1px solid black;
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="fixed-area">Fixed Area</div>
<div id="content"></div>
<div id="footer">Footer</div>

"Fixed" positioned before pseudo element

How can I make the icon::before pseudo element not scroll. I want it to have a "fixed" position; not relative to the window, but to div.scrollable.icon
Here's the demo I'm talking about: http://codepen.io/anon/pen/VLWdEm
===UPDATE===
There's a problem here. Here's the new codepen: http://codepen.io/kiranm/pen/QbgxZV
How do I make icon::before "fixed" relative to div.scrollable.icon?
Ok, I understood your problem. Since we all tried the code with the preview expanded we didn't see that when we shrink the preview the div was fixed relative to the window.
So I came up with this, although I couldn't do it just with CSS, I had to add a little of jQuery and modify your HTML structure.
HTML
<div class="scrollable">
<div class="icon"></div>
text
</div>
CSS
.scrollable {
border: 1px solid tomato;
width: 200px;
height: 200px;
overflow: auto;
position: absolute;
}
.icon {
position: relative;
}
.icon::before {
content: 'An icon';
background-color: yellow;
padding: 2em;
}
And the jQuery
var $ = jQuery || $;
$(document).ready(function() {
$('.scrollable').on('scroll', function() {
var top = $('.scrollable').scrollTop() + $('.scrollable').offset().top;
$('.icon').css({'top': top + 'px'});
});
});
As you can see I added another CSS rule so I can manipulate it with jQuery, and with jQuery I took the value of the scroll in the container div and I add to it its value to the top of the window, and I assign that result to the top of the icon so it will be "fixed" to the div. Also I moved the icon div to be a child of scrollable so I can manipulate it separately.
Here's the pen http://codepen.io/anon/pen/QbgxzV
I hope it helps you.
Try like this: Demo
.icon::before {
content: 'An icon';
background-color: yellow;
padding: 2em;
position: fixed; / * changed position absolute to fixed */
}
I cant understand your requirement?
Position fixed is working for relative to window screen only. otherwise you set icon position:relative then give icon::before position absolute.

CSS - how to hide the top of a container using CSS-height, vertical-align and overflow?

I have an image container based on Jquery Mobile listview element structure.
Looks like this:
<li>
<div class="ui-btn-inner">
<div class="ui-btn-text">
<a>
<img src="img/products/l/demo2.jpg">
<h3>product2</h3>
</a>
</div>
</div>
</li>
I'm overriding JQM-CSS to create an image gallery-list. Images and h3 are both contained inside a link element. As the images can have different heights, I want to set a CSS fixed-height/overflow:hidden to the link element to cut off images at the top using vertical align: top.
Here is my CSS so far:
li {
display: inline-block;
min-width: 200px;
max-width: 300px;
width: 24%;
}
li img {
width: 100%;
position: static !important;
max-width: 185px;
max-height: inherit;
}
// fix height and overflow hidden
li a {
height: 100px;
overflow: hidden;
vertical-align: bottom;
}
It doesn't work... If I check on Firebug, the element-height is set to 100px, but it covers the image top versus covering the image bottom and h3, which I do not want to crop away.
I have tried setting line-height to 100px as well, but this does not work at all.
Any hints on what I'm doing wrong?
Thanks!
EDIT:
Can't use clip either, because I don't know at what height I want to start (img.height-100px) and I cannot clip from the bottom. Or can I?
SOLUTION:
It would work like this:
li a {
position:absolute;
bottom: 0;
left: 0;
}
li div.ui-btn-text {
position: relative;
height: 100px;
overflow: hidden;
}
Doesn't use vertical-align but the result is ok.
I'm afraid that can't work. Adding display:block; to your link and would be a start for your method, but check the result: http://jsfiddle.net/uu96D/
vertical-align: bottom; won't push the a tag to the bottom of the container. Here is a guide of how vertical-align works: http://phrogz.net/css/vertical-align/index.html
To solve your problem i'd go to some js solution, and add a negative top margin to the image if its taller than, for example, 80px. Here's a fiddle with the result: http://jsfiddle.net/uu96D/1/
And the code using jQuery:
$('img').each(function(){
var height = $(this).height();
if (height > 80) {
$(this).css({marginTop: "-" + (height-80)});
}
});

Resources