I'm trying to get something to fade in using Jquery. I am gathering the info via scrollTop(). So, when the scroll top equals the offset().top of the div, it will fadein. Or just appear.
#myDiv {
background: #990000;
height: 500px;
width: 100%;
overflow: hidden;
opacity: 0;
}
.fade-in {
opacity: 1.0;
}
There's my CSS.
var winHeight = $(window).height();
$(window).scroll(function() {
var scrollTop = $(window).scrollTop();
$("#myDiv").each(function() {
var $this = $(this);
var trigger = $(this).offset().top;
if (scrollTop >= trigger) {
$this.addClass("fade-in");
}
});
});
And there is my Jquery. The funny thing is that if I use $this.css it works fine.
I am just wondering how CSS and Jquery interact when it comes to opacity.
The id-selector(#myDiv) class gets more priority than the class-selector(.fade-in) in css. So the opacity property in the #myDiv gets more priority when your div has both the classes added. Just changing the .fade-in class a bit, your code should work fine.
.fade-in {
opacity: 1.0 !important;
}
Hope it helps :)
The jQuery .addClass() method just instantly adds the specified class to the element, and once it's added, the css rules are instantly applied just like they would be if you had added the class in the HTML. There's absolutely nothing special or jQuery-specific about how the rules are applied, so opacity shouldn't be applied any differently than any other CSS rule would be. If you believe you're getting a different result when applying the rule via $(this).addClass("fade-in") rather than using $this.css, I'd suggest setting up a jsFiddle to show the issue so folks can take a look at it for you.
Related
I have a small and very simple segment of jQuery code which applies a class which uses position: fixed to the navigation element of my page so that the navigation can become sticky and therefore stay with the user as they scroll down the page.
I am building this on an Commerce platform. The issue is that it looks as though when position: fixed is applied to the navigation element, the property isn't working correctly. It looks as though the position is becoming "fixed" but it's only fixed within the header area that it is contained within and I have no idea why this could be happening. Please see below if you would like to see this for yourself:
http://ts564737-container.zoeysite.com/
You can see that after scrolling slightly, the navigation element becomes fixed but not correctly as it should.
Please see my code below:
CSS
.fixed {
top: 0 !important;
z-index: 100 !important;
position: fixed !important;
transition: all 0.3s;
background-color: #000000;
opacity: 0.9;
}
JavaScript/jQuery
<script>
var num = 40;
jQuery(window).bind('scroll', function () {
if (jQuery(window).scrollTop() > num) {
jQuery('.navigation').addClass('fixed');
} else {
jQuery('.navigation').removeClass('fixed');
}
});
</script>
Could anybody provide any insight as to what's going wrong here and causing the element to not fix properly? Any advice at all is much appreciated, thank you so much.
It's because your some parent/parents container contains css transform property.
I have added this css and your fixed element started working:
* {
transform: none !important;
}
Fixed elements in parent which have transform property have different behaviour.
Related issue
I want to create a function that moves a block smoothly. I prefer to use the CSS option 'transition-duration' for this, but it doesn't seem to work for the position. I checked, and it does work for background-color...
CSS file
#cart {
position: relative;
transition-duration: 0.5s;
background-color: green;
}
JS file
function start() {
document.getElementById("cart").innerHTML = "test2";
document.getElementById("cart").style.left = "100";
document.getElementById("cart").style.background = "gray";
}
So the background-color does change in 2 seconds instead of instantly while the position just changes the instant you use the function. Is there a way to use the 'transition-duration' for the style.left in JS? Or do I have to use something else to make the div move smoothly?
Answer:
The solution is that for transition-duration to do anything, it has to be declared beforehand. This means that because I didn't specify a position in a non-animated state, the movement is done instantly. Another solution is to use transition: left 0.5s since this doesn't require any CSS-styling of the sort.
The CSS for "left" isn't declared in the CSS before it's added in the JS. Also "100" is an invalid value for CSS position (note the added "px" in the following example).
JSFiddle: https://jsfiddle.net/MissionMike/adj4j6tr/
HTML:
<div id="cart">TEST</div>
CSS:
#cart {
position: relative;
transition-duration: 0.5s;
background-color: green;
left: 0;
}
JS:
document.getElementById("cart").innerHTML = "test2";
document.getElementById("cart").style.left = "100px";
document.getElementById("cart").style.background = "gray";
Use transition: left 0.5s linear; as you haven't said what property you're transitioning.
Also, put the styles you want to change to in a class and apply the class with js instead.
Also, you probably want to transition an absolute item inside a relative container, not apply 'left' to a relative element.
I want to animate a translateX with transition on a click event by adding a class to the div in the js. The transform and transition properties are added in the css file.
var widget = document.getElementById('widget');
widget.style.display = 'block';
document.getElementById('widget2').clientWidth; //comment this line out and it wont work
widget.className = 'visible';
It only works if I query the width property of any element in the dom before adding the class.
here is a jsfiddle:
https://jsfiddle.net/5z9fLsr5/2/
Can anyone explain why this is not working?
That's because you begin your transition and modified the display property "at the same time". Altering display will ruin any transition (citation needed, admittedly), so it would be a good idea to isolate the display changing and actual transiting:
https://jsfiddle.net/5z9fLsr5/3/
document.getElementById('showWidget').addEventListener('click', function(e) {
e.preventDefault();
var widget = document.getElementById('widget');
widget.style.display = 'block';
//document.getElementById('widget2').clientWidth;
window.setTimeout(function(){
widget.className = 'visible';
},0);
});
#widget {
width: 200px;
height: 80px;
background: black;
position: absolute;
transition: transform 500ms;
transform: translateX(-200px);
display: none;
}
#widget.visible {
transform: translateX(200px);
}
#widget2 {
position: absolute;
right: 0
}
show
<div id="widget"></div>
<div id="widget2">xxx</div>
Querying clientWidth seems to "pause" the execution for some time, so it works too.
The issue here is the initial setting of display: none. To the browser's layout manager, this indicates that the layout should be done as if the element in question wasn't even in the DOM (it still is, mind you). This means that the CSS style transform: translateX(-200px); will not be applied.
Doing this:
widget.style.display = 'block';
widget.className = 'visible';
triggers both modifications essentially at the same time - the layout is only re-done after both statements have been executed. Inserting document.getElementById('widget2').clientWidth; (clientHeight works as well) triggers the layout manager to repaint, thus registering transform: translateX(-200px).
As others have mentioned before me, the solution is to either use opacity instead of display (this would be my choice), or to use setTimeout with a delay of 0 (see Why is setTimeout(fn, 0) sometimes useful?).
I'm using Javascript to expand a div, but when the content is expanded it's highly abrupt and at best highly unattracive. I was wondering if there was a way to make this div expand slower and more of a visual expand then a BLAM. Now I'm done.
<script language="javascript">
function toggle_profile() {
var ele = document.getElementById("toggleProfile");
var text = document.getElementById("displayProfile");
if(ele.style.display == "block") {
ele.style.display = "none";
text.innerHTML = "View Profile";
}
else {
ele.style.display = "block";
text.innerHTML = "Hide Profile";
}
}
</script>
<a id="displayProfile" href="javascript:toggle_profile();">View Profile</a></p>
<br />
<div id="toggleProfile" style="display: none">
The trick is with appending and removing classes in Javascript... And attaching a CSS3 transition like this:
div {
-webkit-transition: height .25s ease;
-moz-transition: height .25s ease;
transition: height .25s ease;
}
This applies a transition you can control the speed of to all your divs. Of course you can select which DOM elements to apply it to yourself.
And then the two jquery functions I'd use are
$("#object").addClass("removeThis"); //hide
$("#object").removeClass("removeThis"); //show
But as pointed out you may not use jQuery! So here!
document.getElementById("object").className = "";
document.getElementById("object").className = "removeThis";
Where "#object" is the object you are targeting, and ".removeThis" is the class you are adding and removing from the class attribute in the dom tag. Heres what it looks like in css.
#object {
height: 200px;
/* ignoring other CSS */
}
.removeThis {
height: 0;
}
Assuming that you want it to slide up and down. Another trick is to use opacity, or display: none and display: block. But play around. I hope this helps!
Edit since 2012:
Since you're using using JavaScript you're asking for work to be done on the main thread, you can utilize the compositor thread by animating on a transform instead. That is if you can figure out how to get away from animating the height style property.
Theres really no point in re-inventing the wheel. You can do this pretty easily with Jquery's slidetoggle. Here is the page: http://api.jquery.com/slideToggle/
I think the best trick is to use the CSS overflow:hidden property in the division. This will hide the content which is out of the div height or width. Then you can easily increase and decrease the height of the division with smooth CSS transition.
You can read the tutorial here
I am using the following jQuery script:
$("#divid").mouseenter(function() {
$('#divid').show(1000);
}).mouseleave(function() {
$('#divid').hide(1000);
});
$("#hldiv").mouseenter(function() {
$('#divid').show(1000);
}).mouseleave(function() {
$('#divid').hide(1000);
});
As you can see, when the mouse hovers over a hyperlink called #hldiv, the #divid should be shown. The main goal is to keep the DIV shown if the mouse is over the DIV - but the #divid should not be visible initially.
If the mouse moves over the hyperlink, the DIV should appear, and when the mouse then moves over the DIV, it should stay until the mouse leaves.
The problem is that with my current code, when the user moves over the hyperlink and then out - the DIV appears/disappears correctly, but when the user moves out of the hyperlink and over the DIV itself, the DIV also disappears.
How should I fix this?
Why don't you add a container and do:
<div id='container'>
<a ID="hlDiv">hlink</a>
<div ID="divId">Test Test Test</div>
</div>
$(document).ready(function() {
$("#hlDiv").hover(function() {
$('#divId').show(1000);
})
$('#container').mouseleave(function(){
$('#divId').hide(1000);
});
});
fiddle here: http://jsfiddle.net/w68YX/8/
If I understood right, rewriting
$("#divid").mouseenter(function() {
$('#divid').stop(true);
$('#divid').show(1000);
}).mouseleave(function() {
$('#divid').hide(1000);
});
Might help, since it stops the current animation (fading out) and fades it back in (if it has already turned a bit transparent).
However this depends on your HTML, and might not work in your case, so please post the structure also.
I am very late to this party - but there is a far better way to do this, so I want to add it for the sake of future browsers. You don't need jQuery for this effect at all.
First, wrap the two items in a container (here I'm using a div with class container), and apply a class to the item you want to appear/disappear on hove (here I'm using the show-on-hover class on the #divId element)
<div class="container">
<a id="hlDiv" href="...">link text</a>
<div class="show-on-hover" id="divId">popup stuff</div>
</div>
Next, set up your CSS as follows:
.container > .show-on-hover { display: none; }
.container:hover > .show-on-hover { display: block; }
#divId { /* whatever styles you want */ }
The effect is that the hover is now controlled entirely by CSS - but, it doesn't have the 1s transition you originally had. This is a little more complicated (and currently doesn't work in IE - but will be supported as of IE10).
Simply change the CSS as follows:
.container { position: relative; }
.container > .show-on-hover { opacity: 0.0; position: absolute; }
.container:hover > .show-on-hover { opacity: 1.0; }
.show-on-hover {
-webkit-transition: opacity 1s; /* Chrome / Safari */
-moz-transition: opacity 1s; /* Firefox */
-o-transition: opacity 1s; /* Opera */
}
The relative positioning on the .container means that the container sets its own bounding boxes for its child elements and their positioning. This means that when you then set the > .show-on-hover styling to position: absolute;, it will still be constrained to its parent (if you set left: 0; as an example, it will move to the left edge of the .container, rather than the screen).
The opacity toggle now simply makes the absolutely positioned item show/disappear wherever you've placed it (and you would update the CSS to put it exactly where you want, relative to the hyperlink). Because we're no longer using display: none - the DIV will always take up space on the screen - even when hidden (which is probably not what you want).
Finally - the last block, which sets transitions, tells modern browsers that whenever the opacity changes on elements of class .show-on-hover, make that change happen as a tween over 1s of duration.
Here is a jsFiddle showing the transitions: http://jsfiddle.net/TroyAlford/nHrXK/2
And here is a jsFiddle showing just the toggle: http://jsfiddle.net/TroyAlford/nHrXK/3/