Fade LI in and out on click - javascript

I have three separate paragraphs stored in three list-items with a continue reading image. I want only the first list-item to show. When you click the image, it should fade and show the next list-item in a fade transition. Once you reach the third one, it should fade back to the first one when you click.
My issue is that I am getting weird spacing- where the first list-items fades but still takes up space for a moment and causes the next fading in list item to jump up once the prior LI finally fades.
Opacity works perfectly with the fading but display collapses the fading out li so that list items stack on top of each other with the fading.
I could position the list items absolute with the UL position relative but I don't like the inherit lack of responsiveness with that method. I'd like to avoid it if I can help it.
Code so far-
<ul class="copy-box">
<li class="first active"><p>first</p></li>
<li class="second"><p>second</p></li>
<li class="last"><p>third</p></li>
</ul>
<a class="next-btn"><img src="#"></a>
.active {
opacity:1 !important;
transition: .5s;
display: block !important;
}
.copy-box li {
opacity:0;
list-style: none;
display: none;
}
.copy-box li:first {
display: inline;
}
Jquery
`$('.next-btn').click(function(){
if ( $("li.active").hasClass('last') ) {
$('li.active').removeClass('active');
$('.copy-box li').first('li').addClass('active');
return false;
}
else {
$("li.active").removeClass('active').next().addClass('active');
return false;
}
})`

First thing to keep in mind is - display property is not animatable, so you cannot expect it to work with animation/transition.
As you want fade effect, you just need to change opacity from 0 to 1 and vice versa.
One issue you will now run into is that all paragraphs fade in/out at their respective positions and keep on taking space even though they have faded out. You would normally want them to fade in/out all on same position i.e. overlapping each other. For this, you need to set their position to absolute and adjust position as required.
$('.next-btn').click(function(){
if ( $("li.active").hasClass('last') ) {
$('li.active').removeClass('active');
$('.copy-box li').first('li').addClass('active');
return false;
}
else {
$("li.active").removeClass('active').next().addClass('active');
return false;
}
});
.copy-box
{
position: relative;
height: 50px;
}
.copy-box li {
opacity:0;
list-style: none;
position: absolute;
top: 0;
left: 0;
transition: opacity 0.3s ease;
}
.copy-box li.active {
opacity:1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<ul class="copy-box">
<li class="first active"><p>first</p></li>
<li class="second"><p>second</p></li>
<li class="last"><p>third</p></li>
</ul>
<a class="next-btn"><img src="#"></a>

Related

Why button function only works once

i have sidebar if i click on button and then side bar appears from left, and when i click on body side bar hides, but why it is happening only for once.
FIDDLE
HTML
<body>
<div class="site-overlay"></div>
button ☰
<nav id="menu" class="panel" role="navigation">
<ul>
<li>Home</li>
<li>The Ballad of El Goodo</li>
<li>Thirteen</li>
<li>September Gurls</li>
<li>What's Going Ahn</li>
</ul>
</nav>
</body>
JS:
$(document).ready(function() {
$('.menu-link').bigSlide({
easyClose: true
});
$('.menu-link').click(function() {
$('body').addClass('menu-open');
});
});
CSS:
a.menu-link {
float: right;
padding: 20px
}
nav#menu {
background: lightblue;
z-index: 100000000000000
}
.site-overlay {
display: none;
}
.menu-open .site-overlay {
display: block;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 9998;
-webkit-animation: fade 500ms;
animation: fade 500ms;
}
HOW CAN I MAKE IT WORK IT MANY TIMES, instead of only one time.
After the click, you're showing your overlay, but because it has z-index: 9998, the overlay is being placed on top of the button, so when you try to click the button, you're actually clicking on the overlay, not on the button.
You should make an event when the overlay is clicked to remove that class, like this:
$('.site-overlay').click(function() { $('body').removeClass('menu-open') })
This is because the added class is not removed.
You can control it by adding a toggle value for that button.
Instead of addClass put toggle.
On the way you put you will add "menu-open" once and it will never be removed.
you have more information about this here: https://www.w3schools.com/howto/howto_js_toggle_class.asp
You can do it by this JS code.
$(document).ready(function() {
$('.menu-link').bigSlide({
easyClose: true
});
$('.menu-link').click(function() {
event.stopPropagation();
$('body').addClass('menu-open');
});
$('body').click(function(){
$('body').removeClass('menu-open');
})
});

How to make all elements in a node list disappear except target element?

https://codepen.io/m4rsibar/pen/zyPBoz?editors=0110
I've made a codepen example of the effect I'm going for (I've included the code that creates the effect at the very top of the css section), except I want to do it in javascript. (unless there's a way to fix the issues I'm having with the css version)
The issue: the hover is on the div containing the circular elements, if you hover in the div, and aren't on top of an element they all go out of view.
I'm using the :not selector in css to achieve this and to put it on the parent element is the only way I know how to get this to work, I've tried playing around and changing stuff up, to no avail, so I decided to do this with javascript.
In another codepen I tried to simplify as much as possible to try to achieve the effect I'm going for. I've only gotten thus far:
https://codepen.io/m4rsibar/pen/yGPqZM
as you can see when you leave the box it doesn't go back to the original opacity.
Should I be using classes and toggling them?
let lis= document.querySelectorAll('li')
console.log(lis)
lis.forEach(function(li) {
li.addEventListener("mouseover", function(e) {
lis.forEach(function(li) {
e.target.style.opacity="1";
if(e.target.style.opacity==="1"){
li.style.opacity="0.3";
}else{
li.style.opacity="1";
}
});
})
});
This is a simpler approach using only a line of CSS and no JavaScript. Because opacity: 1 is implicit, we don't have to declare that at all, only styles for the non-hovered state.
li {
list-style: none;
background-color: pink;
margin: 2px;
height: 200px;
width: 200px
}
ul {
display: flex;
}
li:not(:hover) {
opacity: 0.3;
}
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
Update
After your feedback and latest example, I took another stab at it. My goal was avoid the double active class on both the ul and active li. It's not ideal from a performance standpoint, but beyond that, it's more JavaScript and CSS to maintain.
What I came up with is a function that detects if an li is the current target (while the mouse is somewhere inside the ul). If the current target is not an li it means that our ul is active but no children are being hovered. I toggle a class accordingly. I like that everything is stored in the ul and we no longer need any li event tracking.
var ul = document.querySelector('ul');
function boxEnter(e) {
this.classList.add('active');
}
function boxLeave(e) {
this.classList.remove('active');
}
function boxMove(e) {
this.classList.toggle('childrenInactive', e.target.tagName !== 'LI');
}
ul.addEventListener('mousemove', boxMove);
ul.addEventListener('mouseenter', boxEnter);
ul.addEventListener('mouseleave', boxLeave);
li {
list-style: none;
background-image: url('https://source.unsplash.com/collection/1163637/200x200');
border-radius: 50%;
margin: 2px;
height: 200px;
width: 200px;
transition: .3s ease;
cursor: crosshair;
will-change: filter, transform;
}
ul {
display: flex;
flex-wrap: wrap;
}
ul.active li {
opacity: .3;
transform: scale(1.1);
filter: blur(5px);
}
ul li:hover,
ul.active.childrenInactive li {
opacity: 1;
transform: scale(1);
filter: blur(0);
}
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
http://jsfiddle.net/j3reaqsw/

On button click show information sliding up and pushing the button upwards using jQuery

I have a foreach loop which displays a list of items using relative and absolute positioning, and on the bottom I would like to add a button (which is at the bottom of the container), which when pressed, shows/hides the given information, pushing the button with itself. I've looked at a couple of stackoverflow questions which had basically the same problem, but I couldn't find a solution which would work in my case.
Here are the codes for the problem (since I've tried a couple solutions, the style positions might not be logical, if you see anything weird please let me know):
The view:
<ul class="events>
#foreach (var events in Model)
{
//absolute positioned div-s
<li>
<div class="eventActions">
<button class="toggleBet">Place bet</button>
#Html.ActionLink("Event details", "Details", "Event", new { eventId = events.Id }, null)
<div class="betContent">#Html.Partial("_BetPartial", new BetViewModel(events))</div>
</div>
</li>
</ul>
The styles:
.events > li .eventActions {
position: absolute;
bottom: 0;
right: 0;
font-size: 24px;
height: 200px;
}
.events > li .toggleBet {
display: inline-block;
}
.events > li .betContent {
background-color: green;
margin: 0;
max-height: 0;
overflow: hidden;
transition: max-height 1s;
}
.events > li .eventActions.open .betContent {
max-height: 300px;
}
The jQuery:
$(".toggleBet").on("click",function(e) {
$(this.parentNode).toggleClass("open");
});
Here is a fiddle which shows what I would like to achieve: http://jsfiddle.net/yeyene/fpPJz/3/ (credits to user yeyene, from this question)
And here is the picture of my project so far (I would like to extend the list items height, move the links lower and make them move up when clicked)
Thank you in advance!
I would suggest forgetting about the .slideToggle method and just using a CSS class on the parent container, then use the max-height property to toggle between open and closed (or just height if you already know exactly how big the container should be when opened).
Here's a simple fiddle showing how you can do this with "pure" CSS by just adding a class to a container: https://jsfiddle.net/8ea3drce/
For good measure, below is the code used in the above JS fiddle:
HTML
<div class="container">
<a class="trigger">Trigger</a>
<ol class="content">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ol>
</div>
CSS
.container {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
}
.container .trigger {
display: inline-block;
background-color: red;
color: white;
cursor: pointer;
padding: 1em;
}
.container .content {
background-color: lightblue;
margin: 0;
max-height: 0; // This suppresses the element's height.
overflow: hidden; // This keeps internal elements from being visible when height is suppressed.
transition: max-height .5s; // This animates the motion when max-height is released. This isn't usually perfect. The closer max-height comes to be with the actual height of the element, the better. Fixed heights might be ideal.
}
.container.open .content {
max-height: 300px; // This releases the element's height to be as large as it would naturally be, up to 500px.
}
Javascript/jQuery
$('.trigger').on('click', function(e) {
$(this.parentNode).toggleClass('open');
})
Using the idea of classtoggling as shown in Dom's answer, setting the absolute position's anchors correctly and deleting the interfering height attribute solved the problem!

Changing the direction in which an ul expands when a button is clicked

So I got a button which when clicked, toggles the visibility of an ul. My button element is a child of my footer, which is fixed to the bottom of my screen. The issue I am having is that when toggled, the ul expands downward instead of up. How would I go about making my ul expand upwards with the first li item starting from the bottom, with each succeeding li item stacking on top of the one before it.
Here is my code:
<footer class="web-stream">
<button type="button" class="active-stream">All</button>
<ul class="feed-list">
<li>feed 1</li>
<li>feed 2</li>
</ul>
</footer>
CSS
.web-stream {
background: green;
width: 100%
height: 2.3em;
margin: auto;
position: fixed;
bottom:0%;
left:0px;
right:0px;
}
.active-stream {
width: 9.5em;
height: 2.3em;
text-align: center;
}
.feed-list {
display: none;
}
Jquery:
jQuery(document).ready(function(){
jQuery(document).on('click','.active-stream', function(event) {
jQuery('.feed-list').toggle('fast'); //use 'slow'
});
});
Here's a JSFiddle.
If I understand your question properly, you just need to reverse the order of the list. If the content is dynamically generated then you could do this when you output the <li> tags. Otherwise the JS in this JSFiddle can accomplish the same thing.
I also moved the button to appear below the list to match your drawing.

css transition background change not fading in smoothly

I am trying to fade in a new background of a header when the user scrolls down. I would like it to fade in smoothly on top of the original background.
Instead what is happening, is that it is removing the original background and then fading in the new one. This makes the transition look ugly when the user scrolls down...
HTML
<div id="navbar" class="navbar">
</div>
CSS
#navbar {
transition: background 0.5s ease-in 0s;
}
.navbar {
background: url("images/nav-bg.png") repeat scroll 0 0 rgba(0, 0, 0, 0);
height: 75px;
margin: 0 auto;
max-width: 1600px;
width: 100%;
position: relative;
z-index: 1;
}
.navbar.fade-blue {
background:#566c75;
}
JS
jQuery(document).ready( function() {
jQuery(window).scroll(function() {
if ( jQuery(window).scrollTop() > 20) {
jQuery(".navbar").addClass("fade-blue");
}
else {
jQuery(".navbar").removeClass("fade-blue");
}
});
});
EDIT: I changed the .fade-blue class as I had two background rules there, I am attempting to fade a background image into a colour.
If you want to fadeIn/fadeOut your background imgae (A) with another one (B), you need to put both in a separate div, and apply to those the opacity transition.
If you need only to fadeOut your backgorund image, you can only put it on separate element inside parent container, and apply to that the opacity transition.
Here an example
How to fade in background image by CSS3 Animation

Categories

Resources