I'm having a hell of a time trying to understand and then implement a working scrolling method.
Goal:
Create a big picture viewer/gallery. Users click on arrow keys or on thumbnails in a toggled menu to navigate through images. The gallery and menu should keep track of which thumbnail the users are viewing.
Situation:
I have a position:absolute #menu that slides to become visible when your mouse hovers over the right edge of the window. This #menu has a child #galleryMenu whose overflow:scroll. The result is scrollable menu that is navigated using the scroll wheel.
Problem:
Everytime the mouse hovers off the #menu, you lose your place. I don't know how to get the #menu to stay where the user left off.
Sample Website Link: http://bahaha.ga/?view=0
I've also tried a few plugins, but they cancel #galleryMenu's overflow:scroll and it ruins the overall #menu.
Any help would be appreciated.
Below is a simpler/cleaned up code to help communicate my goal/problem.
HTML
<div id="resolution">
<div id="main">
<img />
</div>
<div id="menu">
<div id="galleryMenu">
<ul id="galleryThumbnail">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</div>
</div>
CSS
#resolution{
position: absolute;
margin:0;
padding:0;
width: 100%;
height: 100%;
}
#main{
position: absolute;
width: 100%;
height: 100%;
}
#menu{
position: absolute;
display: block;
cursor: pointer;
right: 0;
width: 10px;
}
#galleryMenu{
position: absolute;
display: none;
width: 350px;
right: 0;
overflow: scroll;
}
#galleryThumbnail{
list-style-type: none;
padding: 20px 0 20px 0;
margin: 0;
}
#galleryThumbnail li{
padding: 0;
margin: 0;
}
JQUERY
//Show and Hide Gallery Menu
$("#menu").hover(function(){
$("#galleryMenu").show('slide', {direction: 'right'}, 500);} , function(){
$("#galleryMenu").hide('slide', {direction: 'right'}, 500);}
);
//Set Window Height as Menu Heights
$("#menu").height($(window).height());
$("#galleryMenu").height($(window).height());
// Scroll to Current Thumbnail on Menu
$("#galleryMenu").animate({
scrollTop: $(document).height()-$(window).height()},
1400,
"easeOutQuint"
);
you need this .
var tempScrollTop=0;
$(document).on( 'scroll', '#galleryMenu', function(){
tempScrollTop = $(#galleryMenu).scrollTop();
});
$(document).on( 'hover', '#galleryMenu', function(){
$(#galleryMenu).scrollTop(tempScrollTop);
});
Hope it helps
I managed to find a workaround. Using Jquery's slideUp() and slideDown() kept resetting the location of the #menu (instantly as soon as your mouse hovered off #menu).
Instead of using slideUp() and slideDown(), I ended up using .animate() to move #menu off the screen to the right. This made keeping track of the scroll position on #menu easier as user's hovered away temporarily.
Khaleel, thanks for the code, but it did not work for me. However, I managed to get a working code up:
//Menu : Scroll to Thumbnail
$("#galleryMenu").animate(
{scrollTop: $("li:nth-child(<?php echo $currentImage ?>)").offset().top-()},
500
);
Using the the UL's LI elements and a little bit of PHP, I was able to grab the nth-child of the li element that contained the thumbnail of the currently viewed image in order to center it onto #menu.
Thanks everyone!
Related
I have this fixed height scrollable ul element which is for a video playlist. Scrolling works fine but when the user scrolls thru all the content they get stuck on the playlist container element. Basically, the scroll chain breaks and you can't scroll up unless you tap on one of the other elements on the page which is no easy job due to the playlist container taking all of the space on the screen and it doesn't have any padding around it.
What I need is, I need the browser to stop focusing on the ul element and shift the scroll event from element to window so they wouldn't get stuck scrolling on the ul element.
Playlist element's CSS:
.plyr-playlist-wrapper ul {
padding: 0;
margin: 0;
max-height: 28em;
min-height: 28em;
overflow-y: scroll;
-webkit-overflow-scrolling: touch; // this is the problem
}
You can solve this problem using JS (see below), but you should also consider restructuring your page so that you prevent this issue altogether. For example, you could choose not to limit the height of your ul element and still keep your video in focus when scrolling (e.g. by making it sticky).
Here is a possible solution based on JS (which needs some additional finetuning). It works by detecting when you have scrolled to the top of your ul element and bringing the video back into view.
document.getElementById("suggestions").onscroll = (e) => {
if (e.target.scrollTop == 0) {
document.getElementById("video").scrollIntoView({
behavior: "smooth"
});
}
}
#container {
margin-top: 5em;
}
#video {
height: 10em;
background: blue;
}
#suggestions {
overflow-y: scroll;
height: 28em;
margin: 0;
padding: 0;
background: red;
}
.suggestion {
height: 10em;
margin: 12px;
background: yellow;
}
<div id="container">
<div id="video">
</div>
<ul id="suggestions">
<li class="suggestion">
</li>
<li class="suggestion">
</li>
<li class="suggestion">
</li>
<li class="suggestion">
</li>
</ul>
</div>
Turns out momentum-based smooth scrolling was the problem. So I had to remove it and the problem was solved. You lose the smooth scrolling function but who cares.
// setting it to 'touch' will give you smooth scrolling but it will prob break the scroll chaining
-webkit-overflow-scrolling: auto;
Goal
To have the page navigation positioned lower on the page when initially loaded. So that it looks like pictured below.
Background
I created a navigational element that is using Headroom.js to control its position. The point of the library is that it moves the desired navigational item out of view when a user is scrolling down so that you can see more content. Then the item shows up when you scroll back up to make it convenient to click on a link if that is what you needed to do.
Current State
I have this current demo on codepen.
That navigational item is at the top of the page but on a lower z-index. So not initially visible.
when you scroll down the element is out of view.
But when you scroll up, it is where it needs to be
Code
HTML
<nav id="page-menu" class="link-header header--fixed slide slide--reset" role="banner">
<ul>
<li>Products</li>
<li>Features</li>
<li>Testimonials</li>
<li>Cases</li>
</ul>
</nav>
CSS
#page-menu {
background-color: #BA222B;
list-style-type: none;
width: 100%;
z-index:10;
}
#page-menu ul {
list-style-type: none;
margin: 0;
position: absolute;
bottom: 5px;
right: 10px;
}
#page-menu ul li {
display: inline-block;
margin-left: 10px;
}
#page-menu ul li a {
text-decoration: none;
color: #fff;
}
.link-header {
background-color:#292f36;
height: 100px;
}
.header--fixed {
position:fixed;
z-index:10;
right:0;
left:0;
top:0px;
}
jQuery
(function() {
new Headroom(document.querySelector("#page-menu"), {
tolerance: 5,
offset : 150,
classes: {
initial: "slide",
pinned: "slide--reset",
unpinned: "slide--up"
}
}).init();
}());
Full demo on codepen.
Goal :
From what you are describing, you want the read navigation to appear as such on page load:
And move with the gray bar, but and down, as the user scrolls, until it cutoff point reaches the bottom of the gray bar. Then you want things to kick in, and have the red bar slide up and out of view, and then up and down depending on scroll. You want the transition to be smooth.
Method:
The thing to keep in mind for a smooth transition is that you have two states: A top state and a bottom state. You have to design both, you have to figure out the exact height to change over, and you have to make sure that they will be identical at that spot, so appear seamless.
Top State:
We don't need any sort of extra positioning here. We want it to be static in fact, as odd as that might sound.
Bottom State:
We want fixed positioning here. Since we want the changeover to occur right when the red bar touches the top of the window, your CSS in fixed-header is perfect already.
Changeover Height:
The header and the gray nav bar combined are 180px, so that number will be our change over.
Code:
1. Statechange
Lets work backwards and take the state change first. You will need to change from 150px to 180px in a lot of places. For example, your JS code:
Existing JS:
if ($(window).scrollTop() >= 150) {
...
(function() {
new Headroom(document.querySelector("#page-menu"), {
tolerance: 5,
offset : 150,
New JS:
if ($(window).scrollTop() >= 180) {
...
(function() {
new Headroom(document.querySelector("#page-menu"), {
tolerance: 5,
offset : 180,
And your header will need an updated height, or a removal of height entirely.
Existing CSS:
header {
height:150px;
position: relative;
z-index:30;
}
New CSS:
header {
position: relative;
z-index:30;
}
2. Top State
The big thing here messing you up is that for some reason the library you are using is applying .header--fixed and link-header on page load. I don't know how to prevent this, but we can just neutralize is by removing them from your CSS.
Remove This CSS:
.link-header {
background-color:#292f36;
height: 100px;
}
.header--fixed {
position:fixed;
z-index:10;
right:0;
left:0;
top:0px;
}
Second, we need to tweak the ul inside your red nav.
Existing CSS:
#page-menu ul {
list-style-type: none;
margin: 0;
position: absolute;
bottom: 5px;
right: 10px;
}
New CSS:
#page-menu ul {
list-style-type: none;
margin: 0 auto;
padding:0;
width:960px;
max-width:100%;
text-align:right;
}
3. Bottom State
Everything works really well here aleady, except that the fixed-header class is getting added to the gray nav as well. We need to tweak our jQuery selector bit.
Existing JS:
if ($(window).scrollTop() >= 180) {
$('nav#page-menu').addClass('fixed-header');
}
else {
$('nav#page-menu').removeClass('fixed-header');
}
NewJS:
if ($(window).scrollTop() >= 180) {
$('header nav').addClass('fixed-header');
}
else {
$('header nav').removeClass('fixed-header');
}
4. Misc Cleanup
Everything looks really good here, except that the lis inside our two navs don't line up. We need to fix some margin-right to bring them into line.
Existing CSS:
#page-menu ul li {
display: inline-block;
margin-left: 10px;
}
New CSS:
#page-menu ul li {
display: inline-block;
margin-left: 10px;
margin-right: 10px;
}
Finally, I noticed that there's a missing closing bracket in your HTML, in the gray nav. It's not hurting much, but it could:
<nav>
<ul>
<li>Dentists</li>
<li>Labs</li>
<li>Patients</li>
<ul> <--- ( Should be </ul> )
</nav>
End Result:
http://codepen.io/anon/pen/qIrhx
This is a hard one to explain so bear with me (or just skip straight to the jsfiddle)
I have a Div with a max-height defined and overlow-x set to scroll. Within this Div there are a bunch of list items (in this instance, addresses). Naturally there can be many of these and they can overflow, which works fine. What I want is a 'cover' div that indicates that this panel is disabled. I have done this by putting an absolutely positioned div within the main div, like so.
<div style="max-height:150px;overflow:auto;position:relative">
<ul>
<li>Church Walk, Access To Foxholes Farm, DT2 9HG
</li>
<li>Garden Cottage, Access To Foxholes Farm, DT2 9HG
</li>
<li>Little Bride, Access To Foxholes Farm, DT2 9HG
</li>
...etc
</ul>
<div id="overlayDiv" style="display:none;background-color:white;position:absolute;top:0px;opacity:0.8;height:100%;width:100% ">
<p style="margin-top:50px;text-align:center;font-size:18px;">Searching...</p>
</div>
</div>
This then appears when the user does something, overlaying the content and making it appear disabled. Great! The problem occurs when my list items overflow. When the overlay div appears it only covers the current visible portion of the parent div, meaning that if I scroll down the div it appears 'uncovered' as the cover div only spans the height of the parent, not including its overflow.
This is really hard to explain so please go to my jsfiddle and click one of the addresses. You'll see that the div gets covered. If you then scroll down that div you will see that the items at the bottom of the list are uncovered.
This also works in reverse so if you click the 'Hide the overlay div' button to get rid of the cover and then click one of the addresses at the bottom of the list, you'll see that the 'cover' still only covers the top part of the div.
Any ideas on how you go about making that cover div extend the entire height of its parent, including the overflow? Other alternative solutions are welcomed and encouraged. Bear in mind that I don't necessarily need the 'Searching' text that gets overlaid on top, just the 'cover' would be enough.
3 divs instead of 2 works well:
http://jsfiddle.net/JhGCn/2/
html:
<div id="geogPickerAddressResultContainer" style="max-height:150px;overflow:auto;position:relative">
<div id="insideDiv">
<ul ...
</ul>
<div id="overlayDiv" style="display:none;">
<p style="margin-top:50px;text-align:center;font-size:18px;">Searching...</p>
</div>
</div>
</div>
css:
#insideDiv {
width: 100%;
height: 100%;
position: relative;
}
#overlayDiv {
background-color: white;
position: absolute;
top: 0px;
opacity: 0.8;
height: 100%;
width: 100%;
}
this works fine too:
http://jsfiddle.net/JhGCn/3/
var height = $('#addressPicker li').height();
$.each($('#addressPicker li'), function (i, addr) {
height += $(this).height();
$('#overlayDiv').css("height", height + "px");
etc..
I would take the overlay out of the parent, set a z-index and position it over the address picker with negative margin.
http://jsfiddle.net/JhGCn/1/
#overlayDiv{
background-color: white;
opacity: 0.8;
height: 100%;
width:100%;
position:absolute;
z-index:9999;
margin-top:-150px;
height:150px;
}
This a pattern I've seen before as well: http://jsfiddle.net/6oa6grn9/
#overlayDiv {
background-color: white;
opacity: 0.8;
position: absolute;
bottom: 0;
left: 0;
right: 0;
top: 0;
}
This is my first post, but I'm a long-time viewer. Hope someone can help - this one's been driving me crazy and I've tried and tried to find an answer but to no avail.
Basically, I'm updating a friend's website with a few stylistic scrolling elements. I chose SuperScrollorama as it looks completely amazing, although I'm ready to accept that it's complete overkill for what I'm trying to achieve. I'm really interested in SuperScrollorama anyway, so I suppose I partly chose it just so I could try to use it!
Anyway, the idea I'm trying to implement involves:
Single page website, where section one is simply a centred, large (650px width) image and a navigation menu <ul> centred and fixed to the top of the page containing 6 <li> elements.
On scrolling down, I want the image to shrink to 250px width, and I want to make a space of 250px between the third and fourth <li> for the shrunken image to scroll into and then remain for the duration of the scroll. I'm trying to create the space by adding a margin-right to the third <li>. (I appreciate this may give me undesirable side-effects, one being that it won't be completely centred. Suggestions welcome here too! The problem that I'm about to describe, however, I also experienced when trying other methods based around floating and using two separate divs so the margin-right itself doesn't seem to be the root cause)
Now, I've managed to get the image to shrink and attach itself to the top of the page without too much trouble.
The problem that I'm having is with the margin-right. On page load, the <ul> appears centred and uniformly spread, as I want it to. The margin-right value on the third <li> is 0. However, the value jumps from 0 to 89px following the tiniest of scroll events. Continuing the scroll works as desired, but on scrolling back up, the margin returns to 89px and then stops.
Here's the code that I've got:
HTML:
<body>
<nav>
<ul>
<li>HOME</li>
<li>PROGRAMME</li>
<li id="grow_margin">TICKETS</li>
<li>MENU</li>
<li>VENUE</li>
<li>FAQ</li>
</ul>
</nav>
<header id="fix-it">
<h1><img id="scale-it" src="/images/logo.png" />TITLE</h1>
</header>
CSS:
html {
height: 100%;
width: 100%;
}
body {
height: 100%;
width: 100%;
}
nav {
position: fixed;
top: 0;
width: 100%;
height: 5%;
text-align: center;
}
nav ul {
list-style: none;
height: 100%;
}
nav ul li {
display: inline-block;
height: 100%;
}
nav ul li a {
color:#bbbbbb;
text-decoration: none;
margin: 8px;
}
header {
width: 100%;
position: fixed;
}
header h1 {
width: 100%;
text-align: center;
margin: 0;
padding: 0;
}
And the JS:
<script>
$(document).ready(function() {
var controller = $.superscrollorama({
reverse: true
});
var windowHeight=window.innerHeight;
var scrollDuration = windowHeight;
controller.addTween('#grow_margin',
TweenMax.to( $('#grow_margin'), .25, {css:{'margin-right':'250px'}, immediateRender:true}), scrollDuration);
controller.addTween('#scale-it',
TweenMax.fromTo( $('#scale-it'), .25, {css:{width:'650px'}, immediateRender:true, ease:Quad.easeInOut}, {css:{width:'250px'}, ease:Quad.easeInOut}),
scrollDuration);
controller.addTween('#fix-it',
TweenMax.fromTo( $('#fix-it'), .25, {css:{top:'40%'}, immediateRender:true, ease:Quad.easeInOut}, {css:{top:'4'}, ease:Quad.easeInOut}),
scrollDuration);
});
</script>
Any help would be so much appreciated! It's driving me absolutely crazy!
Thank you!
Rob
I'm Designing a website which involves slideDown.
Initially i have set up a template which looks like the image below
When i hover over each black blocks a ul list will be displayed... But a problem arises when i hover... All the content below the block moves down (This is illustrated in the following figure)
I cant give the position to be absolute because all the content above and below are floating (They Don't have a fixed height). So what else can be done to get a slideDown by holding the rest of content there and by displaying the hover content over the text?
To achieve what you want you should slideDown() an inner submenu element instead of the block itself.
Consider this sample markup:
<div class="item" id="mybox">floating box
<ul class="submenu" style="display: none;">
<li>Subitem 1</li>
<li>Subitem 2</li>
<li>Subitem 3</li>
</ul>
</div>
<p>More content... Just to illustrate</p>
<p>More content... Just to illustrate</p>
The CSS would be something like:
.item {
position: relative; /* to hold absolutely positioned submenu inside */
background: #2684b7;
color: #fff;
padding: 10px;
float: left;
}
.item .submenu {
position: absolute; /* the menu would go on top of everything */
background: #2684b7;
width: 100%;
left: 0;
}
p {
clear: both;
}
And finally the JavaScript is simple, just don't forget to bulletproof your animation:
$('#mybox').hover(
function() { /* mouseover */
$(this).find('.submenu').slideDown();
},
function() { /* mouseout */
$(this).find('.submenu').slideUp();
}
);
Here's the example on jsFiddle: http://jsfiddle.net/zxrvC/
Good luck.
Make a div with position: relative and z-index:55 and inside that div add a new div with position: absolute and also give width. Hope this will solve.
Regards
iijb