Trying to do a regular horizontal nav with arrow that has a endless loop. Tried figuring it out and some how I can't get it to loop back to "all" div.
tried slick carousel but it has this glitch when the page loads
HTML
<div id="second-navigation">
<div id="slider">
<li>All</li>
<li>slide1</li>
<li>slide2</li>
</div>
</div>
JS
var W = $('#second-navigation').width();
var N = $('#slider li').length;
var C = 0;
$('#slider').width( W*N );
$('#left, #right').click(function(){
var myID = this.id=='right' ? C++ : C-- ;
C= C===-1 ? N-1 : C%N ;
$('#slider').stop().animate({left: -C*W }, 1000 );
});
CSS
#second-navigation{
width:300px;
height:150px;
position:relative;
overflow:hidden;
}
#slider{
position:absolute;
height:150px;
left:0;
width:9999px;
}
#slider li{
float:left;
}
One approach would be to as follows:
When a direction button (ie left or right) is clicked, clone the list item that will be moved out of view by the animation (ie the first <li> for the <ul> when the "left" button is clicked)
attach the cloned <li> to the opposite end of the <ul> list (ie append the cloned first to the end of <ul> when "left" is clicked
animate the margin of the <ul> element to hide the original <li> that was cloned (ie for the "left" case, animate the <ul> left margin to "-150px", which is the width of your <li> items)
On completion of the animation, ensure the <ul> margin is reset, and that the now hidden <li> element has been removed
This can be written in code as shown below. There are a few extra things going on here:
The <ul> needs to be the direct parent of <li> items (a <div> cannot parent <li> items)
Flex box is used to achieve horizontal layout of <li> items, which simplifies CSS styling
Compounded animations need to be prevented (ie the case where button click happens during an existing animation). Below, I'm just ignoring clicks if an animation is underway
$("#left").click(function() {
/* If currently animated, early exit */
if($("#second-navigation ul:animated").length) {
return;
}
/* Clone the element that will be hidden */
var firstClone = $("li:first-child").clone();
$("#second-navigation ul")
.animate({
/* Animate ul container left margin to left */
"marginLeft": "-150px"
}, {
done: function() {
/* Reset ul container left margin */
$(this).css("marginLeft", "0px");
/* Remove element that is now hidden */
$("li:first-child", "#second-navigation ul").remove();
}
})
/* Add cloned element to end of list */
.append(firstClone);
});
$("#right").click(function() {
if($("#second-navigation ul:animated").length) {
return;
}
var lastClone = $("li:last-child").clone();
$("ul")
.css({
"marginLeft": "-150px"
})
.animate({
"marginLeft": "0"
}, {
done: function() {
$("li:last-child", "#second-navigation ul").remove();
}
})
.prepend(lastClone);
});
#second-navigation {
position: relative;
overflow: hidden;
width: 300px;
height: 150px;
}
ul {
display: flex;
width: fit-content;
flex-direction: row;
padding: 0;
margin: 0;
}
li {
position: relative;
height: 150px;
width: 150px;
top: 0;
left: 0;
transition: left ease-in-out 1s;
background: linear-gradient(45deg, black, transparent);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="second-navigation">
<ul>
<li>All</li>
<li>slide1</li>
<li>slide2</li>
</ul>
</div>
<button id="left">Move left</button>
<button id="right">Move right</button>
Hope this helps!
Related
Could you please give me tips how to make drop-down menu disappear on scroll up and down?
It is a little bit hard to find it in pure js. Just what path to follow and I will figure out myself.
window.onsrcoll = function(){
var position = 0;
var scPos = (this.pageYOffset || document.documentElement.scrollTop) - (document.documentElement.clientTop || 0);
position += scPos;
if(position > scPos) {
// code here to hide drop-down menu.
}
}
/* on smaller size screens when it becomes drop down menu */
#media(max-width: 880px) {
#navi {
display: none;
}
.navWrapper label[for="mygtukas"] {
background: url(images/open.png);
background-size: 100% 100%;
display: block;
width: 55px;
height: 45px;
cursor: pointer;
position: absolute;
right: 2%;
filter: invert(85%);
transition: all 0.5s;
}
.navWrapper input[type="checkbox"]:checked ~ #navi {
display: block;
user-select: none;
position: absolute;
}
<div class="navWrapper" >
<h1 id="myLogo"><span class="initial">E.</span><span class="name">Erlandas</span> Petronis</h1>
<div class="shadow"></div>
<label for="mygtukas" id="icon"></label>
<input type="checkbox" id="mygtukas">
<ul id="navi">
<li id="li"><a id="link" class="active" href="#home">Home</a></li>
<li id="li"><a id="link" href="#about">About</a></li>
<li id="li"><a id="link" href="#portfolio">Portfolio</a></li>
<li id="li"><a id="link" href="#contact">Contact</a></li>
</ul>
</div>
JS does not work, at least does not make sense or am i off the track here?
As I can see that you want to make the drop-down menu disappear when scrolling down.
One way to do it would be by using Javascript.
What you can do is take the getElementById to change the style top of the navbar to make it disappear when scrolling down.
You can do something like this in javascript :
var position = window.pageYOffset;
window.onsrcoll = function(){
var scPos = window.pageYOffset;
if(position>scPos) {
document.getElementById("navbar").style.top = "0";
} else {
document.getElementById("navbar").style.top = "-50px";
}
position = scPos;
}
For this to work, you'll have to give your navbar a position: fixed; and top: 0;
Hide menu on scroll
el.scrollIntoViewIfNeeded() scrolls to el if it's not inside of the visible browser area. In general it works fine but I'm having problems with using it with a fixed header.
I made an example snippet: (The method doesn't work in Firefox, so neither does the demo) https://jsfiddle.net/ahugp8bq/1/
In the beginning all three colored divs are displayed below the fixed header. But if you click "second" and then "first", the beginning of #first will be behind the header, which I don't want.
The problem seems to be that the position of #otherContainer (its padding-top) is pretty much ignored when scrolling up.
Actually, this is quite simple if you use the consistent and supported getBoundingClientRect().top + body.scrollTop way - all you now have to do is reduce the header from it, so just get it and calculate its height.
var header = document.getElementById('container')
var clicks = document.querySelectorAll('#container li');
var content = document.querySelectorAll('#otherContainer > div');
// Turn the clicks HTML NodeList into an array so we can easily foreach
Array.prototype.slice.call(clicks).forEach(function(element, index){
element.addEventListener('click', function(e){
e.preventDefault();
// Set the scroll to the top of the element (top + scroll) minus the headers height
document.body.scrollTop = content[index].getBoundingClientRect().top + document.body.scrollTop - header.clientHeight;
});
});
#container {
position: fixed;
background: yellow;
width: 100%;
height: 50px;
}
ul li {
display: inline;
cursor: pointer;
}
#otherContainer {
padding-top: 60px
}
#first, #second, #third {
height: 500px
}
#first {
background: red
}
#second {
background: green
}
#third {
background: blue
}
<div id="container">
<ul>
<li id="jumpToFirst">first</li>
<li id="jumpToSecond">second</li>
<li id="jumpToThird">third</li>
</ul>
</div>
<div id="otherContainer">
<div id="first"></div>
<div id="second"></div>
<div id="third"></div>
</div>
I'm having trouble figuring out why my CSS transition isn't firing when I programmatically remove a class from an element.
Essentially, I am trying to create a progressively enhanced, infinitely-scrolling carousel using pure Javascript.
The basic idea is that as the user clicks to scroll either left or right, the first or last element is plucked from the parent ul element, and either prepended or appended to the proper location, depending on the scroll-direction of the user's click.
Here is the relevant code:
HTML:
<div id="scroller">
<ul>
<li>
<a>
<img src="...">
</a>
</li>
..... more li elements
<li>
<a>
<img src="...">
</a>
</li>
</ul>
</div>
CSS:
#scroller {
position: absolute;
left: 0em;
height: 8em;
width: 400em;
}
#scroller ul {
list-style: none;
}
#scroller ul li {
overflow: hidden;
float: left;
height: 8em;
width: 8em;
transition: width 1s ease;
}
#scroller ul li.hide {
width: 0em;
}
#scroller ul li a img {
width: 8em;
}
JS (scroll right click event, for example):
/** Remove the element from the end of the list, add the hide class */
var node = this.list.removeChild(this.items[(this.items.length - 1)]);
/** Add the hide class to the node */
node.className += ' hide';
/** Insert the node at the beginning of the scroller */
this.list.insertBefore(node, this.items[0]);
/** Remove the hide class to trigger the transition animation */
node.className = node.className.replace('hide', '');
Everything is working well, in terms of the items being shifted around the ul correctly, so that is not the problem.
The issue is that the CSS transition is not being applied when the width of the li elements are changed by removing the "hide" class.
I had hoped to create a smooth scrolling effect in browsers than can support the CSS transition.
Thanks in advance for not suggesting that I use a JS library! :)
Use a combo of setTimeout and the transitionend event.
Look here for more info on transitionend:
CSS3 transition events
/** Remove the element from the end of the list, add the hide class */
one = document.getElementById('one');
two = document.getElementById('two');
list = document.getElementById('list');
/** Add the hide class to the node */
two.addEventListener('transitionend', end, false);
setTimeout(function(){
two.className += ' hide';
}, 0)
function end(){
/** Insert the node at the beginning of the scroller */
list.insertBefore(two, one);
/** Remove the hide class to trigger the transition animation */
setTimeout(function(){
two.className = two.className.replace('hide', '');
}, 0)
}
#scroller {
position: absolute;
left: 0em;
height: 8em;
width: 400em;
}
#scroller ul {
list-style: none;
}
#scroller ul li {
overflow: hidden;
float: left;
height: 8em;
width: 8em;
transition: width 1s ease;
}
#scroller ul li.hide {
width: 0em;
}
#scroller ul li a {
width: 8em;
background-color:red;
}
<div id="scroller">
<ul id="list">
<li id="one">
<a>
One
</a>
</li>
<li id="two">
<a>
Two
</a>
</li>
</ul>
</div>
I have a container div element, this should contain all child div elements.
I saw this thread: Slide a div offscreen using jQuery and I was wondering how to implement it (within a div element and not in the body).
The code is working fine, but what if the "wrapper" div element has 500px width, how am I supposed to wrap the child divs? Am I need to use iframe or ...?
For a better understanding I made this image:
The red rectangle would be a window and the grey background the wall. You can only see trough the window and see the current div element. If you push the right button -aqua- you will see the green div and if you push the left button you will see the yellow div.
Notice: Div elements should move and not the wall.
jQuery for the logic and CSS3 for transition and transform.
Multiple galleries + Auto-slide + Pause on hover:
$(function(){
$('.gallery').each(function() {
var $gal = $(this),
$movable = $(".movable", $gal),
$slides = $(">*", $movable),
N = $slides.length,
C = 0,
itv = null;
function play() { itv = setInterval(anim, 3000); }
function stop() { clearInterval(itv); }
function anim() {
C = ($(this).is(".prev") ? --C : ++C) <0 ? N-1 : C%N;
$movable.css({transform: "translateX(-"+ (C*100) +"%)"});
}
$(".prev, .next", this).on("click", anim);
$gal.hover(stop, play);
play();
});
});
.gallery{
position: relative;
overflow: hidden;
}
.gallery .movable{
display: flex;
height: 70vh;
transition: transform 0.4s;
}
.gallery .movable > div {
flex:1;
min-width:100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Pause on hover and autoslide
<div class="gallery">
<div class="movable">
<div style="background:#0af">1 <p style="position:absolute; top:400px;">aaaa</p></div>
<div style="background:#af9">2</div>
<div style="background:#f0a">3</div>
</div>
<button class="prev">Prev</button>
<button class="next">Next</button>
</div>
As many galleries as you want
Count the number of slides and put into a counter C.
On prev/next click manipulate C
On autoslide $(this).is(".prev") will also evaluate as false so ++C will be used, just like clicking the Next button.
On mouseenter simply clearInterval the currently running itv and on mouseleave (the second .hover argument) reinitialize the itv
The animation is achieved by multiplying C*100 and translateX by - C * 100 %
Add all three div in a container div, then make the window wrap around the long div and hide the overflow.
Example if the window area is 960px then the div inside would be 3x 960 (2880)
You can center it by changing it's left position by increments of 960 (placing the long div in relative positioning and the window to overflow to hidden)
#window{
width:960px;
overflow: hidden;
}
#container{
position: relative;
left: -960px;
}
.content_box{
width:960px;
}
Then you can use javascript (jQuery) to animate the left position:
$('#arrow-left').click(function() {
$('#container').animate({
left: '-=960'
}, 5000, function() {
// Animation complete.
});
});
$('#arrow-right').click(function() {
$('#container').animate({
left: '+=960'
}, 5000, function() {
// Animation complete.
});
});
More on .animate can be found in the manual: http://api.jquery.com/animate/
<div id="parent">
<div id="container">
<div id="child1"></div>
<div id="child2"></div>
</div>
</div>
give the parent red div css properties:
position: relative;
overflow: hidden;
width: 500px;
height: somevalue;
wrap the children divs with another div "container for example" and give it the following css properties:
position: absolute;
width: ;/*overall width of all children divs including margins*/
top: 0;
left: 0;
height: ;/*same as parent*/
and finally for children divs:
float: left;
height: ;/*same as parent*/
I have a slide down menu. In HTML I have:
<menu>
<li id="vysledky">Výsledky
<ul class="menu2">
<li>2008
<ul class="menu3">
<li>21.08. - MMSR SCg</li>
<li>R SCOOechová Potôň SK</li>
<li>SCOOTER Brezová /Visonta/ HU</li>
</ul>
</li>
<li>2010</li>
<li>2011<</li>
</ul>
</li>
<li id="forum"><span>Fórum</span></li>
</menu>
And now i want to automaticly set the width of each 3rd level of menu (menu3) by the longest text in it. So in this example the width of this .menu3 will be the width of text "SCOOTER Brezová /Visonta/ HU".
I can't use css because the width of menu2 is stable and if it will be longer than menu2 its set to width of menu2 (cascade)
So i would use javascript (jquery). I have this code:
var i;
var podm;
$('menu>li').each(function() {
podm = 0;
if($(this).children('ul').size()) {
$(this).each(function() {
if($(this).children('ul').size()) {
$(this).each(function() {
podm++;
i = 60;
$(this).find('li a').each(function() {
var w = $(this).text();
$('#js').text(w);
w = $('#js').width();
if(w > i) {
i = w;
}
});
$(this).find("ul.menu3").css("width");
});
}
});
}
});
But this code works bad :-(.
Web: Here
You set the width of the menu3 ul to 345px which causes longer text to overlap. The Javascript just sets this width again.
<ul class="menu3" style="width: 345px; display: block; opacity: 0.13">
Try to remove the width specification and the jQuery code and check if it works. If you need a specific minimum width for the level 3 menu, you can use the min-width CSS attribute.
EDIT:
Ok, spotted it. The problem is the position: relative attribute in .menu3. The CSS for .menu3 should look like this:
.menu3 {
display: none;
position: absolute; /* This changed */
padding: 0;
margin: 0;
list-style: none;
left: 100px;
top: 0px; /* This changed */
background: #464646 url('3menu-po.png') repeat-y;
display: none;
white-space: nowrap;
}
Note the position: absolute. This takes the submenu out of the document flow and therefore it is not affected by the width set in .menu2.