Animations experiencing delays on mobile Chrome

I am currently exploring the world of website animations. I have a version of the jsfiddle code linked below that is similar to what I am working on. The animations function perfectly when viewed on desktop, but when accessed on mobile - specifically on my Chrome browser - there is an unusual lag. This same lag is replicated when I open the jsfiddle on my phone. Even after restarting the Chrome app, the lag disappears but reappears shortly after.

Interestingly, this issue does not occur in Safari.

My device is the latest iPhone running IOS 14.6 with Chrome V90 installed.

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 had difficulty getting JSfiddle to go fullscreen on my phone, hence the small screen size:

Visit this link to see the animation working correctly right after restarting mobile chrome:

However, the animation breaks soon after (when I close or reload the page):

This exact behavior is what I am experiencing on my website using the mobile Chrome browser.

Update: Neither of the suggested solutions worked for me. It is worth noting that this behavior also occurs with text. Although I appreciate the recommendation to use codesandbox, I tried simplifying the code by removing the images and testing it on my iPhone's Chrome browser, but the issue persisted. Wrapping everything in an onload function did not resolve it either.

For now, I have temporarily fixed this using JQuery animations, although I still aim to have CSS3 transitions functioning correctly on my site.

https://codesandbox.io/s/animation-test-forked-tqurn?file=/index.html

https://i.sstatic.net/zdYGS.gif

Answer №1

It seems like a timing issue known as a "race condition" occurring during the page load process. The JavaScript executes before the image request is fully processed.

To comprehend the problem, it is crucial to understand the loading sequence:

  1. Upon loading/reloading, the Server responds with the document (*.html) file

  2. The browser begins parsing the response (*.html) and initiates new requests for each identified resource:

    • CSS
    • JavaScript (JS)
    • Images (IMGs)
  3. These requests finalize in an unpredictable order. For instance, larger images may take longer to load than a *.css file,... certain resources might already be cached by the browser and hence won't trigger a request at all,...

    If the request for the *.js file finalizes prior to the completion of the IMGs request, there won't be a calculated height available for that image and the newly appended CSS class is-visible will still trigger the transition regardless...

  4. Once the IMG requests are completed (image gets rendered), a Content Reflow is activated for the IMG embedding An ongoing transition on elements needing repainting (the IMG) is interrupted and restarts from keyframe 0. This could elucidate the encountered issue.


Here are three potential solutions to resolve the Issue:

A. Retain the ultimate size of the image.

  • Specify a fixed height in CSS and include a dedicated class in the HTML:

    .myImg {
      width: 50px;
      height: 50px;
    }
    
  • You can also include width and height as attributes within the HTML. This ensures that the final dimensions are accessible in JS even when *.css is still loading...

    <img height="50" width="50" class="..." src="...">
    

B. Integrate some form of "load detection" for the images and delay the transition until the image loads entirely.

  • We verify whether the img is already loaded: src is assigned and height is determined-
  • If not, establish an onload event for that particular image (since it's not yet loaded)
  • Additionally, you have the option of utilizing lazy loading for that image and solely loading images 'on demand' (refer to the provided example). The img´s src is featured as a data-src attribute and src is set via JS once the image becomes available.

Now, employing a isLoaded(element) function enables the exclusion of incompletely loaded images within .scroll().

Visit this jsFiddle, or delve into the illustration below...

(previously shown code snippets included for brevity)

(previously shown code snippets included for brevity)

C. Await the load event of the document

You can encapsulate your JS initialization code within a load event pertaining to the entire document. This event triggers after all resources (CSS, IMG,..) have been completely loaded.

window.addEventListener('load', (event) => {
    // Insert JS init code here (images are fully loaded at this point!)
});

Answer №2

Upon testing your code in the Chrome browser on an iPhone, I was unable to replicate the bug seen in your screen recording.

Could it be possible that the lag you experienced was due to trying to run the entire jsfiddle web app on a mobile Chrome browser? Given the complexity of the web app and everything happening behind the scenes, in addition to the specific output being tested, it's likely that performance issues could arise. It may prove beneficial to isolate just the output for testing purposes.

I have transferred your code to a codesandbox environment where you can view the output independently in a mobile browser (refer below). This will allow you to determine whether the issue observed is indeed a coding error.

It is worth mentioning that the image of the ball being used is quite large in file size (~200kb) relative to its display size. Therefore, experiencing flickering during loading on the page would not be unusual.

Here is a scaled-down version of the ball image (reduced by 80% and optimized with ) resulting in a final size of approximately 42kb (which could potentially be further reduced):

https://i.sstatic.net/B1yK9.png


Your code now available on codesandbox:

https://codesandbox.io/s/animation-test-ok1dp

Check out only the output (best viewed in a mobile browser on your device):

See a screen video (recorded on my iPhone using the Chrome browser):

https://i.sstatic.net/vFPbd.gif

Answer №3

I find myself in a similar predicament. The webpage functions seamlessly on other browsers, but on Chrome mobile, it operates with noticeable lag. This issue arose after updating my iPhone to iOS 14.

Answer №4

A simplified example experiencing choppy performance on IOS Google Chrome, while Safari runs smoothly and without any issues.

Hopefully this information can assist in identifying the problem and documenting the discrepancies.

<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

Answer №5

After encountering the same issue, I decided to do some research and found useful resources to identify this bug as an iOS Chrome bug. I hope that sharing these resources will assist others who face this bug in the future.

The discussion regarding this bug started back in 2018 on chromium: https://bugs.chromium.org/p/chromium/issues/detail?id=899130

There is also a more recent and active thread available:

https://bugs.chromium.org/p/chromium/issues/detail?id=1231712

Additionally, you may find a helpful post on css-trick related to this issue:

https://css-tricks.com/forums/topic/problem-with-transition-of-transform-property-in-chrome-on-ios/

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

When initially compiling Angular 5, an error (TS2339) may occur, but after a successful compilation, everything runs smoothly

In a unique scenario, I wrote code that fetches information from an API server without knowing the structure of the response fields. Once I receive the response, I need to create a form for updating the data and sending it back. To handle unknown ngModel p ...

Is your Angular2 form page experiencing reloading issues?

I am currently incorporating Angular2 into my project. I am facing an issue where the page keeps refreshing, and I'm unable to determine the cause. Below is a snippet of my form: <form> <div class="form-group"> ...

What is the best way to delay a recursive JavaScript function for 3 seconds?

Before writing this post, I have already come across the following questions: how-to-pause-a-settimeout-call how-to-pause-a-settimeout-function how-to-pause-a-function-in-javascript delay-running-a-function-for-3-seconds Question The below code snipp ...

Moving information from Ajax to PHP

I'm experiencing an issue with sending data from AJAX to PHP on the same site, "testpage.php". The PHP script doesn't seem to be displaying the data being sent. Using jQuery/Ajax: <script src="http://code.jquery.com/jquery-latest.js" type="t ...

Problem with displaying JSF Bootstrap Glyphicons

I recently encountered a problem in my web app where my Glyphicons in Bootstrap suddenly stopped working, appearing as empty squares for no apparent reason. Even after ensuring that the font files were intact and replacing them with fresh ones from versi ...

Ways to retrieve data from an AJAX success callback function

Within my front end JavaScript application, I need to execute an ajax request in order to retrieve data from the server. Once this data is acquired, I aim to display it within the view. var retrievedData; $.ajax({ url:"/getDataFromServer.json", ty ...

Incorporating EJS Template Body Parameters into AWS Lambda's Handler.js Using Serverless.yml

I have a scenario where I am trying to embed an EJS template named 'ui.ejs' into my handler.js file. The goal is to extract URL query parameters, then pass them to a function called 'ui.js' to retrieve data, which will then be displayed ...

Aligning text fields and text areas is not consistent

Seeking a solution to align two input fields side by side, with a textarea directly below them form ul { list-style: none; text-align: center; } form ul li { display: inline-block; margin-left: auto; margin-right: auto; } #nameform, #emailform ...

Encountering both a CORS error and data in Angular 7

My application is using Angular 7 for the front end and Node.js (express) for the backend. The cors module in the Node.js server.js file is implemented like this: var cors = require('cors') app.use(cors()); When making an API call from the fro ...

I'm encountering an issue with my array in JavaScript while using // @ts-check in VS Code. Why am I receiving an error stating that property 'find' does not exist on my array? (typescript 2.7

** update console.log(Array.isArray(primaryNumberFemales)); // true and I export it with: export { primaryNumberFemales, }; ** end update I possess an array (which is indeed a type of object) that is structured in the following manner: const primar ...

Showing the values of two distinct select boxes in a URL

Here are both select boxes, the goal is to display selected values from both in the URL. This can be achieved by displaying them like this: e.g www.example.com#135+#140 OR www.example.com#135&140 (The order of values doesn't matter as long as bot ...

Combine and blur multiple background images using CSS blending techniques

I am currently working on a website, which is just a demo built in ReactJS: The issue I'm facing is related to the background. The idea behind the app is simple - it consists of 4 parts, with the top part displaying weather information without a bac ...

Reload Popup Box

I am currently developing a website using Django and I am in need of a popup window that can display logging messages and automatically refresh itself every N seconds. In order to achieve this, I am utilizing the standard Python logger, JavaScript, and Daj ...

How can I prevent text highlighting on a website?

Is there a way to lock the copy button on my site without restricting the save as button, which is activated by right click? I want users to be able to save the website as an HTML file, but prevent them from copying text. Can this be achieved using Javas ...

The Kendo Grid is not displaying any data when trying to bind the data source using an ajax callback to the controller

My query is quite similar in nature to this: Binding Kendo Data Source with Async $.ajax calling from C# MVC Controller Action Below is the javascript code used for generating the Kendo grid: $(document).ready(function () { $("#grid").kendo ...

Redux state assigns object to another object

I started with an initial state that looks like this: let initialState = { items: [ { name: 'a' }, { name: 'b' } ], otherItems: [] } I am attempting to copy the items array and assign i ...

An unusual html element

During a recent exploration of a website's code using the inspect tool, I stumbled upon a tag that was completely unfamiliar to me. <gblockquote></gblockquote> I've come across a blockquote before, but never a gblockquote. Interest ...

Retrieving HTML content using scriptJS

Currently utilizing VueJS and encountering an issue after compiling code in production mode. I have one index.html file and several assets that are being uploaded to the cloud. The challenge lies in the fact that the client is not accepting the HTML file ...

Efficiently handling multiple JSON objects in a single PHP function

Currently, I am working on a project that involves populating two dropdown menus where the value of one depends on the other. Specifically, I have three dropdowns - one to select a class, and the other two for selecting subjects and exams based on the sele ...

Identifying the difference between var and JSON.stringify

Take a look at this code snippet: var data = JSON.stringify({ id: _id, ReplyId: _idComment }) openDialog(_url, data, $('#div-modal1')); function openDialog(url, Id, div) { //How can we identify if variable Id is of type JSON.stringi ...