Javascript - Smooth scrolling to element on mobile device - javascript

I am implementing a navigation with anchors that trigger some Javascript to scroll to a specified element, testing it on iOS (Iphone 4) for now.
This is not a new topic and I have done a lot of research before I decided to re-open this question, for no avail. However, my setup also differs a bit from the numerous others in that I first trigger a transition on the navigation horizontally and then the smooth-scroll afterwards. I am wondering if the combination might raise that "buggy" behavior. What make me not really believe this is the fact that waiting for the transition to finish does not resolve the problem (neither using a callback function, nor utilizing window.setTimeout).
Using .scrollTop simply make the browser jump to the element. The transition of the navigation however is smooth.
Using .animate, the transition of the navigation is very laggy. When I apply a very slow animation, it "only" laggs until the transition of the navigation has finished (or some milliseconds after that), whereas the last part of the scroll is quite smooth (this gives me some hope).
The .translate3d CSS option worked fine, but the page is "cut" so that I cannot scroll back after the transition has finished. This is more of a solution for full screen pages I guess.
I do not want to know how to implement an anchor that triggers scrolling, I am asking if someone knows a smooth way to implement scrolling (in my case for iOS). Meaning, I realise that I could have written the JS-Function more generic, but this is only test-code for now.
I have not tested this on android as my target device is iOS, but if this is a known issue only for iOS (e.g. it is working on android) I would be happy if you tell me.
JavaScript / jQuery:
$('#my-link').click(function (event) {
scrollTo('element'); /* hand crafted for now */
event.preventDefault();
});
function scrollTo (element) {
navToggle(); /* This toggles classes on various elements, triggering the respective element's transition */
$('html, body').animate({
'scrollTop': $('#'+element).offset().top /* I deleted the callback (on navToggle) and setTimeout code as it did not make a huge difference to the result */
}, 666);
}
HTML:
<!-- typed out by hand, if there are minor errors they are not related to the issue -->
<a href='#element' id='my-link'>Click to scroll</a>
...
<div id='element'>...</div>
Providing that code is actually just part of the etiquette as I dont look for concrete improvement on what I have written. However, this works like a charme on desktop browsers and if it helps some of you, the better. Also check out this question on how to implement anchor scrolling as it delivers great answers for desktop browsers!
It is late (or early) and my brain is a mess, but I hope I made my question clear (If not I will come back to edit it.): Is there a way to make a mobile browser (e.g. iOS' Safari) smooth scroll like a charme? If already solved, please point me in the right direction.
Thank's a lot and happy coding!

Related

Laggy jittery user experience when updating top/bottom value using javascript scroll event

I am trying out this new implementation where I am updating some div's bottom/top value to emulate fixed position using javascript with scroll event. The problem is while scrolling the div's are getting a fixed position but moving little bit up/down depending on scroll direction. Had to do it this way as I used transform scale. So CSS position fixed doesn't work. Any optimization advice will be very helpful.
the code is here --> Alternative of position fixed using JavaScript shows weird behavior on window resize
If you check my page on desktop/laptop you can experience that. It depends on a lot of variables like how powerful the device is, browser to browser. I am hoping that if anyone has access to MAC OS on safari and chrome or Windows chrome or any desktop/laptop with a decent browser on it may check the user experience and leave a comment about how laggy jittery is it? Is it like okay or bad?
the webpage link --> https://elomymelo.com/soundcore-motion-boom-plus.html
All you need to do is, scroll down half of my page clicking the link above on desktop/laptop. The right side content should get fixed. But may have jittery behavior on scroll. And please leave a comment about how bad is the experience?
Thanks for your time. This will help me a lot to figure out if I should implement it on the other pages or not. Any optimization advice will be very helpful.

Chat like scroll behaviour (ReactJs)

I am trying to implement a chat application, more precisely a scroll behavior for chat application. I think it's best described with a gif.
https://i.imgur.com/NnpMeOx.gif
As you can see, I want to support a few key features:
Scrolling is reversed so on page load, the messages start on the bottom along with the scrollbar
Chat is scrolled to the bottom when user types in a message. (this is easy, no need to pay attention to this part)
If new messages appears (pushed by websocket in real life) it shouldn't disrupt the existing scroll position, unless it's already at the bottom. Then it should scroll to reveal the message automatically.
So far I've implemented 2 solutions:
a) Display flex and flex-direction column-reverse on the scrollable element. This works beautifully out of a box, but only on chrome :( IE (and Edge) as well as firefox just ignores this totally. NOT A GOOD SOLUTION
b) I flipped the container with transform: scaleY(-1) then I reversed the messages and fliped every one of those with the same transform. The main obvious problem here is the scroll (mouse wheel and arrows) is reversed. I sort of fixed it, didn't manage smooth scroll (sucks) but yet again, Edge (and probably IE) just shows scrollbar as disabled. NOT A GOOD SOLUTION
I am really hoping to find somebody who can point me in the right direction because so far, my efforts while logically ok totally failed browser compatibility.
The code is on https://github.com/PeterKottas/react-bell-chat, it's react but tbh, that doesn't matter much as this seems more like a general web dev exercise.
P.S.: I can't use jQuery, hope that's fair. So either css or plain javascript. Like I've said, this doesn't have much to do with react
Well I got no replies and managed to fix it myself so I'll accept this in case it helps somebody in the future.
3rd and final solution:
I kept the direction of scrolling and didn't do any reversing at all. Instead I hooked into onScroll and wheel event, created a few callbacks and managed to mimic the behavior perfectly. You can find more details in the code on https://github.com/PeterKottas/react-bell-chat.

Scroll event on Android Browser not firing. Need workaround

I've created a website with a parallax street scene. See here for an archived version.
It works just fine on all major desktop browsers, and Safari Mobile. It works fine in Mobile Firefox and Chrome for Android Beta also. However the default Android browser has issues with the scroll event. Let me be clear. Scrolling is not the issue. The div scrolls as required. The scroll event doesn't fire. This issue I experience on Honeycomb as well as ICS.
I'm not concerned about other mobile browsers because for mobile screen sizes one usually does not see the parallax scene; mediaqueries and conditional JavaScript loading take care of that. Responsive design and all that jazz.
Basically, I've written a parallise() jQuery plugin that positions each image based on its position and 'depth'. This function is bound to the scroll event.
On Android Browser, this event only fires at the start of the next touch, instead of continuously.
OK, so I thought that perhaps if I bound the function to touchstart, touchmove, and touchend events I would solve my issue. No cigar. Other touch events are also bugged. Applying the suggested workaround causes the events to fire, but as I have to e.preventDefault(), scrolling (the whole point of the exercise) is disabled.
What if I just poll the position of the stage div relative to the window div? Turns out that the position information is only updated at the start of the next touch.
I am at the end of my tether. Any help would be much appreciated.
Even if the touch events worked correctly on the bugged versions of Android, and you were then effectively able to track the native scroll position during a drag, this would be prone to error. For example, it wouldn't account for the momentum animation which happens after the touching has finished.
iOS and Android make sacrifices to improve the performance of scrolling. On both platforms, it's not possible to get the accurate scroll position until the scroll has completed. The scroll event (on the <body>) doesn't fire until the momentum animation is finished. So while your original question is about scroll events on an overflowing <div>, fixing this might not be totally helpful for you anyway.
If you want an animation to update in time with the scroll, then you need to perform the scroll programatically rather than using the browser's native scroll. The best library to do this is iScroll. You can achieve parallax effects very easily as seen in this demo.
If you need more complex effects (the walking character, in your example), you can opt for the "probe" version of iScroll which allows pixel-perfect polling of scroll position in return for reduced performance.
However, there are many downsides to using iScroll:
You may need to change your markup and styling
It is unnecessary overhead for desktop browsers, but due to markup changes may be difficult to use only as a fallback
The scrolling will not feel perfect - on iOS, with its usually excellent scrolling performance - the slight difference in momentum calculation can feel jarring. On Android, the scrolling can become more laggy than usual.
Swipe shim that doesn't need preventdefault on touchstart: https://github.com/TNT-RoX/android-swipe-shim

Safari jittering/jumping (bug?) on first "focus" event of page load

I'm currently fighting a very frustrating bug on Safari, and I'm not sure where else to turn.
It seems most elements (but not all, and I can't discern the differentiating factor) that will trigger a focus event will cause all elements on the page that are transitioned or animated to jump ~2px to the top and left. And this only occurs on the first focus event after the page loads.
It's a little annoying to see the bug, as it's in the logged-in portion of droplr.com, and I have been completely unable to distill down a simpler case on JSFiddle.
If you have/create an account and log-in, click on this edit icon for a drop:
You'll see that on the first focus of the page, things jitter. Here's the timeline when there's a single drop on the page and I trigger focus on an offending element:
With more drops, it's just more of the same, but it seems to max out around 40 paints. And the profiler doesn't suggest anything nefarious. Just a trip through jQuery internals.
If instead of laying elements out via a translate3d or matix3d, I simply use top and left, this bug goes away. After hours and hours of debugging this, I'm at a complete loss.
Hoping someone has seen something similar, could take a look, or could give me advice on debugging next steps.
Thanks so much!
Update: Dave Desandro suggested it was the 3d acceleration kicking in, so I tried it out with a translate instead, and sure enough, that did not cause the jitter. I have no idea why the hardware acceleration would be firing up with a focus event though, and only once.
I've tried setting a transformZ of 0 on page load to go ahead and ramp-up the hardware, but no luck there, either. Any more ideas are welcomed.
I've had this issue a while back and honestly I don't remember what exactly was the cause but here are some of the steps I followed:
Check that you don't have hide() and show() for the same element in the next line or vice versa.
Example:
el.show()
el.hide()
Change Custom fonts to "Arial"
For the elements you don't want focus events add this code at the bottom of your scripts:
noFocusElem.off('focus');
This will make sure to remove any focus handlers you might have added by mistake
Finally place your css before any scripts. It's a know fact that adding css rules after an inline style has been applied may cause jitter especially if you're using line-hieght property
Hope this helps :)
I've had this happen when using custom font kits. Could this be the issue? Some events cause custom fonts to re-draw, which can cause a ever so slight "jitter" in page display.
Sometimes, manually setting heights and widths on all the parent HTML elements can reduce the flicker.
I know this question was posted a while ago and this is a bit of a long shot but here goes:
Maybe as a starting point go back to chrome and look at the composite layering:
Hit this into the address bar:
about:flags
You will be able to enable composite borders from within there. The red borders generally indicate a rendering issue:
http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome
What I have found from time to time is that although there are rendering issues in Chrome the browser copes pretty well with hiding them from me. In other webkit based browsers however the result can be more noticable (i.e. android).
I've also seen flickering occur when z-indexes are being used in conjunction with content that is being transformed.
Either way it would be great to know how you resolved this issue (if you did). Post an answer to your own question perhaps?
A way to avoid spending time fixing load time twitches; you could set the page to hidden then make elements visible with the load. If your page is slow to load, you may want to have a spinner default to visible, then have load hide it. Then you could come back to the issue when you have nothing better to do.
Just my 2c worth.
The first thing I would try:
First in chrome, whack in 'about:flags' (yes I know you're not using Chrome). Find the 'Composited render layer borders' and turn it on. Once this feature is switched on you'll get a rough idea of what is being rendered/hardware accelerated.
See: http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome
and look for any rendering problems. These are normally caused by z-indexes. Play around with any z-indexes and hide/show certain elements until the rendering issues are resolved. Then work from there. translate-z hacks and opacity can also cause problems.
From experience I've found rendering problems in other webkit browsers can be diagnosed using chrome. Flickering is a common occurrence on the stock android browser.
Secondly: take a look at the focus event itself and try things like preventing the default behaviour. Seems like a long shot to me but give it a go.
I haven't tested this, so I will be very surprised if it works... but here's an idea:
$(document).ready(function() {
$(document).focus(function(e) {
e.preventDefault();
});
$(document).click(function() {
$(document).unbind();
});
});
I've been running into the same issue recently and found something that fixed it in my case.
Check for anything that's hidden offscreen like:
text-indent: -9999px;
left: -9999px;
Removing any instance of these from the 3d accelerated elements (including children) stopped the content jump on focus for me.

Jquery animate problem

I have the weirdest of problems.
I have a jQuery function that animates the result bars of a poll.
function displayResults() {
$(".q_answers1 div").each(function(){
var percentage = $(this).next().text();
$(this).css({width: "0%"}).animate({
width: percentage}, 'slow');
});
}
As you can see it is a simple animation that elongates a couple of divs. It works OK until I embed it on my main page. The problem seems to be that there is too much OTHER content that breaks the beauty of the smooth animation. I was thinking of me being lame in implementing the JavaScript, CSS etc. but after a couple of tests and reverse engineering I found out that THE MORE CONTENT (images, text, video) I HAVE ON THE PAGE, THE WORSE THE QUALITY OF THE ANIMATION IS. I can only guess what the reason is... I really like my animation :)! Appreciate the help!
This demo shows how it should look like. I get it to work like this when the page has less content on it. By bad quality I mean not smooth flow of the bars. The worst case is when the bars appear in their final width in an instant.Tested it on Mozilla and Chrome and IE7 - no difference.
Edit: It seems that without the actual examples your hands are tied so here is something to work on. Just look for the red border, pick one answer and click the button. The language is Bulgarian if you are wondering.
A desirable behavior here
I can live with that here
Starting to look weird here
I don't get this here
If all of them look the same to you then my computer is to blame and I don't have to worry about this particular problem anymore, which already took 2 much effort. Use Mozilla if possible.
Edit 2: I found this SO answer that answers some of my questions about the animate() function and how it works, but the problem remains unsolved, at least for my computer.
How much content are we talking here?
If the page is large enough, the browser engine may simply not have enough power to re-render the contents quickly enough to provide a smooth display.
The way jQuery does it's animation is that it periodically updates inline CSS attributes. If the elements you're changing style's of are floated or have other complex interactions with the other elements on the page then the animation wont be smooth.
In short, put less stuff on your page. You might also attempt some sort of iFrame solution or switch to using flash to display the results.
This is just a limitation of the system, unfortunately.

Categories