Safari: jittery shaky text when using css animation on scroll - javascript

In my one-pager website I have some containers that has this property
.containers {
transition: opacity 1000ms cubic-bezier(.25, .46, .45, .94), transform 1600ms cubic-bezier(.19, 1, .22, 1);
}
#page {
position: fixed;
overflow: scroll;
width: 100vw;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 0;
}
where #page is the main wrapper I use in position fixed to prevent browser pull/bounce and make the website feel like an app.
and in my JS I have a function that detects the scroll
$('#page').scroll(function() {
$(".containers").each(function() {
$(this).css('transform', 'translate3d(0, ' + (-$("#page").scrollTop()) + 'px, 0)');
});
});
so whenever the container contains an image the scroll is like butter and silk on both chrome and safari
but when the container contains a paragraph of text. it become jittery
I know the problem can be the fact i have a 1600ms setup that it may create a conflict but why only in Safari (both mobile iphone and desktop)??

I tried different solutions suggested out there, but so far the one that helped me the most is using -webkit-transform: along with transform: and now it feels much better especially on mobile

Related

How to build a CSS animation that "slides in", revealing a text/div after it finishes sliding?

I am trying to mimic the CSS animations from a website here: https://stanographer.com/
I want to copy the way the site:
starts by showing a full screen black div sliding away to the right
"loads" the black background (div tags) behind text (as in "Hi, I'm Stanley Sakai"), expanding left to right and
"loads" the text over the black background div, expanding left to right.
Now you might ask, "Why not just inspect the page, look at the classes on the divs and text, then inspect the CSS sheet in the network tab?" And I've tried that. The CSS looks weird. My friend said it is pre-processed by SASS, whatever that means. Anyway, I cannot decipher the code.
I've been to a few different StackOverflow pages (here's one) & over a dozen different pages on Google. I learned about using keyframes but I haven't figured out how to recreate the effect on Stanographer.com. My friend, who owns the website, also provided this example, but I don't get how to apply it to individual divs. He said something about using the z-index but I just don't see it.
I know that to make the page start with a full black screen & then slide out, I have to trigger a class change using JavaScript. I have:
let blackStuff = document.getElementById("blackness");
window.addEventListener("load", () => {
console.log("loaded");
blackStuff.setAttribute("class", "black-box-out");
},
false
);
.black-box {
position: fixed;
float: left;
top: 0;
width: 100%;
height: 100%;
bottom: 0;
background-color: #000;
z-index: 999999;
-webkit-animation: powerslide 0.5s forwards;
-webkit-animation-delay: 2s;
animation: powerslide 0.5s forwards;
animation-delay: 2s;
}
#-webkit-keyframes powerslide {
100% {
left: 0;
}
}
#keyframes powerslide {
100% {
left: 0;
}
}
.black-box-out {
margin-left: 100%;
animation: slide 0.5s forwards;
-webkit-transition: slide 0.5s forwards;
transition: slide 0.5s forwards;
}
<div id="blackness" class="black-box"></div>
But this just makes the "blackness" div disappear instantly on page load. I want it to slide out. Clearly, I don't get how to use CSS animations.
If you are interested in seeing more of what doesn't work, read on. Otherwise, you can skip this section: it only shows my failed trials.
I've learned how to make a CSS animation expand horizontally from 0:
.wrapper {
position: relative;
overflow: hidden;
width: 500px;
height: 50px;
border: 1px solid black;
}
.slide-custom {
width: 500px;
height: 50px;
background: cyan;
position: relative;
-webkit-animation: slideIn 2s forwards;
animation: slideIn 2s forwards;
}
/* moz and webkit keyframes excluded for space */
#keyframes slideIn {
0% {
transform: scaleX(0);
}
100% {
transform: scaleX(1);
}
}
<div class="wrapper slide-custom">
<h1 class="slide-custom">
<span>MEET ROLY POLY.</span>
<!-- expands horizontally from 0 width to 100% width -->
</h1>
</div>
And I've learned to make text "slide in" from the left, though it starts at 100% width when I want it to start at 0% width:
/* CSS */
.test-slide {
animation-duration: 3s;
animation-name: testSlide;
}
#keyframes testSlide {
from {
margin-left: 0%;
width: 50%;
}
to {
margin-left: 100%;
width: 100%;
}
}
<div class="test-slide">
<h1><span>ABOUT.</span></h1>
<!-- will slide in from the left -->
</div>
There's more -- unfortunately none of it mimics the website I'm trying to copy.
Explanation
There are multiple ways to achieve what you want actually. I did not opt to animate width. The first few frames of the animation will be not as expected.
So instead, we can use clip-path. What clip-path basically does is masking. You can "crop" a div such that only a part of it is visible. We will utilise clip-path and ::before or ::after pseudo-element (either is fine) to create this animation. What we need to do:
Create the pseudo-element and position it such that it covers (is on top) the whole animatable element (position: absolute)
Set the pseudo-element's background to black
Using clip-path, mask the animatable element to display no parts of the element (this will also cause the pseudo-element to not be displayed as it is part of the element). The direction of the clipping is important. The direction here is from the right side to the left side.
Using animation and #keyframes, unmask the previously masked div. This will reveal it slowly from the left side to the right side (because initially, we masked it from the right to left; upon unmasking, the reverse direction happens)
Upon unmasking the element, the pseudo-element will be on top of the text we want to display
After a short while later, mask the pseudo-element (not the whole element) from the right direction to the left direction, again using clip-path so that the text seems revealed slowly
It works! However, I recommend reading about clip-path. Also, one really handy clip-path CSS generator I really like to use is this (if you want to clip from the right to left, you should drag the points from the right to left). I also highly recommend reading about CSS positioning (a staple in good CSS animations). You needn't be using z-index: 9999; you generally want to keep track of the z-index you use.
Solution
Here's a working solution using the described method. Try running it.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: Helvetica;
}
body,
html {
width: 100%;
height: 100%;
}
#wrapper {
background: #555555;
width: 100%;
height: 100%;
color: white;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#wrapper * {
margin: 5px;
}
.heading {
font-size: 3em;
padding: 10px 5px;
}
.caption {
font-size: 1em;
padding: 5px;
font-family: Courier;
}
.animatable {
position: relative;
clip-path: polygon(0 0, 0 0, 0 100%, 0% 100%);
animation: .75s cubic-bezier(1,-0.01,.12,.8) 1s 1 reveal forwards;
}
.animatable::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #20262b;
padding: inherit;
animation: .75s cubic-bezier(1,-0.01,.12,.8) 1.75s 1 hideBlack forwards;
}
#keyframes reveal {
from { clip-path: polygon(0 0, 0 0, 0 100%, 0% 100%); }
to { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }
}
#keyframes hideBlack {
from { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }
to { clip-path: polygon(100% 0, 100% 0, 100% 100%, 100% 100%); }
}
<div id="wrapper">
<div class="heading animatable">Hi, I am Richard!</div>
<div class="caption animatable">I am a person.</div>
</div>
Although the simple animation you wanted can be created using merely CSS, I still suggest you read about how to make animations using JavaScript and the various libraries it has in making animations. This is because once there are many animations and transitions going on, it becomes hard to keep track of animations (especially when you want animations to start after another animation ends). A good library is anime.js (do explore more options before settling on one). Furthermore, notice how the animations only appear upon scrolling down in the website you provided? That's doable only with JS (one such method is using IntersectionObserver API provided by most browsers).
Here you have some CSS3 animations, you trigger that animation when the .entrance-animation gets the .active class.
You'll need an observer to watch when the item gets into view and, when the item is visible, you add the .active class to it.
Hope it helps!
setTimeout(() =>
{
let animate = document.querySelectorAll('.entrance-animation');
animate.forEach(item => item.classList.add('active'));
}
,1000);
.entrance-animation
{
position: relative;
color: blueviolet;
white-space: nowrap;
font-size: 24px;
width: 0;
overflow: hidden;
transition: width 0.5s ease;
}
.entrance-animation::before
{
content: '';
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 100%;
background-color: black;
z-index: 10;
transition: width 0.5s ease;
transition-delay: 0.5s;
}
.entrance-animation.active
{
width: 100%;
}
.entrance-animation.active::before
{
width: 0%;
}
<p class="entrance-animation">
Hello
</p>
<p class = "entrance-animation">
Here we are
</p>
You can use CSS3 transitions or maybe CSS3 animations to slide in an element.
For browser support: http://caniuse.com/
I made two quick examples just to show you how I mean.
CSS transition (on hover)
Demo One
Relevant Code
.wrapper:hover #slide {
transition: 1s;
left: 0;
}
In this case, Im just transitioning the position from left: -100px; to 0; with a 1s. duration. It's also possible to move the element using transform: translate();
CSS animation
Demo Two
#slide {
position: absolute;
left: -100px;
width: 100px;
height: 100px;
background: blue;
-webkit-animation: slide 0.5s forwards;
-webkit-animation-delay: 2s;
animation: slide 0.5s forwards;
animation-delay: 2s;
}
#-webkit-keyframes slide {
100% { left: 0; }
}
#keyframes slide {
100% { left: 0; }
}
Same principle as above (Demo One), but the animation starts automatically after 2s, and in this case I've set animation-fill-mode to forwards, which will persist the end state, keeping the div visible when the animation ends.
Like I said, two quick example to show you how it could be done.
EDIT: For details regarding CSS Animations and Transitions see:
Animations
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_animations
Transitions
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_transitions
Hope this helped.

Transition for text box to top of page not working properly for Safari and Chrome on IOS

There is text box at the bottom of page. Whenever it is focused it should be transitioned to the top of page. This is because I want to show suggestions to user when typing. This implementation is working for PC and for android devices. While for IOS devices when the visual keypad is displayed the Text box goes out of view port but appears again when I press 'done'.
Following is the CSS I am using:
#searchSection {
position: relative;
/*-webkit-overflow-scrolling: auto;*/
transition: all 0.5s;
-webkit-transition: all 0.5s; /*safari*/
-webkit-transition-delay: 0;
-moz-transition: all 0.5s;
-o-transition: all 0.5s;}
#searchSection .focused {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
height: 100%;
background: #e8e8e8;
width: 100%;
z-index: 1000;
/*-webkit-backface-visibility: hidden;*/}
Following is the JS which modifies the class name:
goog.events.listen(
searchInput,
goog.events.EventType.FOCUS, function () {
goog.dom.classlist.add(searchSection, 'focused');
}
);
Is there any solution/workaround to it?
In my experience Safari on iOS (Chrome is using the same engine there) has problems with inputs in containers that have position: fixed.
I helped myself by using position: absolute instead and scrolling to the input element before giving it focus.

JQuery UI `Slide` Transition Issues With CSS `transform

When executing JQueryUI's slide transition on an element with a CSS transform the top half of the element is being hidden during the animation. Is there some way I can adjust my JQueryUI animation and/or CSS to prevent this from happening?
JSFiddle: I've created a JSFiddle with the appropriate code - http://jsfiddle.net/9dTkL/4/
To accomplish the vertical centering, I do the following:
<style>
#banner-welcome {
background-color: rgba(0, 0, 0, 0.5);
position: absolute;
width: 100%;
top: 50%;
transform: translateY(-50%);
-ms-transform: translateY(-50%);
-o-transform: translateY(-50%);
-webkit-transform: translateY(-50%);
}
</style>
The top and transform within the CSS allow the banner to fall into the center.
To perform the animation, I execute the following:
$('#banner-welcome').toggle(
'slide',
function()
{
document.location.href = "#/" + destination;
}
);
When the animation starts the top half of the #welcome-banner disappears, and the bottom half animates. I've removed the transform from the CSS and everything works great -- except that my banner is no longer centered.
I am performing the vertical centering this way due to a combination of AngularJS and ng-views. I had previously used JavaScript to center the element, but adding the logic to the $(window).resize() event caused problems in other ng-views. I needed a way to isolate this to the specific ng-view.
Is there something I can adjust with my animation or CSS that would not cause the top half of the banner to disappear?
toggle is removed as of 1.9: http://api.jquery.com/toggle-event/
so please use animate or slideDown or slideUp method
also the transform property doesn't need prefixes
#banner-welcome {
background-color: rgba(0, 0, 0, 0.5);
position: absolute;
width: 100%;
top: 50%;
transform: translateY(-50%);
}
have you tried adding transform-origin property
#banner-welcome {
background-color: rgba(0, 0, 0, 0.5);
position: absolute;
width: 100%;
top: 50%;
transform-origin: 50% 50% 0;
transform: translateY(-50%);
}
im not seeing the top part disappear in latest Firefox 24

Cross-device CSS problems

I just tested my website with both Google Chrome Desktop and Mobile version, and it seems like the label for the slide-out menu is not displaying. It does work, it's just not displayed, and I have no idea why. Changing positions does not work here, because the slide-out design I'm using is relying on positions, and I need them to be fixed.
Related CSS:
#slideout #label {
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
transform: rotate(90deg);
display:block;
float:right;
margin:46% 0 0 0;
padding: 0 2px 6px 2px;
font-size: 20px;
position: fixed;
left:-36px;
-webkit-transition:left 0.5s ease-in-out,opacity 0.5s ease-in-out;
-moz-transition:left 0.5s ease-in-out,opacity 0.5s ease-in-out;
-o-transition:left 0.5s ease-in-out,opacity 0.5s ease-in-out;
transition:left 0.5s ease-in-out,opacity 0.5s ease-in-out;
background-color:#fff;
border-bottom:0 !important;
border-radius:8px 8px 0 0;
}
#slideout.opened #label {
left: 86px;
}
JavaScript:
$('#label').on('click',function(){
$('#slideout').toggleClass('opened');
});
EDIT: I tried using this code:
#slideout #label {
position: absolute;
left: 90px;
}
#slideout {
position: relative;
}
But What happens is, the label is in the right place, but it is cut off and invisible.
position:fixed is unpredictable on mobile, you should be able to fix it by switching to position:relative; even though that may be difficult. There is some decent coverage on this here: http://www.quirksmode.org/blog/archives/2012/10/budding_consens.html
Look at the opacity property of your slide panel.
You set opacity to 0.3 when hiding the panel, your label is inside your panel, so it fades too.
But it looks like there is some problem in chrome mobile, and opacity property. the button disappears completely. You should try to put it outside your panel. When I disable the opacity : 0.3 of the slide panel in chrome inspector, the label appears.
I think you should investigate this.
Try the following in addition to what you have:
#slideout {
position: relative;
}
#slideout #label {
position: absolute;
top: 46%;
right: -10px; (approximate)
}
Obviously, these are overrides for a couple, so integrate them at your discretion. Also, remove the float: right;
That's only a guess, but the problem might come from the javascript event handling which is different on a mobile because the event is actually different. I guess the click event is triggered twice on mobile, something like "touch" or "mousedown", so therefore, the event happening twice, the toggleClass() adds and remove the wanted class. So either you detect mobile with javascript in order to add the correct event
Detecting a mobile browser (detect mobile)
jQuery mobile (click event) (appropriate event)
Or you change the toggle class for "addClass" and "removeClass" with a timer. Something like
var animating = false;
var open = false;
$('#label').on('click',function(){
if (!animating) {
animating = true;
if (open) {
$('#slideout').removeClass('opened');
} else {
$('#slideout').addClass('opened');
}
setTimeout(function() { animating = false }, 500); // 500 = 0.5s of css animation
}
});
Hope this helpsĀ­.
use postion:fixed in your css along with respective width-height property.

Parallax and vibrate background image with scroll

I need background image parallax and vibrate little bit when scrolling with mouse.
Background position is working with jQuery's css() function but not vibrating.
When ii firebug it result is
<div data-speed="10" data-type="background" style="height: 1000px;
background-position: 50% 0px; animation: 0s ease 0s normal none 1 NaNpx;"
class="parallax-container" id="intro">
I am using jQuery's code for this, and testing in Mozilla.
/*parallex backgound*/
$glob('div[data-type="background"]').each( function() {
var $bgobj = $glob(this); // assigning the object
$glob(window).scroll( function() {
var yPos = -($window.scrollTop() / 10);
var coords = '50% '+ (yPos) + 'px';
$bgobj.css({'background-position': coords}).animate({
'-webkit-animation': 'vibrateAnim 1s ease', /* Safari 4+ */
'-moz-animation': 'vibrateAnim 1s ease', /* Fx 5+ */
'-o-animation': 'vibrateAnim 1s ease', /* Opera 12+ */
'animation': 'vibrateAnim 1s ease' /* IE 10+ */
},500);
});
});
HTML:
<div id="intro" class="parallax-container" style='height:1000px;' data-type="background" data-speed="10">
<div id="mainTitleText" class="top-content">
<img class="logo" src="images/logo.png">
</div><!-- mainTitleText -->
</div><!--home-->
CSS:
#-moz-keyframes vibrateAnim {
0% { top: -10px; }
10% { top: 10px; }
20% { top: -10px; }
30% { top: 10px; }
40% { top: -10px; }
50% { top: 10px; }
60% { top: -10px; }
70% { top: 10px; }
80% { top: -10px; }
90% { top: 10px; }
100% { top: -10px; }
}
DEMO:
jsFiddle
I need as in link https://victoriabeckham.landrover.com/INT
jsFiddle DEMO
(Tip: Remove /show/ in URL to access jsFiddle Edit Page).
Consider using the jQuery Vibrate plugin in your Parallax website. The parallax website you mentioned in comments is using a custom written parallax script for that site, so no plugin is available.
The above jsFiddle uses parallax plugin jQuery Parallax v1.1.3 along with it's revised demo, modified with an extra vibrating trainers footwear object.
The benefit of this vibrate plugin is that it has interaction with the mouse, to stop vibrating when the mouse is over any text when used with reverse option. That is useful so visitors can ready message clearly.
Side note: In the jsFiddle, the vibrating object is in between 2 other elements, so the mouseover will not apply in that case due to DOM layout order.
$('#extra').vibrate({
speed: 50, // Vibration speed in milliseconds
trigger: "mouseover", // Triggering event
reverse: true, // Reverse behaviour
overEffect: "stop", // Over effect, see details below
vibrateClass: "", // CSS class applied when vibrating (New in vers. 1.1!)
overClass: "" // CSS class applied when over effect is triggered (New in vers. 1.1!)
});

Categories