What I'm trying to do is have a block(let's call it .top) that is fixed and another block(let's call this one .content), that, when scrolling, goes over .top, this all while retaining everything that .top contains clickable.
Now there are some obvious setups
this
http://jsbin.com/rucifuzu/1/edit?html,css,output
or this
http://jsbin.com/hufomaxu/1/edit?html,css,output
problem with both is a) you have to account for scrollbar width b) scrolling/swiping on .top won't do anything with the element with overflow: auto underneath it
I have thought about a couple of solutions.
First would be pointer-events: none on .top, which would make it "transparent" for mouse events, thus triggering scroll on whavever is under it, the problem with is that click events won't work either, and since I plan on having clickable and selectable thing inside .top, it's a problem. I could reset pointer-events back to auto just for those click/selectable thing, but considering one of those clickable things is gonna be big ass headline, I'm gonna have a problem with scroll not working with mouse position on it again.
Second was what I call scroll delegation, using JS I would catch mousewheel events and change scrollTop on the overflow: auto element. This would work fine, except that it might result in different scroll "feel" while this delegation is happening and while native scroll on .content kicks in. It's also pain in the arse to get this behaving correctly on touch devices.
So neither is ideal. Have I missed any genious and simple solution to this problem?
TL;DR Goal is to have the .top element BOTH clickable and "scroll-thru-able"
this way .top is clickable, but element under it won't scroll - http://jsbin.com/hufomaxu/1/edit?output
this way element under it will scroll, but .top is not clickable - http://jsbin.com/tuluwili/1/edit?output
Not sure I understand 100% - you want to visually cover up a fixed element while scrolling but still be able to click on it?
One simple solution might be using 3 layers instead of 2.
Bottom layer contains your links and is fixed.
Middle layer is the one that will scroll over it and cover it up.
Top layer is fixed and is identical to Bottom layer except clear all the background colors and set opacity to 0.
When you scroll it would look like the bottom is being covered up but you could still click on the top invisible layer.
Might not work if you need to do things like drag to copy text or interact in other ways with the middle layer.
Related
i am currently creating a web site and my problem is, that I have to put two DIVs on the page, that enable scrolling either one screen back or forth with a mouse click instead of the scrollbar (which is also usable) and I want them only to be visible, when there actually is something to scroll. So when the content fits into another DIV, there should not be any scroll back/forth button visible. They may take the space (or not) but I do not want them visible.
Now, I could poll the offsetWidth and scrollWidth of that other DIV with a 100ms interval, compare them and decide the visibility, but that is really ugly.
Is there some event I cloud use except resize, because that would not work on mobile/mac?
I did not find anything (yet) - neither on SO nor on the internet.
Thanks
I wasn't able to find any events to hook into for this - I want to take control over the scroll distance when the user does things like moving the mouse wheel, clicking a scroll button (up or down), clicking the empty space of a scroll bar, etc.
For example, if I have a list of things, and each row is 16px tall, how would I be able to force it to scroll 16 pixels for single scroll events (i.e. mouse wheel up/down, or clicking the scroll button, if one exists)? And then, if scrolling by clicking the empty scroll bar, how can I ensure it scrolls by a fixed amount, so when it's done scrolling, it would be perfectly aligned? The best example I can give is how it behaves in Excel. Provided you have the scroll lines to be set to 1 line in settings, scrolling up or down will move one row at a time. Clicking the empty part of the scroll bar moves down exactly to the next not-fully-visible row.
My research, up until now, indicates I'll be using the .scroll() function (at least if I'm using jQuery), but I'm completely stumped at the plan of attack, even moreso because I'm unable to find any way to differentiate between a mouse wheel scroll, button scroll, or scrollbar jump (or whatever the terms would be).
Is there also a way to restrict this in CSS, avoiding any JavaScript at all?
To achieve this, you need to use scroll-snap-type, as stated by DM in the comments.
You'd set the parent div to have scroll-snap-type: y mandatory;, and it's immediate children elements would have scroll-snap-align: top (or bottom)! This should allow rows to be viewed perfectly, provided the containing element is an appropriate size (and assuming each child element is a known fixed size).
In HTML/CSS/JS, there is one thing I am having trouble figuring out:
How to prevent people from scrolling an element using the mouse wheel press (i.e. hold down the mouse wheel and drag, or click the mousewheel, drag, click the mouse wheel again) and how to do the same when people try to drag the elements around on a touch-device.
This is something I stumble upon, amongst other places, when trying to make a hamburger-style menu.
Setting an element's CSS to overflow: hidden will hide the scroll bars, but using above two methods, it is still easy to scroll through them.
Until now, the only 'solution' I found was to make a second element, and position it on top of the element that should not be scrollable. But this hardly seems like a perfect solution to me.
How can these events be captured using JavaScript?
How can, on, for instance, this page, scrolling horizontally and vertically be blocked when the menu is open?
If you create a jsfiddle, we can give a better solution. If you are OK with jquery, I can give some solution for your second point "How can, on, for instance, this page, scrolling horizontally and vertically be blocked when the menu is open?".
First you need to create one simple class like below.
.overhidden
{
overflow:hidden !important;
}
Next, we need to apply this class when you press the menu icon on your screen. Also we need to remove if they click again for closing. It is easy to do in jquery like below.
$(document).ready(function(){
$('#hamburger').click(function(){
$('body').toggleClass('overhidden');
});
});
I have an overflow: hidden div which I am scrolling by allowing the user to click and drag the background. There are also links and buttons in this space.
This is what I do for the CSS:
#div-grabscroll {
cursor: url(../img/openhand.cur), move;
}
#div-grabscroll:active {
cursor: url(../img/closedhand.cur), n-resize;
}
This works great but what happens is that while dragging, if the mouse ends up moving (due to reaching scroll limits) over a button the pointer cursor overrides my closedhand cursor.
The desired behavior is that for the entire duration that the div is being controlled by the mouse, I want the cursor to remain the closedhand.
Is there a way to override the cursor without modifying CSS for everything that the mouse might move over? I tried !important on the :active style but that didn't do it.
Answer / Question: What would happen if you had a duplicate div which sat on top of the grabscroll div, but which had no background or content of any type so as to not hide anything behind it, and then set the cursor hand on this.
Does z-index overwrite importance this way?
Does this make sense?
Effectively you have grabscroll - button - opaque grabscroll in that layered order.
This is a very similar problem to creating "modal" dialog boxes, and it will probably have a similar solution: I think you'll have to create an iframe positioned over the content you're scrolling, making it higher up in the z-index order than the content, for the duration of the scroll. This is because on IE (at least) form controls tend not to obey z-index well, which is why "lightbox"-style things do this iframe shim thing.
Here's an answer I gave to another question here on SO which demonstrates the basics of the iframe shim. In that case it's for modal purposes, but the concept and most of the code would apply.
this is an odd one, that has eaten a lot of hours of my time. Here's a photo since i can only put 1 link: http://www.screencast.com/t/byVmPE6H . Explanations follow.
Basically, what i need to achieve is point 1 in the photo.
Please notice that the left padding is larger than the right one. The initial padding property is:
padding: 12px 15px; (i.e. 12px vertical padding, 15px horizontal).
Then, via jquery, on page load, i set the left padding to some value like so:
$(links[0]).attr("style","padding-left : "+padding+"px;"); (i could've used .css(), the effect and problem remain the same)
This works beautifully in all browsers, you guessed right, except IE. I'm not talking about versions 6 or 7, but only IE 8. So, in IE 8, on page load, i get point 2 from the photo above.
Remember, that happens only on page load. After i go with the pointer over the link (i.e. triggering the mouseover event), the right padding jumps back into place and it looks perfect, just like in the first link (actually that first photo is from IE8!).
Eliminating the jquery line above doesn't trigger the same behavior, the 15px paddings are ok. There's no event handler registered for "mouseover" on the links. There's only this css property for mouseover:
#navigation li.first:hover a{
background: transparent url(../images/menu_on_left.png) left top no-repeat;
}
(i.e. only a background image change, absolutely nothing else)
So, when page loads, if i use jquery to change the left padding, the right one dissapears. On mouse over, the right padding pops back into view. I cannot explain myself why this happens. If i can't find a solution i'm actually thinking of computing the position of all the menu items and arranging them with position: absolute. Sounds really bad, i know.
Can anyone enlighten me please?
I finally solved it, and beware:
IE is so dumb, that if you have a list of floated elements, and you change the right padding of the first one, the other don't react by moving right, they just stand there. So what i did was:
remove all other menu items (via clone() then remove() unfortunately, i didn't have jquery 1.4 available or i would've used detach(), but it works just fine),
change padding via css()
re-insert the other menu items. Now they sense the new padding on the first item and are positioned correctly.
Crazy, isn't it? just another IE hate reason for me...
I hope this helps anyone, have a nice day!