I have a similar issue as CSS Transition not firing when adding class to body (Firefox) but I can seem to find a way to solve it targeting the element in different ways or removing classes.
Here is what I have:
Markup:
<div class="ball b40 first">
<a class="ffx-fx" href="javascript:void(0)">
</a>
</div>
css:
.ffx-fx {
-webkit-transition: all 1.5s ease-in-out;
-moz-transition: all 1.5s ease-in-out;
-o-transition: all 1.5s ease-in-out;
-ms-transition: all 1.5s ease-in-out;
transition: all 1.5s ease-in-out;
}
.b40 a {
width:220px;
height:220px;
background: url(../images/temp/1_a.jpg) center center;
background-size: 100% 100% !important;
}
.b40 .b40-rotated {
width:220px;
height:220px;
background: url(../images/temp/1_b.jpg) center center !important;
}
js:
window.setInterval(function() {
$( ".b40 .ffx-fx" ).toggleClass( "b40-rotated" );
}, 5000);
I don't believe you can switch out background-images with transitions. At least I haven't tried it. How I usually handle this situation is have two inner divs--one with the on hover class and one with the off class. Then on hover, I change opacity. Opacity transition works. Sooo something like this...
HTML
<div class="container">
<a href="">
<div class="off_state"></div>
<div class="on_state"></div>
</a>
</div>
CSS
.container{position:relative;}
.off_state, .on_state{
position:absolute;
top:0;
left:0;
transition: all 1s;
}
.off_state, .container:hover .on_state{opacity:0.0;filter:alpha(opacity=0);}
.container:hover .on_state{opacity:1.0;filter:alpha(opacity=100);}
It's a rough version, but that's how I've always done it.
NOTE: jQuery UI also has the ability to add a class slowly. You can view it here: http://jqueryui.com/addClass/. It would probably be easier to use.
Related
So I'm trying to create a slide effect for some bootstrap badges I am using to display some hierarchical data relationships using AngularJS.
I have a slider-effect for showing new sub-categories, and hiding sub-categories that are already open. Now this is all working well, except it seems to do the "showing slide" first, and then the "hiding slide" second, which is the opposite of what you would like.
ie. When you hit a badge for a different category, it should first slide closed the already showing other sub-categories, and then open the new sub-categories to be shown.
The html looks like this:
<div ng-controller="MainController">
<ul ng-repeat="category in categories">
<li ng-if="category.category_type=='parent'" ng-show="category.category_show">
<span class="badge badge-p" ng-click="updateResults(category)">{{category.category_name}}</span>
</li>
<li ng-if="category.category_type == 'child'" ng-show="category.category_show" class="badge-slider">
<span class="badge badge-c">{{category.category_name}}</span>
</li>
</ul>
</div>
The relevant CSS looks like this:
.badge-slider {
max-height: 100px;
-webkit-transition: max-height linear 0.2s;
-moz-transition: max-height linear 0.2s;
-o-transition: max-height linear 0.2s;
transition: max-height linear 0.2s;
overflow:hidden;
}
.badge-slider.ng-hide {
max-height: 0px;
}
I have mocked up a simplified plnkr example to demonstrate what is happening here: http://plnkr.co/edit/S255yk0N2wAXrfq7Mqd6
EDIT 1: Thanks to the help of sbedulin I was able to get this working beautifully. I've also updated the code so that the subcategories dynamically indent based on how far down the tree they are. You can find my newly mocked up version here: http://plnkr.co/edit/5I1pU0TZo6AjHJTbBuG9
I was able to achieve the desired effect by only modifying your CSS:
/* Styles go here */
.badge-slider {
max-height: 100px;
-webkit-transition: max-height linear 1.2s;
-moz-transition: max-height linear 1.2s;
-o-transition: max-height linear 1.2s;
transition: max-height linear 1.2s;
transition-delay: 0.0s;
overflow:hidden;
}
.badge-slider.ng-hide {
-webkit-transition: max-height linear 0.0s;
-moz-transition: max-height linear 0.0s;
-o-transition: max-height linear 0.0s;
transition: max-height linear 0.0s;
max-height: 0px;
}
I set your transition lengths to 1.2s in .badge-slider just so you can clearly see that it is working. The key is adding in transition-delay: 0.0s; to .badge-slider and adding transition lengths of 0.0s to .badge-slider.ng-hide. Hope this helps!
Main problem is that <ul ng-repeat="category in categories"> generates multiple <ul> elements, ngRepeat should be placed on <li>s.
After some refactoring HTML will look like:
<ul>
<li ng-repeat="category in categories"
ng-init="isChild = category.category_type == 'child'"
ng-show="category.category_show"
class="badge-slider">
<span ng-click="isChild || updateResults(category)"
ng-bind="category.category_name"
class="badge {{ isChild ? 'badge-c' : 'badge-p' }}">
</span>
</li>
</ul>
CSS
.badge-slider {
-webkit-transition: all 0.2s linear 0.2s;
-moz-transition: all 0.2s linear 0.2s;
-o-transition: all 0.2s linear 0.2s;
transition: all 0.2s linear 0.2s;
line-height: 30px;
overflow:hidden;
max-height: 30px;
}
.badge-slider.ng-hide {
transition-delay: 0.0s;
max-height: 0px;
}
Working plunk is here
Is there a way to animate display:none to display:block using CSS so that the hidden div slides down instead of abruptly appearing, or should I go about this a different way?
$(document).ready(function() {
$('#box').click(function() {
$(this).find(".hidden").toggleClass('open');
});
});
#box {
height:auto;
background:#000;
color:#fff;
cursor:pointer;
}
.hidden {
height:200px;
display:none;
}
.hidden.open {
display:block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="box">
Initial Content
<div class="hidden">
This is hidden content
</div>
</div>
And a JSFiddle
Yes, there is a way:
http://jsfiddle.net/6C42Q/12/
By using CSS3 transitions, and manipulate height, rather than display property:
.hidden {
height: 0px;
-webkit-transition: height 0.5s linear;
-moz-transition: height 0.5s linear;
-ms-transition: height 0.5s linear;
-o-transition: height 0.5s linear;
transition: height 0.5s linear;
}
.hidden.open {
height: 200px;
-webkit-transition: height 0.5s linear;
-moz-transition: height 0.5s linear;
-ms-transition: height 0.5s linear;
-o-transition: height 0.5s linear;
transition: height 0.5s linear;
}
More here: Slide down div on click Pure CSS?
Since you're already using jQuery, the simplest thing is just to use slideDown(). http://api.jquery.com/slidedown/
There's also slideToggle().
Then you don't need to manually do all the browser-specific transition css.
I like the idea of CSS transitions, but it's still very jumpy. Sometimes the max-height has to be set to a very high number because of dynamic content which renders the transition useless as it's very jumpy. So, I went back to jQuery, but it had its own faults. inline elements are jumpy.
I found this to work for me:
$(this).find('.p').stop().css('display','block').hide().slideDown();
The stop stops all previous transitions.
The css makes sure it's treated as a block element even if it's not.
The hide hides that element, but jquery will remember it as a block element.
and finally the slideDown shows the element by sliding it down.
What about
$("#yourdiv").animate({height: 'toggle'});
Toggle will switch your div on/off, and the animate should make it appear from below. In this scenario, you don't need the specific CSS to "hide" it.
We can use visibility: hidden to visibility: visible instead of display: none to display: block property.
See this example:
function toggleSlide () {
const div = document.querySelector('div')
if (div.classList.contains('open')) {
div.classList.remove('open')
} else {
div.classList.add('open')
}
}
div {
visibility: hidden;
transition: visibility .5s, max-height .5s;
max-height: 0;
overflow: hidden;
/* additional style */
background: grey;
color: white;
padding: 0px 12px;
margin-bottom: 8px;
}
div.open {
visibility: visible;
/* Set max-height to something bigger than the box could ever be */
max-height: 100px;
}
<div>
<p>First paragraph</p>
<p>Second paragraph</p>
</div>
<button
onclick="toggleSlide()"
>
toggle slide
</button>
I did this workaround for the navigation header in my React site.
This is the regular visible css class
.article-header {
position: fixed;
top: 0;
transition: top 0.2s ease-in-out;
}
This is the class that is attached to the div (when scrolled in my case)
.hidden {
top: -50px !important;
transition: top 0.5s ease-in-out;
}
You can use also
$('#youDiv').slideDown('fast');
or you can tell that the active div goes up then the called one goes down
$('.yourclick').click(function(e) {
var gett = $(this).(ID);
$('.youractiveDiv').slideUp('fast', function(){
$('.'+gett).slideDown(300);
});
});
Something like that.
I have an img tag that I want to change the src when hover and it all works but i would like to add some transition so it doesn't look so rough but since it's an img src i cant target it with css.
http://jsfiddle.net/Ne5zw/1/
html
<img id="bg" src="img/img1.jpg">
<div onmouseover="imgChange('img/img2.jpg'); "onmouseout="imgChange('img/img1.jpg');">
js
function imgChange(im){
document.getElementById('bg').src=(im);
}
You want a crossfade. Basically you need to position both images on top of each other, and set one's opacity to 0 so that it will be hidden:
<div id="container">
<img class="hidden image1" src="http://www.istockphoto.com/file_thumbview_approve/4629609/2/istockphoto_4629609-green-field.jpg">
<img class="image2" src="http://www.istockphoto.com/file_thumbview_approve/9958532/2/istockphoto_9958532-sun-and-clouds.jpg" />
</div>
CSS:
.hidden{
opacity:0;
}
img{
position:absolute;
opacity:1;
transition:opacity 0.5s linear;
}
With a transition set for opacity on the images, all we need to do is trigger it with this script:
$(function(){
debugger;
$(document).on('mouseenter', '#hoverMe', function(){
$('img').toggleClass('hidden');
});
});
http://jsfiddle.net/Ne5zw/12/
Here is a pure css solution using css transition. You can use a div as the container and set the background-image on hover.
.image-container {
background: url(http://placeholder.pics/svg/300x300/DEDEDE/555555/Old%20Image) center center no-repeat;
background-size: contain;
width: 150px;
height: 150px;
-webkit-transition: all .3s ease-in-out;
-moz-transition: all .3s ease-in-out;
transition: all .3s ease-in-out;
}
.image-container:hover {
background-image: url("http://placeholder.pics/svg/300x300/DEDEDE/555555/New%20Image");
}
<div class="image-container"></div>
Just in case someone is curious how to actually create a transition-like effect when you are actually changing the source attribute of an image, this was the solution I came up with.
Javascript:
var bool = false;
setInterval(() => {
bool = !bool;
let imgSrc = bool ? 'hero-bg2.jpg' : 'hero-bg.jpg'; // Toggle image
$('.parallax-slider').addClass('transitioning-src'); // Add class to begin transition
setTimeout(() => {
$('.parallax-slider').attr('src', `https://website.com/images/${imgSrc}`).removeClass('transitioning-src');
}, 400); // Ensure timeout matches transition time, remove transition class
}, 6000);
CSS:
.parallax-slider {
transition: opacity 0.4s ease-in;
-webkit-transition: opacity 0.4s ease-in;
-moz-transition: opacity 0.4s ease-in;
-ms-transition: opacity 0.4s ease-in;
-o-transition: opacity 0.4s ease-in;
opacity: 1;
}
.transitioning-src {
transition: opacity 0.4s ease-out;
-webkit-transition: opacity 0.4s ease-out;
-moz-transition: opacity 0.4s ease-out;
-ms-transition: opacity 0.4s ease-out;
-o-transition: opacity 0.4s ease-out;
opacity: 0;
}
This will give the illusion of 'fading to black and back' between images - even if you're using something like parallax.js where you have a data-attribute driven component that renders out into a dynamic image. Hope it helps someone.
Fixed Mister Epic solution's images in this jsfiddle.
HTML
<div id="container">
<img class="hidden image1" src="http://placeholder.pics/svg/300x300/DEDEDE/555555/Old%20Image">
<img class="image2" src="http://placeholder.pics/svg/300x300/DEDEDE/555555/New%20Image" />
</div>
<div id="hoverMe">hover me</div>
CSS
div#hoverMe {
background-color:yellow;
width:50px;
height:50px;
position:fixed;
top:300px;
}
div#container{
position:relative;
height:200px;
}
.hidden{
opacity:0;
}
img{
position:absolute;
opacity:1;
transition:opacity 0.5s linear;
}
JS
$(function(){
$(document).on('mouseenter', '#hoverMe', function(){
$('img').toggleClass('hidden');
});
});
I'm animating the images so that when hovered over the opacity goes up to 1, that part is working perfectly fine however when images are hovered over in chrome the 2nd column flickers a tiny bit to the side. I've tested it in IE and Firefox aswell and have no issues.
Check it for yourself here: http://abmenzel.com/work/
HTML:
<body class="blue4">
<div class="content">
<div class="work-item blue4">
<img src="img/Template-2-Intro.png"/>
</div>
</div>
</body>
CSS:
.work-item{
width:25%;
opacity:0.8;
overflow:hidden;
display:block;
float:left;
}
img{
width:100%
}
.work-item:hover{
opacity:1;
-webkit-transition: all 0.2s ease-in-out 0s;
-moz-transition: all 0.2s ease-in-out 0s;
-o-transition: all 0.2s ease-in-out 0s;
-ms-transition: all 0.2s ease-in-out 0s;
transition: all 0.2s ease-in-out 0s;
}
I'm also using a script to set the height equal to the dynamic width, which might have something to do with it but I am unsure..
SCRIPT:
$(function() {
var div = $('.work-item');
var width = div.width();
div.css('height', width-5);
});
First of all, put your transition properties in normal element, not on :hover state.
Then, if you need only transition on opacity, use :
opacity 0.2s ease-in-out 0s
That flicker is a known bug in Webkit browsers, it happens when you animate opacity on fluid elements (here 25%).
Here's a workaround:
-webkit-backface-visibility: hidden;
-webkit-transform: translateX(0);
I know it sounds like a hack, but it works...
I use translate3D instead of translateX:
img {-webkit-transform: translate3D(0,0,0);}
My problem..
I have a number of images (inside hyperlinks), and I want each to darken on mouseover (i.e. apply a black mask with high opacity or something), and then go back to normal on mouseout . But I can't figure out the best way to do it.
I've tried..
Jquery color animate and some javascript references.
Setting the opacity of the image with javascript.
I don't want..
Image start at 80% opacity then go to 100% on mouseover (that's easy).
To swap between 2 images (one light & one dark), forgot the mention this sorry..
To reiterate..
I want in image (inslide a hyperlink) to darken on mouseover and then lose its darkness on mouseout.
Thoughts?
UPDATE :
This is my progress from suggestions. Looks fine in IE8, but not in FF3
<html>
<body>
<a href="http://www.google.com" style="background-color:black; opacity:1;filter:alpha(opacity=100)">
<img src="http://www.google.co.uk/intl/en_uk/images/logo.gif" width="200"
style="opacity:1;filter:alpha(opacity=100)" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"
onmouseover="this.style.opacity=0.6;this.filters.alpha.opacity=60" />
</a>
</body>
</html>
Thoughts?
-- Lee
ANSWER
I'm going with this (seems to work in IE8 & FF)
<html>
<head>
<style type="text/css">
.outerLink
{
background-color:black;
display:block;
opacity:1;
filter:alpha(opacity=100);
width:200px;
}
img.darkableImage
{
opacity:1;
filter:alpha(opacity=100);
}
</style>
</head>
<body>
<a href="http://www.google.com" class="outerLink">
<img src="http://www.google.co.uk/intl/en_uk/images/logo.gif" width="200"
class="darkableImage" onmouseout="this.style.opacity=1;this.filters.alpha.opacity=100"
onmouseover="this.style.opacity=0.6;this.filters.alpha.opacity=60" />
</a>
</body>
</html>
Or, similar to erikkallen's idea, make the background of the A tag black, and make the image semitransparent on mouseover. That way you won't have to create additional divs.
CSS Only Fiddle (will only work in modern browsers)
JavaScript based Fiddle (will [probably] work in all common browsers)
Source for the CSS-based solution:
a.darken {
display: inline-block;
background: black;
padding: 0;
}
a.darken img {
display: block;
-webkit-transition: all 0.5s linear;
-moz-transition: all 0.5s linear;
-ms-transition: all 0.5s linear;
-o-transition: all 0.5s linear;
transition: all 0.5s linear;
}
a.darken:hover img {
opacity: 0.7;
}
And the image:
<a href="http://google.com" class="darken">
<img src="http://www.prelovac.com/vladimir/wp-content/uploads/2008/03/example.jpg" width="200">
</a>
Make the image 100% bright so it is clear.
And then on Img hover reduce it to whatever brightness you want.
img {
-webkit-transition: all 1s ease;
-moz-transition: all 1s ease;
-o-transition: all 1s ease;
-ms-transition: all 1s ease;
transition: all 1s ease;
}
img:hover {
-webkit-filter: brightness(70%);
filter: brightness(70%);
}
<img src="http://dummyimage.com/300x150/ebebeb/000.jpg">
That will do it,
Hope that helps
I realise this is a little late but you could add the following to your code. This won't work for transparent pngs though, you'd need a cropping mask for that. Which I'm now going to see about.
outerLink {
overflow: hidden;
position: relative;
}
outerLink:hover:after {
background: #000;
content: "";
display: block;
height: 100%;
left: 0;
opacity: 0.5;
position: absolute;
top: 0;
width: 100%;
}
How about this...
<style type="text/css">
div.frame { background-color: #000; }
img.pic:hover {
opacity: .6;
filter:alpha(opacity=60);
}
</style>
<div class="frame">
<img class="pic" src="path/to/image" />
</div>
Put a black, semitransparent, div on top of it.
Create black png with lets say 50% transparency. Overlay this on mouseover.