Show More/Show Less CSS JS Animation not working - javascript

I have some texts in my site that I want to show only when the user clicks at the title and then the text appears with an animation, and when the user clicks again at the title the text disappears. I made this code bellow that is working awesome for "show more" but for some reason its not working for "show less"!
function showMore(resp) {
if (document.getElementById(resp).style.maxHeight == "400") {
document.getElementById(resp).style.animation = "showmore 2s ease-in-out reverse";
document.getElementById(resp).style.maxHeight = "0";
} else {
document.getElementById(resp).style.animation = "showmore 2s ease-in-out";
document.getElementById(resp).style.maxHeight = "400";
}
}
#keyframes showmore {
0% {
opacity: 0;
max-height: 0;
}
100% {
opacity: 1;
max-height: 400px;
}
}
.awr {
text-align: left;
margin-left: 10px;
font-size: 17;
color: dimgrey;
max-height: 0;
overflow: hidden;
}
<div class="question" onclick="showMore('awr1')">
<h3>How it Works?</h3>
</div>
<div class="awr" id="awr1">
<p>this is the text that must be hidden.</p>
</div>
Can anyone help me?

I implemented in jQuery but you can easily transform into Javascript.
You can simply add a class & toggle it.
function showMore(resp) {
$("#" + resp).toggleClass("show");
}
.awr {
text-align: left;
margin-left: 10px;
font-size: 17;
color: dimgrey;
height: 0px;
visibility: hidden;
transition: all 0.3s linear;
background-color: #F1F1F1;
}
.show {
visibility: visible;
height: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="question" onclick="showMore('awr1')">
<h3>How it Works?</h3>
</div>
<div class="awr" id="awr1">
<p>this is the text that must be hidden.</p>
</div>

You can do this with css transition instead of animation. Transition basically watches the given properties for changes and animates it from one state to the next. You can also use the all keyword here if you just want everything to animate when it's changed.
.show {
opacity: 1;
max-height: 400px;
}
.awr {
/* your other styles here */
opacity: 0;
max-height: 0;
transition: all 2s;
}
If I'm not mistaken, easing is default behavior, too. Then toggle the class with JavaScript however you usually would. For example, this is my preferred method:
const showMore = resp => document.querySelector(`#${resp}`).classList.toggle('show')

Related

Using CSS to slide text from right to left until the end the text string

I am trying to create a slider component that slides text from right to left, and if the length of the text is longer than the width of the div element keep moving the text until the end of the text is reached.
The code I have just slides until the beginning of the text hits the left end of the div element, and I am trying to have it move until the end of the string hits the right side of the div. The slider component will have both strings which are shorter than the width, in which case the text should move until the left side of the div, if it is longer than the width it should move the end of the string hits the right side of the div.
Any pointers or suggestions on how I can move this text until the end of the text hits the right side of the div?
code:
.slider {
width: 100%;
overflow: hidden;
margin-left: 300px;
background-color: aqua;
}
.slider h2 {
animation: slide-left 10s;
}
#keyframes slide-left {
from {
margin-left: 100%;
}
to {
margin-left: 0%;
}
}
#keyframes slide-right {
to {
transform:translateX(0);
}
}
<div className="slider">
<h2>Hello world, I need a very long text to show how the text will move</h2>
</div>
UPDATE
Using a timer I managed to have an animation that stops when a condition is hit. I sense that the animation speeds-up at the end, so I will try a bit further.
.slider {
width: 100%;
overflow: hidden;
margin-left: 300px;
background-color: aqua;
}
.slider h2 {
animation: slide-left 30s;
animation-play-state: paused;
}
#keyframes slide-left {
from {
margin-left: 0%;
}
to {
margin-left: -1000%;
}
}
#keyframes slide-right {
to {
transform:translateX(0);
}
}
useEffect(() => {
if(executeTimer){
let interval = setInterval(() => {
let sliderElement = document.getElementById('slider');
let sliderWidth = sliderElement.clientWidth;
setCounter(counter + 1);
if(counter === 100){
document.getElementById("slider").style.animationPlayState = "running";
}
if(sliderWidth >= sliderElement.scrollWidth) {
setExecuteTimer(false);
document.getElementById("slider").style.animationPlayState = "paused";
}
},10);
return () => clearInterval(interval);
}
}, [executeTimer, counter]);
return (
<div className="slider" id="slider-container">
<h2 id="slider">Hello world, this is just a little bit longer; no it needs to be just a little bit longer</h2>
</div>
);
I have a similar need so here's the solution I've came up with.
transform: translateX(calc(-100% + 200px));
This did the trick for me.
Only issue is that the speed of the scrolling depends on the length of the text. It doesn't bother me so I won't be trying to 'fix' it.
:root {
--slider-width: 400px;
}
body {
background-color: gray;
}
.slider {
width: var(--slider-width);
height: 40px;
overflow: hidden;
background-color: blue;
white-space: nowrap;
}
.text {
font-size:26px;
display: inline-block;
animation: slide 20s linear infinite;
}
#keyframes slide {
0% {
transform: translateX(0%);
}
50% {
transform: translateX(calc(-100% + var(--slider-width)));
}
100% {
transform: translateX(0%);
}
}
<div class="slider">
<div class="text">
Hello world, I need a very long text to show how the text will move
</div>
</div>
I hope this will help you.
You could change the
margin-left: 0%;
to
margin-left: -200%;
Or some other value which at the very least is -100% or below. If the text may be 3x as wide as the screen then -300% would be needed.

Image won't stay visible for hover effect

Hello and thank you in advance for reading my question.
GOAL: Set image so that once it's scrolled into view it transitions smoothly into a set position - but still reacts to :hover. Using #keyframes and a little JavaScript, I set the image to opacity: 0 and it's final opacity to opacity: .85. Then I added a hover effect in CSS to make it's opacity: 1
The issue is once it's finished with it's transition - it disappears - reverting to it's original opacity which is zero. I managed to make it freeze at .85 with animation-fill-mode: forwards, rather than animation-fill-mode: none, but then it won't respond to :hover
And here's a test snippet of the problem in action:
let observer_img = new IntersectionObserver(updates => {
updates.forEach(update => {
if (update.isIntersecting) {
update.target.classList.add('shift_frame_center_img');
} else {
update.target.classList.remove('shift_frame_center_img');
}
});
}, { threshold: 0 });
[...document.querySelectorAll('.features-img-wrapper img')].forEach(element => observer_img.observe(element));
body {
width: 100%;
height: 100vh;
background-color: lightgrey;
}
/* CHILD */
.features-img-wrapper img {
width: 10rem;
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 8rem;
opacity: 0;
transition: all .5s;
}
/* APPEND-CHILD */
.shift_frame_center_img {
animation: center_img 1s 0.5s none;
}
/* CHILD ON HOVER */
.features-img-wrapper img:hover {
opacity: 1;
transform: scale(1.035);
}
/* KEYFRAMES */
#keyframes center_img {
0% {
transform: translateY(20rem);
}
100% {
transform: translateY(0);
opacity: .85;
}
}
<body>
<div class="features-img-wrapper">
<img src="https://synapse.it/wp-content/uploads/2020/12/test.png">
</div>
</body>
If I could get a hand with this that would be wonderful, I'm a bit of a beginner and have already spent a few hours on this, all feedback welcome. Thank you very much.
Solution 1
To understand why the hover effect was not working with the animation-fill-mode: forwards, read this answer.
You can fix that by adding !important property to the hover styles:
.features-img-wrapper img:hover {
opacity: 1 !important;
transform: scale(1.035) !important;
}
The problem, in this case, is that the transition will not work for hover.
Solution 2
You could remove the animation entirely and add the final state styles to the shift_frame_center_img class.
But you would still need to use the !important property because of the CSS Specificity.
let observer_img = new IntersectionObserver(updates => {
updates.forEach(update => {
if (update.isIntersecting) {
update.target.classList.add('shift_frame_center_img');
} else {
update.target.classList.remove('shift_frame_center_img');
}
});
}, { threshold: 0 });
[...document.querySelectorAll('.features-img-wrapper img')].forEach(element => observer_img.observe(element));
body {
width: 100%;
height: 100vh;
background-color: lightgrey;
}
/* CHILD */
.features-img-wrapper img {
width: 10rem;
transform: translateY(20rem);
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 8rem;
opacity: 0;
transition: all .5s;
}
/* APPEND-CHILD */
.shift_frame_center_img {
transform: none !important;
opacity: .85 !important;
}
/* CHILD ON HOVER */
.features-img-wrapper img:hover {
opacity: 1 !important;
transform: scale(1.035) !important;
}
<body>
<div class="features-img-wrapper">
<img src="https://synapse.it/wp-content/uploads/2020/12/test.png">
</div>
</body>
This snippet removes the need for fill-mode forwards by setting the img to have opacity 1 as its initial state so it will revert to that at the end of the animation.
The animation itself is altered to take 1.5s rather than 1s with the first third simply setting the img opacity to 0 so it can't be seen. This gives the delay effect.
let observer_img = new IntersectionObserver(updates => {
updates.forEach(update => {
if (update.isIntersecting) {
update.target.classList.add('shift_frame_center_img');
} else {
update.target.classList.remove('shift_frame_center_img');
}
});
}, { threshold: 0 });
[...document.querySelectorAll('.features-img-wrapper img')].forEach(element => observer_img.observe(element));
body {
width: 100%;
height: 100vh;
background-color: lightgrey;
}
/* CHILD */
.features-img-wrapper img {
width: 10rem;
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 8rem;
opacity: 0;
transition: all .5s;
opacity: 1;
}
/* APPEND-CHILD */
.features-img-wrapper img {
animation: center_img 1.5s 0s none;
}
/* CHILD ON HOVER */
.shift_frame_center_img:hover {
opacity: 1;
transform: translateY(0) scale(1.035);
}
/* KEYFRAMES */
#keyframes center_img {
0% {
transform: translateY(20rem) scale(1);
opacity: 0;
}
33.33% {
transform: translateY(20rem) scale(1);
opacity: 0;
}
100% {
transform: translateY(0) scale(1);
opacity: .85;
}
}
<body>
<div class="features-img-wrapper">
<img src="https://synapse.it/wp-content/uploads/2020/12/test.png">
</div>
</body>
Note: as each transform setting will reset anything that isn't included both tranlateY and scale are included in each setting.
Outside the SO snippet system it was possible to leave the animation settings untouched by chaining another animation to the front which ran for 0.5s and just set the img to opacity: 0. This did not work in the snippet system (it got into a loop of flashing on and off) hence the introduction of one but extended animation.

Infinite auto scrolling image

I want to make an auto scrolling image. Here is what I've tried.
Scrolling image
Here is my code.
<style>
.scroll_container {
width: 100%;
height: 200px;
/* background-color: #ddd; */
overflow: hidden;
}
.ads_box_holder {
width: 100%;
white-space: nowrap;
min-width:100%;
width: auto !important;
width: 100%;
}
.ads_box {
display: inline-block;
position: relative;
top: 0;
left: 0;
width: 190px;
height: 200px;
padding: 10px 10px;
margin-right: 10px;
}
.ads_box img {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
animation: slide 20s infinite;
}
#keyframes slide {
0%{ transform:translateX(0px) }
10%{ transform:translateX(-200px) }
20%{ transform:translateX(-400px) }
30%{ transform:translateX(-600px) }
40%{ transform:translateX(-800px) }
50%{ transform:translateX(-1000px) }
60%{ transform:translateX(-1200px) }
70%{ transform:translateX(-1400px) }
80%{ transform:translateX(-1600px) }
90%{ transform:translateX(-1800px) }
100%{ transform:translateX(0px) }
}
<style>
<div class="scroll_container">
<div class="ads_box_holder">
<div class="ads_box"><img src="images/ads.png"></div>
<div class="ads_box"><img src="images/blur.jpg"></div>
<div class="ads_box"><img src="images/foot.jpg"></div>
<div class="ads_box"><img src="images/body.jpg"></div>
<div class="ads_box"><img src="images/s.png"></div>
<div class="ads_box"><img src="images/menu.jpg"></div>
<div class="ads_box"><img src="images/face.jpg"></div>
<div class="ads_box"><img src="images/c.jpeg"></div>
<div class="ads_box"><img src="images/foot2.jpg"></div>
<div class="ads_box"><img src="images/b.jpg"></div>
</div>
</div>
Now, I used keyframe css. So, when images move to left one after another, there has empty space in the right side as shown in below
---------
| |
| image | empty space are left here
| |
---------
In the reality, I want to add my images dynamically and images may be over 20 images. So, I'm not sure this keyframes is ok or not when images add dynamically.
I want to replace that empty space to the all of the images inside this box.
So, there is no empty space left and images are always scroll one after another.
But, I don't know how to replace images when space found inside ads_box_holder div.
And I remove css animation and also tried with javascript like this.
<script>
$(document).ready(function(){
var childCount = $(".ads_box_holder :visible").children().length;
var move = 0;
var hideImageTime = 0;
window.setInterval(function(){
hideImageTime += 1;
move += 200;
$(".ads_box_holder").css({
"margin-left":-move+"px",
});
if(hideImageTime > childCount) {
jQuery('.ads_box_holder .ads_box').each(function(){
var next = jQuery(this).next();
count += 1;
if (!next.length) {
next = jQuery(this).siblings(':first');
}
next.children(':first-child').clone().appendTo(jQuery(this));
});
}
},2000);
});
</script>
But it is the same result when I use keyframe css.
NOTE: The image moving style is ok but I just want to place all images when empty space found inside ads_box_holder.
I have no idea how to achieve what I want. I'm really appreciate for any suggestion.
Finally I got what I want. Clone first child and append at last of ads_box_holder and remove first child.
$(document).ready(function(){
function animation() {
$('.ads_box_holder').children(':first').clone().appendTo(".ads_box_holder");
$('.ads_box_holder').children(':first').css({
"margin-left":"-204px",
"-webkit-transition": "all 0.7s ease-out",
"-moz-transition": "all 0.7s ease-out",
"-ms-transition": "all 0.7s ease-out",
"-o-transition": "all 0.7s ease-out",
"transition": "all 0.7s ease-out"
});
setTimeout(function(){$('.ads_box_holder').children(':first').remove()},1500);
}
window.setInterval(animation,2000);
});
I hope it will help for someone.

Trigger opacity transition on mouse in and out

I want to trigger a opacity transition. If an element is hovered by the cursor, the cursor shall fade out, change its background-image and then fade in again. I wanted to achieve that by adding and removing a css class. It's not working, what is wrong?
js fiddle
HTML
<div class="wrapper">
<div class="cursor">
</div>
<div id="grey">
</div>
</div>
CSS
.wrapper {
width: 100%;
height: 100%;
background-color: lightgrey;
padding: 60px;
cursor: none;
}
#grey {
width: 100px;
height: 100px;
background: grey;
}
.cursor {
position: fixed;
width: 20px;
height: 20px;
pointer-events: none;
opacity: 0;
-webkit-transition: opacity .3s; /* Safari */
transition: opacity .3s;
}
.red {
background: red;
opacity: 1;
}
.green {
background: green;
opacity: 1;
}
JS
$('.wrapper').on('mousemove', function(e){
$('.cursor').css('left', e.clientX-10).css('top', e.clientY -10);
if ($.contains($('.wrapper')[0], e.target)){
$('.cursor').removeClass('green').addClass('red');
}else{
$('.cursor').removeClass('red').addClass('green');
}
});
DEMO HERE
Ok, here you go. You need to keep track of 2 things here which you already achieved partially and also wait for fadeOut to complete and add a callback for adding and removing respective class
Whether cursor has entered element
Whether cursor has left element
Below is how you could actually do it.
var entered=false;//global variables to show the position of cursor
var left=false;
$('.wrapper').on('mousemove', function(e){
$('.cursor').css('left', e.clientX-10).css('top', e.clientY -10);
if ($.contains($('.wrapper')[0], e.target)){
if(!entered)
{
//just to do it once and not on every mousemove you need to check here whether
//it has already entered and moving inside the element
entered=true;
left=false;//to check the vice versa operation
$('.cursor').fadeOut('fast',function(){
//callback function after fadeOut completes
$(this).removeClass('green').addClass('red');
}).fadeIn('fast');
}
}else{
if(!left)
{
left=true;
entered=false;
//same goes here too
$('.cursor').fadeOut('fast',function(){
$(this).removeClass('red').addClass('green');
}).fadeIn('fast');
}
}
});
you have to change background color , not opacity ( opacity is always 1 )
CSS
.cursor {
position: fixed;
width: 20px;
height: 20px;
pointer-events: none;
opacity: 0;
-webkit-transition: background-color .3s; /* Safari */
transition: background-color .3s ;
}
.red {
background-color: red;
opacity: 1;
}
.green {
background-color: green;
opacity: 1;
}
So you said your question is wrong, it is "no, I just made it easier for hier, in reality it is an background image" - so you transition between two background-images.
Here is how you do it:
You can not do it with CSS transition in ONE element/div
You will have to make two divs wich one background each
Increase the zIndex of the div you want to fade out in by one
Fade out div, while the new div stays at opacity: 1

Fade effect attribute/function in javascript custom script?

I need to add a fade effect on my javascript function
Javascript
<script type="text/javascript">
window.onload=function() {
loginBtn = document.getElementById('loginBtn');
fader = document.getElementById('login_fader');
login_box = document.getElementById('login_box');
closebtn = document.getElementById('closelogin');
loginBtn.onclick=function(){
fader.style.display = "block";
login_box.style.display = "block";
}
closebtn.onclick=function() {
fader.style.display = "none";
login_box.style.display = "none";
}
}
</script>
HTML
<div id="login_fader"> </div>
<div id="login_box">
<table class="table-login">
<th>Login or Register</th>
<th><a id="closelogin">X</a></th>
<tr>
<td>Login</td>
<td>Register</td>
</tr>
</table>
</div>
CSS
<style type="text/css">
#loginBtn {
float: right;
margin-top: -6%;
cursor:pointer;
}
#login_fader {
background: black;
opacity: .5;
-moz-opacity: .5;
-filter: alpha(opacity=50);
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 5;
display: none;
}
#login_box {
width: 320px;
height: 200px;
border: 1px white solid:
background: #5a5a5a;
position: fixed;
top: 25%;
left: 35%;
z-index: 10;
display: none;
}
.table-login {
background: #FFF;
border-radius: 8px;
box-shadow: 0 0 5px 2px;
opacity: 0.95;
}
#closelogin {
float:right;
cursor:pointer;
}
</style>
Js fiddle
http://jsfiddle.net/U3n4j/
I have tried using the transition properties from css3 and tried applying both to login_box and login_fader.
I found some functions on the net but don't know how to link them to my already made function and i was thinking if there are any properties directly that i can link them to my function.
Proper way to fade in a static box in css3 and js 1.7 ++
This is a example using only webkit and modern javascripts classList.add
but you can add the other prefixes.-moz,-ms,-o
in this example i show only the animation.
css
.box{
width:100%;
height:100%;
position:fixed;
left:0;top:-100%;/*notice TOP -100%*/
opacity:0;
-webkit-transition:opacity 700ms ease,top 0 linear 700ms;/*notice TOP delay*/
background-color:rgba(0,0,0,0.7);
}
.box.active{
-webkit-transition:opacity 700ms ease,top 0 linear 0;
/*top transition not needed but could help to understand*/
top:0;
opacity:1;
}
js
function show(){
box.classList.add('active');
}
function hide(){
box.classList.remove('active');
}
var box=document.getElementsByClassName('box')[0],
button=document.getElementsByTagName('button')[0];
button.addEventListener('click',show,false);
box.addEventListener('click',hide,false);
DEMO
http://jsfiddle.net/RAu8Q/ not working anymore
http://jsfiddle.net/RAu8Q/17/ new syntax 10-2015
if you have any questions just ask.
I can't tell exactly what effect you're trying to achieve, but if you're going to use CSS transitions, then you need to be transitioning between numerical properties. I.e., you can't expect a fade to occur simply by transitioning from display:block to display:none. You'd want to use opacity instead.
First of all, don't try to use css transitions in conjunction with display property, that won't work! Instead, try transitioning other properties. Let's take opacity for instance (we'll simulate display: none/block functionality by setting opacity to 0/1)
Secondly, set the start value for opacity to 0 on the desired HTML element (the one you'd like to animate). Specify which property to animate (opacity in our case):
transition: opacity 1s;
-moz-transition: opacity 1s;
-webkit-transtion: opacity 1s;
When the login button is clicked, set opacity to 1:
loginBtn.onclick=function() {
fader.style.opacity = 1;
login_box.style.opacity = 1;
}
When the close button is clicked, set opacity back to 0:
closebtn.onclick=function() {
fader.style.opacity = 0;
login_box.style.opacity = 0;
}
Link to fiddle.
I believe that what you want to do needs css animations. So just create an animation class that fades out the target element and apply it after the user logs in.
#keyframes fadeOut {
from: {
opacity:1;
},
to: {
opacity:0;
}
}
then use apply it on the class
.fadeOut {
animation:fadeOut 0.25s forwards;
}
EXAMPLE
http://jsfiddle.net/zgPrc/

Categories

Resources