Smooth transition on collapsing element with angular & css only - javascript

I am trying to add a collapsable element to my app. I don't want to use jQuery or any other dependency than Angular.
I have built a very simple demo here: http://jsfiddle.net/eg69cfub/2/
The elements are displayed/hidden properly the only problem is the transition.
I don't understand why it is so abrupt, I'd like it to be smooth.
How can I fix this please?
HTML:
<div ng-app>
<div>
<ul>
<li ng-repeat='test in [1, 2, 3]' ng-controller='accordionCtrl'>
<div class='header' ng-click='isVisible = !isVisible'> Hello {{ test }}</div>
<div class='body' ng-class='{ collapsed: isVisible }'> Goodbye </div>
</li>
</ul>
</div>
</div>
CSS:
li {
list-style: none;
}
.header {
width: 100%;
background-color: red;
}
.body {
width 100%;
background-color: blue;
display: block;
min-height: 1px;
transition: all ease 3s;
overflow: hidden;
}
.collapsed {
min-height: 0;
height: 0;
}
JS:
var myApp = angular.module('myApp',[]);
function accordionCtrl($scope) {
$scope.isVisible = false;
}

In Angular, you can use ng-animate to perform smooth animations with ng-show directive (along with many other directives). Here is your fiddler with animations: http://jsfiddle.net/fu2jw6j1/
Your HTML:
<div ng-app>
<div>
<ul>
<li ng-repeat='test in [1, 2, 3]' ng-controller='accordionCtrl'>
<div class='header' ng-click='$scope.isVisible=!$scope.isVisible'> Hello {{ test }}</div>
<div class='box' ng-show="$scope.isVisible" ng-animate="'box'"> Goodbye </div>
</li>
</ul>
</div>
And here's the CSS:
li {
list-style: none;
}
.header {
width: 100%;
background-color: red;
}
.box {
width 100%;
background-color: blue;
display: block;
min-height: 1px;
transition: all ease 3s;
overflow: hidden;
height: 20px;
}
.box-show-setup, .box-hide-setup {
-webkit-transition:all linear 0.3s;
-moz-transition:all linear 0.3s;
-ms-transition:all linear 0.3s;
-o-transition:all linear 0.3s;
transition:all linear 0.3s;
}
.box-show-setup { height: 0; }
.box-show-setup.box-show-start { height:20px }
.box-hide-setup {height: 0; }
.box-hide-setup.box-hide-start { height: 0px; }
You can find more about ng-animate directive in Angular's documentation: https://docs.angularjs.org/api/ngAnimate

Related

CSS transition does not animate on toggle

I made a little accordion that I would like to animate.
I have the following code but the animation as written is not working and I don't know why.
I know it's somehow complicated to make the height to work, but I managed to find a work around using max-height.
I would like my div to have an animated width and height to make it feel like you unfold it.
The weird behaviour is that if you resize the window, everything seems animated...
document.getElementById("ping").onclick = function () {
console.log(this);
this.children[1].classList.toggle("active");
};
.content.active {
display: block;
max-height: 200px;
transition-property: width, max-height;
transition-duration: 400ms, 100ms;
transition-timing-function: cubic-bezier(0.305, 0, 0, 1.015);
transition-delay: 400ms, 100ms;
width: 40vw;
background: orange;
}
.content {
width: 0px;
max-height: 0px;
transition-property: width, max-height;
transition-timing-function: cubic-bezier(0.305, 0.000, 0.000, 1.015);
transition-duration: 400ms, 100ms;
transition-delay: 100ms, 100ms;
background: orange;
display: none;
}
.cat.active {
background: orange;
}
<section id="item0">
<div id="ping" class="cat">
<div class="title active" style="">
<a>Open</a>
</div>
<div class="content" style="">
<div>
<div class="images">
first test <br>
another
</div>
</div>
</div>
</section>
1.) Only apply the transition parameters to the initial state, not to the .active state/class.
2.) Don't use display:none and block, but instead transition between max-height: 0 and width: 0 and their ".active" values.
3.) To hide the overflowing contents (which would still be visible), apply overflow: hidden to the initial state
document.getElementById("ping").onclick = function () {
console.log(this);
this.children[1].classList.toggle("active");
};
.content.active {
max-height: 200px;
width: 40vw;
}
.content {
max-height: 0;
width: 0px;
transition-property: width, max-height;
transition-duration: 400ms, 100ms;
transition-timing-function: cubic-bezier(0.305, 0, 0, 1.015);
transition-delay: 400ms, 100ms;
background: orange;
overflow: hidden;
}
.cat.active {
background: orange;
}
<section id="item0">
<div id="ping" class="cat">
<div class="title active" style="">
<a>Open</a>
</div>
<div class="content" style="">
<div>
<div class="images">
first test <br>
another
</div>
</div>
</div>
</section>

Bootstrap slide box

Hello i have found a nice javascript effect of box in
link 1
link 2
But it's for wordpress only.
Is it possible to make same slide box with Bootstrap and javascript/jquery?
This is a very simple example of recreating the slide down effect on the links you posted. It can be done fairly easily just using html and css.
<div tabindex="1" class="mainbox">
<h1>
This is a box with hidden content
</h1>
</div>
<div class="hidden">
<h2>
I am no longer hidden
</h2>
</div>
div {
width:500px;
height:200px;
background:#3c3c3c;
color:black;
}
.mainbox {
cursor:pointer;
position:relative;
z-index:1;
}
.mainbox:hover {
outline:none;
}
.hidden {
position:absolute;
top:0;
z-index:-1;
opacity:0.75;
-webkit-transition:top 1s;
-moz-transition:top 1s;
}
.mainbox:hover + .hidden {
top:200px;
-webkit-transition:top 1s;
}
https://jsfiddle.net/tz3vjLg7/
Try this; with this approach you can move the main container to any place you want, add margins, paddings, etc to main-container without having to also re position the sliding panels inside
.main-container {
position: relative;
margin-left: 50px;
}
.main-panel {
position: absolute;
width: 250px;
height: 150px;
background-color: lightgrey;
z-index: 1
}
.slide-panel {
position: absolute;
width: 250px;
height: 150px;
background-color: blue;
opacity: 0;
transition: all 0.3s ease-in-out;
}
.main-container:hover .slide-panel {
opacity: 1;
transform: translateY(150px)
}
<div class="main-container">
<div class="main-panel"></div>
<div class="slide-panel">Slide Panel</div>
</div>

This chain of CSS animation should run infinitely but it doesn't

I have this simple set of CSS animations that I want to run indefinitely. But for some reason, it only runs twice and stops.
Here's a CodePen example.
Here is how I implement it using Jquery (this is also seen on the code)
$('#slide1').one(animationEnd, () => {
$('#slide1').css('display', 'none').removeClass('animate-1')
$('#slide2').css('display', '').addClass('animate-2')
})
$('#slide2').one(animationEnd, () => {
$('#slide2').css('display', 'none').removeClass('animate-2')
$('#slide3').css('display', '').addClass('animate-3')
})
$('#slide3').one(animationEnd, () => {
$('#slide3').css('display', 'none').removeClass('animate-3')
$('#slide1').css('display', '').addClass('animate-1')
})
See that #slide3 should revert to #slide1 for animation. It did, but it stops after 2 cycles.
You have defined counter variable as const, but it needs to be let to allow later reassignment.
let counter = 0;
Also you need to use $.on instead of $.one when binding to the animation end. $.on is used to bind handler to some event (every time it occurres), while $.one is used for one time binding only (run the handler first time the event occurres, but no more that that).
Here is your updated example:
https://codepen.io/anon/pen/WXNOKQ
answer already given and accepted, this is only for infos since the javaScript takes only three boxes into account.
animation-delay can be used to keep animation looping infinitly:
body {
color: #FFFFFF;
background-color: #27292d;
overflow: hidden;
background: #27292d url('bg.jpg') no-repeat fixed center;
font-family: 'Roboto', sans-serif;
}
.slider-container {
position: absolute;
right: 0;
top: 40%;
}
.slider-content {
position: relative;
font-size: 32px;
text-transform: uppercase;
}
.boxes {
float: left;
padding: 10px 20px;
margin: 5px;
position: relative;
}
.sub-box {
clear: both;
margin-left: 60px;
}
.sub-box span {
color: #000000;
padding: 10px 20px;
background-color: #FFFFFF;
}
.box1 {
background-color: #FF4F80;
}
.box2 {
background-color: #4CA2F0;
}
.box3 {
background-color: #53CEC8;
}
#keyframes heartbeat {
0% {
transform: translate(100px, 200px) scale(0)
}
50% {
transform: translate(100px, 200px) scale(0)
}
60% {
transform: translate(-100px) scale(1.5)
}
70% {
transform: translate(-100px) scale(1.5)
}
80% {
transform: translate(-100px) scale(1.5)
}
100% {
transform: translate(100px, -200px) scale(0)
}
}
.slider-single {
position: absolute;
right: 0;
width: 400px;
height: 50px;
margin: 20px;
transform: scale(0);
}
.animate-1 {
transition: 300ms cubic-bezier(.17, .67, .55, 1.43);
animation: ease-out heartbeat 6s -3s infinite;
}
.animate-2 {
transition: 300ms cubic-bezier(.17, .67, .55, 1.43);
animation: ease-out heartbeat 6s -1s infinite;
}
.animate-3 {
transition: 300ms cubic-bezier(.17, .67, .55, 1.43);
animation: ease-out heartbeat 6s 1s infinite;
}
<div class="slider-container">
<div class="slider-content">
<div id='slide1' class="slider-single animate-1">
<div class=''>
<p class='boxes box1'>Pink Header</p>
</div>
<div class='sub-box'>
<span>White Header</span>
</div>
</div>
<div id='slide2' class="slider-single animate-2">
<div>
<p class='boxes box2'>Another Header</p>
</div>
<div class='sub-box'>
<span>subheader</span>
</div>
</div>
<div id='slide3' class="slider-single animate-3">
<div>
<p class='boxes box3'>10 more to go</p>
</div>
</div>
</div>
</div>
<div class="slider-container">
<div class="slider-content">
<div id='slide1' class="slider-single animate-1">
<div class=''>
<p class='boxes box1'>Pink Header</p>
</div>
<div class='sub-box'>
<span>White Header</span>
</div>
</div>
<div id='slide2' class="slider-single" style='display:none;'>
<div>
<p class='boxes box2'>Another Header</p>
</div>
<div class='sub-box'>
<span>subheader</span>
</div>
</div>
<div id='slide3' class="slider-single" style='display:none;'>
<div>
<p class='boxes box3'>10 more to go</p>
</div>
</div>
</div>
</div>

css - show element then animate it (trigger by jquery addClass) [duplicate]

This question already has answers here:
jQuery click toggle animation
(2 answers)
Closed 5 years ago.
i'm trying to animate an element with css.
First this element is hidden. A javascript event will show it and i want it to be animated.
The expected animation is letter-spacing -2px to letter-spacing 3px
$('#btn').click(function() {
$('#wrapper').addClass('animate');
});
#wrapper {
display: none;
/* I dont want the wrapper to be visible before the event */
}
#wrapper .message {
display: none; /* the message is not visible before the event */
letter-spacing: -2px;
transition: all 3s;
}
#wrapper.animate .message {
display: block;
letter-spacing: 3px;
}
#wrapper.animate {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
<div id="wrapper" class="col-sm-12 no-padding">
<div class="text-center font-size-20">
<span class="message">
Message to show and animate
</span>
</div>
</div>
<button id="btn">Click me to animate</button>
Thanks
I found the real issue:
When using a unique class to show AND change the property to animate, the browser will directly show the element with the new property (letter-spacing 3px).
To make it work, I can add a timeout.
I'm still waiting for a better solution if it exists
$('#btn').click(function() {
$('#wrapper').addClass('show');
window.setTimeout(function() {
$('.message').addClass('animate');
}, 500);
});
#wrapper {
display: none;
/* I dont want the wrapper to be visible before the event */
}
#wrapper .message {
display: none; /* the message is not visible before the event */
letter-spacing: -2px;
transition: all 3s;
}
#wrapper.show .message {
display: block;
}
#wrapper .message.animate {
letter-spacing: 3px;
}
#wrapper.show {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
<div id="wrapper" class="col-sm-12 no-padding">
<div class="text-center font-size-20">
<span class="message">
Message to show and animate
</span>
</div>
</div>
<button id="btn">Click me to animate</button>
Have you tried to change the css value of display instead of add a class ?
$('#btn').click(function() {
$('#wrapper').css('display', 'block);
});
And look at this : https://www.w3schools.com/cssref/pr_class_visibility.asp
visibility property can help you.
Here you go with the solution https://jsfiddle.net/5h1dgfpu/
$('#btn').click(function() {
$('#wrapper').addClass('animate');
});
#wrapper .message {
display: block; /* the message is not visible before the event */
letter-spacing: -2px;
visibility: hidden;
opacity: 0;
transition: visibility 0s, opacity 0.5s linear;
}
#wrapper.animate .message {
display: block;
letter-spacing: 3px;
visibility: visible;
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper" class="col-sm-12 no-padding">
<div class="text-center font-size-20">
<span class="message">
Message to show and animate
</span>
</div>
</div>
<button id="btn">Click me to animate</button>
You can move the item using margin in the css, and for delay, you can use setTimeOut function in javascript, like below
HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper" class="col-sm-12 no-padding">
<div class="text-center font-size-20">
<span class="message">
Message to show and animate
</span>
</div>
</div>
<button id="btn">Click me to animate</button>
CSS
#wrapper .message {
display: none; /* the message is not visible before the event */
transition:all 300ms ease-in-out;
margin-left:0px;
}
#wrapper.animate .message {
display: block;
letter-spacing: 3px;
visibility: visible;
margin-left:30px;
}
JAVA-SCRIPT
$('#btn').click(function() {
$('#wrapper span').show();
setTimeout(function() {
$('#wrapper').addClass('animate');
}, 1000);
});
Here is a fiddle for you
$(document).ready(function(){
$("#click").click(function(){
$("#text").css("visibility","visible");
$("#text").animate({
opacity: '1'
});
});
});
#text{
font-family: monospace;
font-size: 25px;
display: block;
visibility: hidden;
opacity: 0.2;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main">
<p id="text"> Message to show and animate</p>
</div>
<button id="click">Click & Animate</button>

Trying to fadeIn .css ('background-image", __)

I'm trying to get a background image to swap between other images when divs are hovered over. What do I need to change to make the images fade between one another? Code looks like this:
$('#mainUK').mouseenter(function(){
$('.splash').css("background-image","url(Assets/Images/Splash/UK.jpg)");
});
$('#mainJapan').mouseenter(function(){
$('.splash').css("background-image","url(Assets/Images/Splash/Japan.jpg)");
});
etc..
CSS:
.splash {
background-image: url(Assets/Images/Splash/UK.jpg);
background-repeat:no-repeat;
background-position:center center;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
width:100%;
height:100%;
position:fixed;
}
html:
<div class="splash_bg">
<div class="splash">
<div class="back_arrow"><h3>←</h3></div>
<div class="main_nav">
<ul>
<li class="main_headings"><div id="mainUK"><h3>The UK</h3></div></li>
<li class="main_headings_sub"><div id="mainEngland"><h3>England</h3></div></li>
<li class="main_headings_sub"><div id="mainScotland"><h3>Scotland</h3></div></li>
<li class="main_headings_sub"><div id="mainWales"><h3>Wales</h3><div></li>
<li class="main_headings"><div id="mainJapan"><h3>Japan</h3></div></li>
<li class="main_headings"><div id="mainChina"><h3>China</h3></div></li>
<li class="main_headings"><div id="mainHK"><h3>Hong Kong</h3><div></li>
<li class="main_headings"><div id="mainMalaysia"><h3>Malaysia</h3><div></li>
</ul>
</div>
</div>
</div>
EDIT:
So I've solved it. Thanks to #demux/#luciferous as you pointed me in the right direction. If there's a better way to do this please feel free to let me know. Thank again.
html:
<div class="splash">
<div class="splash_UK"></div>
<div class="splash_Japan"></div>
<div class="splash_China"></div>
<div class="splash_HK"></div>
<div class="splash_Malaysia"></div>
<div class="back_arrow"><h3>←</h3></div>
<div class="main_nav">
<ul>
<li class="main_headings"><div id="mainUK"><h3>The UK</h3></div></li>
<li class="main_headings_sub"><div id="mainEngland"><h3>England</h3></div></li>
<li class="main_headings_sub"><div id="mainScotland"><h3>Scotland</h3></div></li>
<li class="main_headings_sub"><div id="mainWales"><h3>Wales</h3><div></li>
<li class="main_headings"><div id="mainJapan"><h3>Japan</h3></div></li>
<li class="main_headings"><div id="mainChina"><h3>China</h3></div></li>
<li class="main_headings"><div id="mainHK"><h3>Hong Kong</h3><div></li>
<li class="main_headings"><div id="mainMalaysia"><h3>Malaysia</h3><div></li>
</ul>
</div>
</div>
CSS: (I've adjusted the z-index either side of the divs to 1 & 3 respectively.)
.splash_UK, .splash_Japan, .splash_China, .splash_HK, .splash_Malaysia{
background-repeat:no-repeat;
background-position:center center;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
width:100%;
height:100%;
position:fixed;
opacity:0;
z-index:2;
-webkit-transition: opacity 200ms linear;
-moz-transition: opacity 200ms linear;
-o-transition: opacity 200ms linear;
-ms-transition: opacity 200ms linear;
transition: opacity 200ms linear;
}
.splash_UK {
background-image: url(Assets/Images/Splash/UK.jpg);
}
.splash_Japan {
background-image: url(Assets/Images/Splash/Japan.jpg);
}
.splash_China {
background-image: url(Assets/Images/Splash/China.jpg);
}
.splash_HK {
background-image: url(Assets/Images/Splash/HK.jpg);
}
.splash_Malaysia {
background-image: url(Assets/Images/Splash/Malaysia.jpg);
}
JS:
$('#mainJapan').mouseenter(function() {
$('.splash_Japan').css('opacity', '1');
$('.splash_UK,.splash_China,.splash_HK,.splash_Malaysia').css('opacity','0');
});
$('#mainUK').mouseenter(function() {
$('.splash_UK').css('opacity', '1');
$('.splash_Japan,.splash_China,.splash_HK,.splash_Malaysia').css('opacity','0');
});
$('#mainChina').mouseenter(function() {
$('.splash_China').css('opacity', '1');
$('.splash_Japan,.splash_UK,.splash_HK,.splash_Malaysia').css('opacity','0');
});
$('#mainHK').mouseenter(function() {
$('.splash_HK').css('opacity', '1');
$('.splash_Japan,.splash_China,.splash_UK,.splash_Malaysia').css('opacity','0');
});
$('#mainMalaysia').mouseenter(function() {
$('.splash_Malaysia').css('opacity', '1');
$('.splash_Japan,.splash_China,.splash_HK,.splash_UK').css('opacity','0');
});
A CSS only solution:
.splash {
font-family: sans-serif, verdana;
position: relative;
width: 200px;
height: 200px;
}
.splash-item-container {
padding: 0;
}
.splash-item {
margin: 2px 0;
display: block;
list-style-type: none;
background-color: rgba(150, 150, 150, 0.2);
line-height: 1.5em;
}
.splash-item a {
display: block;
color: black;
text-decoration: none;
}
.splash-item:before {
display: block;
content: '';
transition: background-color 1s;
position: absolute;
top: 0;
left: 0;
width: 200px;
height: 200px;
z-index: -1;
}
.splash-item-red:hover:before {
background-color: #ffdddd;
}
.splash-item-green:hover:before {
background-color: #ddffdd;
}
.splash-item-blue:hover:before {
background-color: #ddddff;
}
<div class="splash">
<ul class="splash-item-container">
<li class="splash-item splash-item-red">Red</li>
<li class="splash-item splash-item-green">Green</li>
<li class="splash-item splash-item-blue">Blue</li>
</ul>
</div>
If you must use jQuery:
$(function() {
$('.main-nav li').hover(function() {
$('.splash').removeClass('cats-bg sports-bg').addClass($(this).data('class'));
});
});
.splash {
transition: background-image 1s;
}
.splash.cats-bg {
background-image: url(http://lorempixel.com/400/200/cats/);
}
.splash.sports-bg {
background-image: url(http://lorempixel.com/400/200/sports/);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="splash">
<h3 class="black-arrow">←</h3>
<ul class="main-nav">
<li data-class="cats-bg">Cats</li>
<li data-class="sports-bg">Sports</li>
</ul>
</div>
One solution would be to use multiple values in the background-image property and toggle them on mouseenter and mouseleave events.
$(document).ready(function() {
var tar = document.getElementById('target');
var bgimage = $(tar).css('background-image');
var bgimagearr = bgimage.split(',')
$(tar).on('mouseenter', function() {
$(this).css('background-image', bgimagearr[0])
});
$(tar).on('mouseleave', function() {
$(this).css('background-image', bgimagearr[1])
});
})
css would be something like
#target{
width:500px;
height: 500px;
background-image:url('./images/one.jpeg'),url('./images/two.jpeg');
}
But it would i reckon it would be better to have two different elements altogether and achieve this easily, if your requirements are flexible,

Categories

Resources