Animations lagging on mobile chrome - javascript

I'm trying to do animations on my website. I'm using have a similar version of the jsfiddle code linked below. When viewed on desktop, the animations work well. However when viewed on mobile, specifically on my chrome browser, there is a weird lag. The jsfiddle shows the exact same lag when I open it on my phone. If I restart the chrome app the lag goes away back comes back soon after.
This issue doesn't occur in Safari.
I have the latest iPhone with IOS 14.6 and chrome V90.
https://jsfiddle.net/brodriguez98/e2bvwcja/33/
HTML:
<html>
<p style = 'margin-top: 100vh;'>above</p>
<img class = 'balltest show-on-scroll standard-push' src = 'http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png'/>
<img class = 'balltest show-on-scroll fade-in' src = 'http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png'/>
<p style = 'margin-bottom: 100vh'>below</p>
</html>
CSS:
.balltest {
width: 50px;
}
.fade-in {
opacity: 0;
-webkit-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
-moz-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
-o-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 0.3s 0.25s ease-out;
will-change: transform, opacity;
}
.standard-push {
opacity: 0;
transform: translateY(4em);
-webkit-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out, translateZ(0);
-moz-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
-o-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 0.3s 0.25s ease-out;
will-change: transform, opacity;
}
.is-visible {
transform: translateY(0);
opacity: 1;
}
Javascript:
var elementsToShow = document.querySelectorAll('.show-on-scroll');
$(window).scroll(function() {
Array.prototype.forEach.call(elementsToShow, function (element) {
if (isElementInViewport(element)) {
element.classList.add('is-visible');
} else {
element.classList.remove('is-visible');
}
});
});
// Helper function from: http://stackoverflow.com/a/7557433/274826
function isElementInViewport(el) {
// special bonus for those using jQuery
if (typeof jQuery === "function" && el instanceof jQuery) {
el = el[0];
}
var rect = el.getBoundingClientRect();
return (
(rect.top <= 0 &&
rect.bottom >= 0) ||
(rect.bottom >= (window.innerHeight || document.documentElement.clientHeight) &&
rect.top <= (window.innerHeight || document.documentElement.clientHeight)) ||
(rect.top >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight))
);
}
I apologize for the tiny screen, couldn't get JSfiddle on fullscreen on my phone:
Animation working right after restarting mobile chrome:
https://www.loom.com/share/ac6c843b90d2428bb875572d55e32959
Animation breaking soon after (when I close/reload the page):
https://www.loom.com/share/e51cf88aa1a74aed8e4d1ed253e83ea0
This is exactly the same behavior I'm seeing on my website using mobile chrome browser.
Update:
Neither of the answers below worked for me. I forgot to mention that this behavior is also happening with text. Also, thanks for suggesting codesandbox, I forked your code and made it even simpler by removing the images but I still get the same result on my iphone chrome browser. I also tried wrapping everything with an onload function and that didn't work either.
For now I was able to fix this with JQuery animations but I would still like CSS3 transitions to work on my site.
https://codesandbox.io/s/animation-test-forked-tqurn?file=/index.html

This looks like a "race condition" issue when loading the page.
The JS runs before the IMG request is done.
To understand the problem it is necessary to understand the loading sequence:
On load/reload the Server responds with the document (*.html) file
The browser starts to parse the response (*.html) and starts new requests for each resource found:
CSS
JS
IMGs
These requests complete in an unpredictable order. E.g. large images may load longer than a *.css file,... some resources may already be cached by the browser and won´t start a request at all,...
If the request for the *.js file completes before the IMGs request is done, there is no rendered height found for that image and the new added CSS class is-visible will start the transition anyway...
Once the IMG requests completes (img gets rendered). A Content Reflow is triggered for the IMG.
An ongoing transition on elements that need a repaint (the IMG) is 'reset' and starts from keyframe 0.
This may explain your issue.
Here are 3 options that might fix your Issue:
A. Preserve the final dimension of the image.
Set a fix height in CSS and add class in html:
.myImg {
width: 50px;
height: 50px;
}
You could also add width and height as html attributes. The final dimension is now available in JS even if *.css is still loading...
<img height="50" width="50" class="..." src="...">
B. Add some "load detection" for the images and prevent the transition until image is fully loaded.
We check if img is already loaded:
src is set and height is detected-
Else set an onload event for that image (because it is not loaded yet)
Optional: You can use lazy loading for that image and only load images 'on demand' (see final example). The img´s src is set as data-src attribute and and src will be set by JS once the image is available.
Now we can use a isLoaded(element) function to exclude images in .scroll() that are currently not fully loaded.
Here is jsFiddle, or expand the example below...
var elementsToShow = document.querySelectorAll('.show-on-scroll');
$(window).scroll(function() {
Array.prototype.forEach.call(elementsToShow, function (element) {
if (isLoaded(element) && isElementInViewport(element)) {
element.classList.add('is-visible');
} else {
element.classList.remove('is-visible');
}
});
});
[...elementsToShow].forEach((imgEl, i) => {
if (
imgEl.src &&
imgEl.getBoundingClientRect().height
) {
imgEl.dataset.isLoaded = true;
console.log(`Img ${i} already loaded`);
} else {
console.log(`Img ${i} still loading... or should be lazyloaded`);
imgEl.onload = function(e) {
console.log(`Img ${i} finally loaded! onload event`);
e.target.dataset.isLoaded = true;
};
if (imgEl.dataset.src) {
console.log(`Img ${i} start lazy load...`);
imgEl.src = imgEl.dataset.src;
}
}
})
function isLoaded(el) {
return el.dataset.isLoaded
}
var elementsToShow = document.querySelectorAll('.show-on-scroll');
$(window).scroll(function() {
Array.prototype.forEach.call(elementsToShow, function(element) {
if (isLoaded(element) && isElementInViewport(element)) {
element.classList.add('is-visible');
} else {
element.classList.remove('is-visible');
}
});
});
[...elementsToShow].forEach((imgEl, i) => {
if (
imgEl.src &&
imgEl.getBoundingClientRect().height
) {
imgEl.dataset.isLoaded = true;
console.log(`Img ${i} already loaded`);
} else {
console.log(`Img ${i} still loading... or should be lazyloaded`);
imgEl.onload = function(e) {
console.log(`Img ${i} finally loaded! onload event`);
e.target.dataset.isLoaded = true;
};
if (imgEl.dataset.src) {
console.log(`Img ${i} start lazy load...`);
imgEl.src = imgEl.dataset.src;
}
}
});
function isLoaded(el) {
return el.dataset.isLoaded
}
// Helper function from: http://stackoverflow.com/a/7557433/274826
function isElementInViewport(el) {
// special bonus for those using jQuery
if (typeof jQuery === "function" && el instanceof jQuery) {
el = el[0];
}
var rect = el.getBoundingClientRect();
return (
(rect.top <= 0 &&
rect.bottom >= 0) ||
(rect.bottom >= (window.innerHeight || document.documentElement.clientHeight) &&
rect.top <= (window.innerHeight || document.documentElement.clientHeight)) ||
(rect.top >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight))
);
}
.balltest {
width: 50px;
}
.fade-in {
opacity: 0;
-webkit-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
-moz-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
-o-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 0.3s 0.25s ease-out;
will-change: transform, opacity;
}
.standard-push {
opacity: 0;
transform: translateY(4em);
-webkit-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out, translateZ(0);
-moz-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
-o-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 0.3s 0.25s ease-out;
will-change: transform, opacity;
}
.is-visible {
transform: translateY(0);
opacity: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<p style='margin-top: 100vh;'>above</p>
<img class='balltest show-on-scroll standard-push' src='http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png' />
<img class='balltest show-on-scroll fade-in' src='http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png' />
<img class='balltest show-on-scroll standard-push' data-src='http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png' />
<img class='balltest show-on-scroll fade-in' data-src='http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png' />
<p style='margin-bottom: 100vh'>below</p>
</html>
C. Wait for the load event of the document
You can wrap your JS initialization code into a load event for the entire document. The event is fired after all ressources (CSS, IMG,..) were completely loaded.
window.addEventListener('load', (event) => {
// JS init code hier (images are loaded at this point!)
});

I tested your code on Chrome browser for iPhone and could not reproduce the bug displayed in your screen recording.
Could it be that the lag had to do with attempting to run the entire jsfiddle web app on mobile chrome browser? It's a heavy web app with a lot going on under the hood, besides any actual output you're testing, so that might account for performance issues. Better to test just the output by itself.
I've migrated your code to a codesandbox which will allow you to view the output by itself in a mobile browser (see below). You can judge for yourself whether or not the issue you witnessed is an actual code bug.
It should also be noted that the ball image that you're using is quite large in file size (~200kb) for the size it's being displayed at. Therefore, it wouldn't be out of the ordinary to see it flicker while it's loading on the page.
Here's a smaller version of the ball image (downscaled by 80% and optimized with https://tinypng.com/) for a final size of ~42kb (you could definitely make it even smaller):
Here's your same code on codesandbox:
https://codesandbox.io/s/animation-test-ok1dp
Here's just the output (try viewing this in mobile browser on your device):
https://ok1dp.csb.app/
Here's a screen video (that I captured on my iPhone using Chrome browser):

I face this situation too. On other browsers, it is smooth. On Chrome mobile, it is so lag. This situation appear when I update my iPhone to iOS 14.

A simplified sample running choppy on IOS Google Chrome. Safari runs smooth and painless.
Hope this helps further to narrow down the problem and document the difference.
<div class="menu__icon icon-menu">
<span></span>
<span></span>
<span></span>
</div>
.icon-menu {
cursor: pointer;
display: block;
height: 18px;
position: absolute;
left: 28px;
top: 52px;
width: 28px;
z-index: 5;
}
.icon-menu span {
will-change: transform;
background-color: #018d8d;
height: 2px;
left: 0;
position: absolute;
top: calc(50% - 1px);
-webkit-transition: all .3s ease 0s;
transition: all .3s ease 0s;
width: 100%;
}
.icon-menu span:first-child {
top: -8px;
}
.icon-menu span:nth-child(2) {
top: 0;
}
.icon-menu span:last-child {
top: 8px;
}
.icon-menu._active span:first-child {
top: -1px;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
}
.icon-menu._active span {
-webkit-transform: scale(0);
transform: scale(0);
}
.icon-menu._active span:last-child {
top: -1px;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
const element = document.querySelector('.menu__icon');
element.addEventListener('click', () => {
console.log('clicked');
element.classList.toggle('_active');
});
https://codepen.io/dblue71/pen/dyzMWmO

I am also facing this issue, and so I did a little digging and find some helpful resources to track this bug, which is indeed an iOS Chrome bug.
I hope that these resources can help those who come across this bug and pass by here.
The related topic initiated in 2018 on chromium :
https://bugs.chromium.org/p/chromium/issues/detail?id=899130
A more recent and active topic :
https://bugs.chromium.org/p/chromium/issues/detail?id=1231712
And finally a post on css-trick which might help you
https://css-tricks.com/forums/topic/problem-with-transition-of-transform-property-in-chrome-on-ios/

Related

how to fade in and out with javascript

I am trying to make a message appear if the user doesn't scroll for specific amount of time and then make the text fade out as soon as the user scroll. What I have tried so far is not working.
I am looking for vanilla javascript solutions only.
thank you for your help.
// make scroll button appear ---------------
var scrollText = document.getElementById("scrollMsg");
function showMsg() {
scrollText.className = "show";
}
setTimeout(showMsg, 2000);
// make scroll button fadout ---------------
function scrollHide() {
var scrollText2 = document.querySelector("#scrollMsg.show");
var scrllTPosition = scrollText2.getBoundingClientRect().top;
var screenPosition = window.innerHeight / 0.5;
if (scrllTPosition < screenPosition) {
scrollText2.classList.add("scrollHide");
}
}
window.addEventListener("scroll", scrollHide);
#scrollMsg {
height: auto;
position: sticky;
bottom: 175px;
z-index: 1;
opacity: 0;
-webkit-transition: opacity 0.7s;
-moz-transition: opacity 0.7s;
transition: opacity 0.7s;
}
#scrollMsg.show {
opacity: 1;
-webkit-transition: opacity 0.7s ease-in-out;
-moz-transition: opacity 0.7s ease-in-out;
transition: opacity 0.7s ease-in-out;
}
#scrollhide {
opacity: 0;
-webkit-transition: opacity 0.7s ease-in-out;
-moz-transition: opacity 0.7s ease-in-out;
transition: opacity 0.7s ease-in-out;
}
<p id="scrollMsg">scroll</p>
I've added some large divs to allow us to scroll through the document.
// make scroll button appear ---------------
var scrollText = document.getElementById("scrollMsg");
window.addEventListener('scroll', (e) => {
console.log('user scrolled!')
scrollText.style.opacity = 0
});
#scrollMsg {
opacity: 1;
transition: opacity 1s;
}
<div style="height:100px"></div>
<p id="scrollMsg">scroll</p>
<div style="height:4000px"></div>

IntersectionObserver: Trigger event when scrolling back to the top

I am starting to use the IntersectionObserver API and could create some basic animations, which includes hiding and appearing of elements. However, once a person wants to scroll back to the top, the elements which disappeared by one of the triggers are not getting visible again.
My Solution so far
So I thought I might create another test variable within the intersection observer callback function (the stepI and stepII variable in my code), which checks if the callback function was previously triggered. If so, instead of disappearing the elements, let them appear again.
My current problem
So let's say a background image (id="hiddenImg") should appear when the first text block (id="I") passes the 50% border of the viewport and it disappears when the second text block (id="II") enters this area. Even though the image is getting visible again when scrolling back up, if the user does not scroll back completely (so that the second text block goes out of the viewport) and then scrolls back to the bottom, the disappearing trigger of that second text block is not called. This would mean that the background image would stay visible, which it shouldn't.
Here is the js part:
var stepI = false;
var stepII = false;
// list of options
let options = {
rootMargin: '0px 0px -50%' //WHEN reaching half of the viewport
};
// instantiate a new Intersection Observer
"use strict";
var intersectionObserver = new IntersectionObserver(function (entries, observer) {
entries.forEach(function (change) {
if (change.isIntersecting) {
if (change.target.id == "I") {
$("#hiddenImg").removeClass("hidden_img");
$("#hiddenImg").addClass("visible_img");
stepI = true;
observer.unobserve(change.target);
}
if (change.target.id == "II") {
if (stepII == false) {
$("#hiddenImg").removeClass("visible_map");
$("#hiddenImg").addClass("hidden_map");
stepII = true
} else {
$("#hiddenImg").removeClass("hidden_map");
$("#hiddenImg").addClass("visible_map");
stepII = false;
}
}
}
});
},options);
// list of paragraphs
let elements = document.querySelectorAll(".stepper");
for (let elm of elements) {
intersectionObserver.observe(elm);
}
Here is my complete code:
<html>
<head>
<!-- Load the polyfill. -->
<script src="/js/intersection-observer.js"></script>
<script src='https://unpkg.com/intersection-observer#0.5.0/intersection-observer.js'></script>
</head>
<body>
<style>
.intro-imgs {
display: block;
margin: 0 auto; /* Will not center vertically and won't work in IE6/7. */
left: 0;
right: 0;
position: fixed;
position: expression(fixed);
}
.hidden_img {
visibility: hidden;
opacity: 0;
-ms-transform: scaleX(0); /* IE 9 */
-webkit-transform: scaleX(0); /* Safari 3-8 */
-o-transform: scaleX(0);
-moz-transform: scaleX(0);
transform: scaleX(0);
-webkit-transition: visibility 0s 0.5s, opacity 0.5s linear, -webkit-transform 0.5s;
-moz-transition: visibility 0s 0.5s, opacity 0.5s linear, -moz-transform 0.5s;
-o-transition: visibility 0s 0.5s, opacity 0.5s linear, -o-transform 0.5s;
transition: visibility 0s 0.5s, opacity 0.5s linear, transform 0.5s;
}
.visible_img {
visibility: visible;
opacity: 1;
-ms-transform: scaleX(1); /* IE 9 */
-webkit-transform: scaleX(1); /* Safari 3-8 */
-o-transform: scaleX(1);
-moz-transform: scaleX(1);
transform: scaleX(1);
-webkit-transition: opacity 0.5s linear, -webkit-transform 0.5s;
-moz-transition: opacity 0.5s linear, -moz-transform 0.5s;
-o-transition: opacity 0.5s linear, -o-transform 0.5s;
transition: opacity 0.5s linear, transform 0.5s;
}
.stepper{
max-width: 70rem;
margin: 550px auto 600px auto;
width: 90%;
background-color: rgba(248, 248, 248, 0.95);
font-family: "Helvetica";
font-size: 17px;
line-height: 26px;
padding: 15px;
}
</style>
<!--HTML-->
<div class="headline">
<img id="hiddenImg" class="hidden_img intro-imgs" src="https://image.shutterstock.com/image-photo/funny-portrait-hero-260nw-410898763.jpg" >
</div>
<div id="I" class="stepper">
<p>Lorem Ipsum</p>
</div>
<div id="II" class="stepper">
<h1>THE HEADLINE</h1>
</div>
<!-- SCRIPT-->
<script>
var stepI = false;
var stepII = false;
// list of options
let options = {
rootMargin: '0px 0px -50%' //WHEN reaching half of the viewport
};
// instantiate a new Intersection Observer
"use strict";
var intersectionObserver = new IntersectionObserver(function (entries, observer) {
entries.forEach(function (change) {
if (change.isIntersecting) {
if (change.target.id == "I") {
$("#hiddenImg").removeClass("hidden_img");
$("#hiddenImg").addClass("visible_img");
stepI = true;
observer.unobserve(change.target);
}
if (change.target.id == "II") {
if (stepII == false) {
$("#hiddenImg").removeClass("visible_map");
$("#hiddenImg").addClass("hidden_map");
stepII = true
} else {
$("#hiddenImg").removeClass("hidden_map");
$("#hiddenImg").addClass("visible_map");
stepII = false;
}
}
}
});
},options);
// list of paragraphs
let elements = document.querySelectorAll(".stepper");
for (let elm of elements) {
intersectionObserver.observe(elm);
}
</script>
</body>

Setting and element's opacity and then animating it - all with JS

I am working on a new site that is using page transitions. The old content fades away and the new content fades in - at least that's what should happen.
When the new content is loaded, I use JS to set it's opacity: 0
this.newContainer.style.opacity = 0;
Then, I add a new class so I can use CSS transitions
this.newContainer.classList.add("animate-in");
This is the CSS for the .animate-in
.wrapper.animate-in {
opacity: 1;
visibility: visible;
-webkit-transition: all 1000ms ease-in-out;
-moz-transition: all 1000ms ease-in-out;
-ms-transition: all 1000ms ease-in-out;
-o-transition: all 1000ms ease-in-out;
transition: all 1000ms ease-in-out;
}
However, this doesn't work. The code doesn't animate the opacity from 0 to 1. Instead, it is animating backwards, from 1 to 0. It seems like the classList.add doesn't hear the previous line of code.
Anyone know how to fix this?
EDIT
OK, so I learned that using the JS style.opacity will completely override any opacity CSS rules. This is my problem. How do I get around this?
Try to use css animation and remove code--> this.newContainer.style.opacity = 0;
.wrapper.animate-in {
opacity: 1;
transition: all 1000ms ease-in-out;
animation: animate-in01 1s;
animation-iteration-count: 1;
}
#keyframes animate-in01{
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}

jquery background color fade in on scroll

I want the background of the header to fade in after a number of pixel scrolled. With the code below i kinda get it but not much right! Any idea? thanks!
$(function () {
$(window).scroll(function () {
$(document).scrollTop() > 100 ? $('header').css({
"background": 1
}).fadeIn() : $('header').css({
"background": 0
}).fadeOut();
});
})
A combination of Miquel Las Heras and Owen 'Coves' Jones's answers, who both submitted a not completely on-topic or not complete answer.
Use background trasitions (CSS3) and jQuery simultaneously.
JSFiddle
jQuery
$(document).ready(function () {
$(window).scroll(function () {
if ($(document).scrollTop() > 100) {
$("header").addClass("scrolled");
} else {
$("header").removeClass("scrolled");
}
});
});
CSS
header {
background-color:blue;
-webkit-transition: background-color 700ms linear;
-moz-transition: background-color 700ms linear;
-o-transition: background-color 700ms linear;
-ms-transition: background-color 700ms linear;
transition: background-color 700ms linear;
}
header.scrolled {
background-color: red;
}
Update February 3rd, 2017
browser support is very good, and the less performing jQuery solution below should not be used. Browser support.
Cross-browser solution
If you want to make it more cross-browser compatible, you can try the color plugin. But from what I've tested, it has quite a bad performance.
JSFiddle
$(document).ready(function () {
$(window).scroll(function () {
if ($(document).scrollTop() > 100) {
$("header").animate({
backgroundColor: "red"
}, 200);
} else {
$("header").animate({
backgroundColor: "blue"
}, 200);
}
});
});
Don't forget the plugin itself:
//cdnjs.cloudflare.com/ajax/libs/jquery-color/2.1.2/jquery.color.js
First, as was mentioned in the other answer, you will need to include jQuery UI or the jQuery Color plugin for color animation.
Second, and this is just winging it, but give this the old college try:
$(function(){
$(window).scroll(function(){
var $scrollPercent = ($(document).scrollTop() / 100);
if($scrollPercent <= 1){
$('header').css({backgroundColor:'rgba(0,0,0,'+$scrollPercent+')'});
}
});
});
This should give you a gradual fade in based on the amount down the page you scroll. This means that if you scroll 50 px down, your background color opacity would be set to 50% (50 px down / 100 px height wanted). You can also easily change the amount of height that you want to scroll down to reach full opacity very easily this way.
EDIT So it turns out you just want to fade in the color after 100px ... not my gradual fade in. No problem.
Others have pointed out the wonderful (and much better) CSS3 way to do it ... create a transition effect, and add a class on scroll. I won't steal their thunder, but I shall provide an alternative that works back to ancient browsers too.
Add an additional line of HTML inside of your header at the top:
<div class="header">
<div class="headerBackground"></div>
<!-- other header stuffs -->
</div>
Then set its CSS as such:
.header {
position:relative;
}
.headerBackground {
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
background-color:rgb(0,0,0);
opacity:0;
filter:alpha(opacity=0); // for IE8 and below
}
Then use the following jQuery:
$(function(){
$(window).scroll(function(){
var $bg = $('.headerBackground');
if($(document).scrollTop() >= 100){
$bg.animate({opacity:1},500); // or whatever speed you want
} else {
$bg.animate({opacity:0},500);
}
});
});
This also has the added benefit of not requiring another library (jQuery UI / jQuery Color plugin). The downside is, of course, the non-semantic HTML. Like I said, just another alternative.
I prefer to create 2 css classes for this type of issues. One for when window is scrolled and one for when it's not:
header { background: transparent; }
header.scrolled { background: #f2f2f2; }
Then the javascript should be:
$(function () {
$(window).scroll(function () {
if($(document).scrollTop()>100){
$('header').addClass('scrolled');
}
else {
$('header').removeClass('scrolled');
}
});
})
your code is correct, but jQuery does not natively support color animation. you need a plugin or jquery-ui for that: http://jqueryui.com/animate/
EDIT: actually, your code is kinda wrong. you want to set the backgroundColor to something. background: 1 is invalid css:
so .css({'backgroundColor': 'red'}) and then .css({'backgroundColor': 'blue'})
If you don't need to support a lot of older browsers you can animate background colours with a combination of jQuery and css3 transitions:
Take the HTML:
<div id="myBox">Stuff here</div>
And the javascript:
var myBox = $('#myBox');
myBox.on('click', function (el) {
myBox.css('background-color', 'red');
}
Then click the element #myBox will change its background colour red. Instantly, with no fade.
If you also put in place the css code:
#myBox {
-webkit-transition: background-color 300ms ease-in-out;
-moz-transition: background-color 300ms ease-in-out;
transition: background-color 300ms ease-in-out;
}
Then any colour changes to the background will be faded over 300ms. Works on all latest version browsers, but not on IE 9 and below.
The solution that I ended up using is as follows:
I created a section that I'm fading in and out based on the scroll position.
CSS
.backTex {
width:100%;
height:500px;
margin-top:50px;
background-color: #myGreen;
//Height
transition: height 0.5s ease;
-webkit-transition: height 0.5s ease;
-moz-transition: height 0.5s ease;
-o-transition: height 0.5s ease;
-ms-transition: height 0.5s ease;
//Background-Color
transition: background-color 0.5s ease;
-webkit-transition: background-color 0.5s ease;
-moz-transition: background-color 0.5s ease;
-o-transition: background-color 0.5s ease;
-ms-transition: background-color 0.5s ease;
transition: background-color 0.5s ease;
}
jQuery
$(document).scroll(function() {
var positionScroll = $(this).scrollTop();
if(positionScroll <= 499) {
$(".backTex").css("background-color", "#fff");
} else if (positionScroll > 500 && positionScroll < 1100) {
$(".backTex").css("background-color", "#2ecc71");
} else {
$(".backTex").css("background-color", "#fff");
}
});
As far as compatibility, I haven't noticed any issues between browsers as of yet. Please reply to my post if you experience any. Thanks!

jQuery on hover opacity

I have tried and failed to get this working. Basically I am trying to get it so that when you hover over one div, it should change the sibling's opacity to 0.5 that has class="receiver".
If you see this jsFiddle, there are 2 divs with class="outerwrapper", and both contain 2 divs of classes hover and receiver. When you hover over the div with class hover, the receiver's opacity should be set to 0.5, but only the one inside the same div (outerwrapper).
Any help would be much appreciated. Thanks in advance.
You don't need to use jQuery, or JavaScript, for this (though you can1), CSS is quite capable in most browsers of achieving the same end-result:
.hover:hover + .receiver {
opacity: 0.5;
}
JS Fiddle demo.
And also, even with 'only' CSS, in modern/compliant browsers, it's possible to use fade transitions (or, strictly speaking, to transition the opacity):
.receiver {
width: 50px;
height: 50px;
background-color: blue;
opacity: 1;
-webkit-transition: opacity 1s linear;
-o-transition: opacity 1s linear;
-ms-transition: opacity 1s linear;
-moz-transition: opacity 1s linear;
transition: opacity 1s linear;
}
.hover:hover + .receiver {
opacity: 0.5;
-webkit-transition: opacity 1s linear;
-o-transition: opacity 1s linear;
-ms-transition: opacity 1s linear;
-moz-transition: opacity 1s linear;
transition: opacity 1s linear;
}
​
JS Fiddle demo.
I was going to provide a JavaScript/jQuery solution as well, but there are several others already posted, now, and I'd rather not repeat other people's answers in my own (it just feels like plagiarism/copying).
Something like this would do it: http://jsfiddle.net/UzxPJ/3/
$(function(){
$(".hover").hover(
function(){
$(this).siblings(".receiver").css("opacity", 0.5);
},
function(){
$(this).siblings(".receiver").css("opacity", 1);
}
);
});​
References
.siblings() - Get the siblings of an element - http://api.jquery.com/siblings/
.hover() - Catch the mouseover/mouseout events - http://api.jquery.com/hover/
$('.hover').hover(function() {
$(this).next('.receiver').css('opacity', 0.5);
}, function() {
$(this).next('.receiver').css('opacity', 1.0);
});
http://jsfiddle.net/2K8B2/
(use .siblings or .nextAll if the .receiver is not necessarily the next element)
This works:
​$(document).ready(function() {
$('.hover').hover(function() {
var $parent = $(this).parent('.outerwrapper');
$parent.find('.receiver').css({ opacity : 0.5 });
}, function() {
var $parent = $(this).parent('.outerwrapper');
$parent.find('.receiver').css({ opacity : 1 });
});
});​

Categories