The homepage of my project has a gallery of images that scroll every x seconds automatically.
On Chrome and Firefox everything is fine, but on Safari only the first image shows well and the others are blank slides.
Here the HomePage component:
import { useEffect, useState, useRef } from 'react'
import './home.styles.scss'
const galleriaDiImmagini = [
'https://i.ibb.co/LCzz4P4/1.webp',
'https://i.ibb.co/txwnt76/2.webp',
'https://i.ibb.co/XCHDFpx/3.webp',
'https://i.ibb.co/S6F1rtc/4.webp',
'https://i.ibb.co/P5GwHPz/5.webp'
]
const delay = 6000
const HomePage = () => {
const [index, setIndex] = useState(0)
const timeoutRef = useRef(null)
const resetTimeout = () => timeoutRef.current ? clearTimeout(timeoutRef.current) : null
useEffect(() => {
resetTimeout()
timeoutRef.current = setTimeout(
() =>
setIndex(prevIndex =>
prevIndex === galleriaDiImmagini.length - 1 ? 0 : prevIndex + 1
),
delay
)
return () => {
resetTimeout()
}
}, [index])
return (
<div className='homepage'>
<div
className='slide-container'
style={{ transform: `translate3d(${-index * 100}%, 0, 0)` }}
>
{
galleriaDiImmagini.map((img, i) => (
<div
key={ i }
className='slide'
style={{
'background': `url(${img}) no-repeat center center fixed`
}}
>
</div>
))
}
</div>
<div className="punti-container">
{galleriaDiImmagini.map((_, i) => (
<div
key={i}
className={`punto${index === i ? " active" : ""}`}
onClick={() => {
setIndex(i);
}}
>
</div>
))}
</div>
</div>
)
}
export default HomePage
And the styles:
$colore-tosto: #2FA7CF;
.homepage {
position: relative;
overflow: hidden;
height: 100vh;
.slide-container {
height: 100%;
width: 100%;
position: relative;
white-space: nowrap;
-webkit-transition: transform 1000ms ease-in-out;
-moz-transition: transform 1000ms ease-in-out;
-o-transition: transform 1000ms ease-in-out;
transition: transform 1000ms ease-in-out;
.slide {
display: inline-block;
height: 100%;
width: 100%;
background-size: contain;
-webkit-background-size: contain;
-moz-background-size: contain;
-o-background-size: contain;
}
}
.punti-container {
width: 100%;
text-align: center;
position: absolute;
top: 75%;
.punto {
display: inline-block;
height: 20px;
width: 20px;
border-radius: 50%;
background-color: rgba($color: #ffff, $alpha: 0.5);
border: 2.5px solid $colore-tosto;
margin: 15px;
&:hover {
cursor: pointer;
background-color: rgba($color: #ffff, $alpha: 0.9);
}
&.active {
background-color: white;
}
}
}
#media only screen and (max-width: 730px) {
.punti-container {
top: 80%;
.punto {
height: 17px;
width: 17px;
border-width: 1.5px;
margin: 10px;
}
}
.slide-container {
.slide {
background-size: auto 100% !important;
}
}
}
}
And here a live video of the site.
I thank in advance anyone who tries to give me a hand.
You need to remove background-attachment : fixed not supported on the safari , check it here Can I use , last parameter of background css key is an attachment
Problem
Seems like safari has a bug and creates problem when using transition: all or transition: xSeconds. It may sometimes crash.
Solution
Change it to transition: color 1000ms ease-in-out; (Or any other property. Just dont keep all ).
Read more here: My website crashes Safari (both desktop and iOS) consistently
I would check:
if you have any extensions that may be limiting your code's behavior in Safari:
did you inspect your code in Safari and check if the CSS is being imported
Split your CSS code in chunks, and start adding each chunk gradually, and check the browser to see if its working; if it suddenly stops working then that's the faulty chunk. You then need to see if there are any incompatibilities with a property or something like that
I'd like to make both .quote-container and #new-quote elements in the same line even if the window width is very small. For example 83pixels. Using min-width on the .quote-container element worked, however, using the same technique on the #new-quote element didn't work.
Maybe that's because #new-quote isn't the children of .quote-container? I even tried to make it a child and it was even worse (picture was taken on the desktop window size):
What I'd like to achieve in visual:
var getNewQuote = function(callback) {
var quote = {};
quote.text = 'Example';
quote.author = 'Example';
$(".loading").hide();
callback(quote);
};
var quoteContainerStartingPadding,
quoteContainerEndingPadding,
newQuoteEndingPadding;
if ($(window).width() > 648) {
quoteContainerStartingPadding = "0 2.5rem";
quoteContainerEndingPadding = "2.5rem";
newQuoteEndingPadding = "2.5rem .75rem";
} else {
quoteContainerStartingPadding = "0 1.5em";
quoteContainerEndingPadding = "1.5rem";
newQuoteEndingPadding = "1.5rem .75rem";
}
$(".quote-container").css("padding", quoteContainerStartingPadding);
getNewQuote(function(quote) {
var getRandomColor = function() {
var colors = ["#ff9966", "#7f00ff", "#396afc", "#0cebeb", "#06beb6", "#642b73", "#36d1dc", "#cb356b", "#3a1c71", "#ef3b36", "#159957", "#000046", "#007991", "#56ccf2", "#f2994a", "#e44d26", "#4ac29a", "#f7971e", "#34e89e", "#6190e8", "#3494e6", "#ee0979"],
randomNumber = Math.floor(Math.random() * colors.length);
return colors[randomNumber];
};
var updateText = function($t) {
var twitter = "https://twitter.com/intent/tweet?hashtags=quotes&related=freecodecamp&text=";
twitter += '"' + quote.text + '" ';
twitter += quote.author;
var tumblr = "https://www.tumblr.com/widgets/share/tool?posttype=quote&tags=quotes,freecodecamp&caption=";
tumblr += quote.author;
tumblr += "&content=";
tumblr += quote.text;
tumblr += "&canonicalUrl=https%3A%2F%2Fwww.tumblr.com%2Fbuttons&shareSource=tumblr_share_button";
var $icon = $("<i class='fa fa-quote-left'>").prop("aria-hidden", true);
$t.find(".quote-text").html("").append($icon, quote.text);
$t.find(".quote-author").html("- " + quote.author);
$("#tweet-quote").attr("href", twitter);
$("#tumblr-quote").attr("href", tumblr);
};
var calcNewHeight = function(q) {
var $temp = $("<div>", {
class: "quote-container temp",
}).appendTo($("body"));
$temp.append($("<div>", {
class: "quote-text"
}), $("<div>", {
class: "quote-author"
}));
updateText($temp, q);
var h = $temp.height() + 40;
$temp.remove();
return h;
};
var changeColor = function(newColor) {
$("body, .button:not(#new-quote)").animate({
backgroundColor: newColor
});
$("#new-quote").animate({
color: newColor
});
$(".quote-text, .quote-author").css("color", newColor);
if ($("#modStyle").length === 0) {
$("head").append("<style id='modStyle'>#new-quote:before {background:" + newColor + ";} .lds-eclipse {box-shadow: 0 .25rem 0 0 " + newColor + ";}</style>");
} else {
$("head style#modStyle").html("#new-quote:before {background:" + newColor + ";} .lds-eclipse {box-shadow: 0 .25rem 0 0 " + newColor + ";}");
}
};
var getQuote = function() {
var nc, nh = 0;
nc = getRandomColor();
nh = calcNewHeight(quote);
changeColor(nc);
$(".quote-container, #new-quote").animate({
height: nh / 16 + "rem",
}, {
duration: 1000,
queue: false
});
$(".quote-container").animate({
padding: quoteContainerEndingPadding
}, {
duration: 1000,
queue: false
});
$("#new-quote").animate({
padding: newQuoteEndingPadding
}, {
duration: 1000,
queue: false
});
updateText($(".quote-container"), quote);
$(".quote-container").children().not($(".loading")).fadeTo(750, 1);
};
$(".quote-container, #new-quote").css({
visibility: "visible",
height: 0
});
$("#new-quote").css("padding", "0 .75rem");
getQuote();
}
);
var two = function() {
$(".quote-container").children().not($(".loading")).hide();
$(".loading").show();
getNewQuote(function(quote) {
var getRandomColor = function() {
var colors = ["#ff9966", "#7f00ff", "#396afc", "#0cebeb", "#06beb6", "#642b73", "#36d1dc", "#cb356b", "#3a1c71", "#ef3b36", "#159957", "#000046", "#007991", "#56ccf2", "#f2994a", "#e44d26", "#4ac29a", "#f7971e", "#34e89e", "#6190e8", "#3494e6", "#ee0979"],
randomNumber = Math.floor(Math.random() * colors.length);
return colors[randomNumber];
};
var updateText = function($t) {
var twitter = "https://twitter.com/intent/tweet?hashtags=quotes&related=freecodecamp&text=";
twitter += '"' + quote.text + '" ';
twitter += quote.author;
var tumblr = "https://www.tumblr.com/widgets/share/tool?posttype=quote&tags=quotes,freecodecamp&caption=";
tumblr += quote.author;
tumblr += "&content=";
tumblr += quote.text;
tumblr += "&canonicalUrl=https%3A%2F%2Fwww.tumblr.com%2Fbuttons&shareSource=tumblr_share_button";
var $icon = $("<i class='fa fa-quote-left'>").prop("aria-hidden", true);
$t.find(".quote-text").html("").append($icon, quote.text);
$t.find(".quote-author").html("- " + quote.author);
$("#tweet-quote").attr("href", twitter);
$("#tumblr-quote").attr("href", tumblr);
};
var calcNewHeight = function(q) {
var $temp = $("<div>", {
class: "quote-container temp",
}).appendTo($("body"));
$temp.append($("<div>", {
class: "quote-text"
}), $("<div>", {
class: "quote-author"
}));
updateText($temp, q);
var h = $temp.height() + 40;
$temp.remove();
return h;
};
var changeColor = function(newColor) {
$("body, .button:not(#new-quote)").animate({
backgroundColor: newColor
});
$("#new-quote").animate({
color: newColor
});
$(".quote-text, .quote-author").css("color", newColor);
if ($("#modStyle").length === 0) {
$("head").append("<style id='modStyle'>#new-quote:before {background:" + newColor + ";} .lds-eclipse {box-shadow: 0 .25rem 0 0 " + newColor + ";}</style>");
} else {
$("head style#modStyle").html("#new-quote:before {background:" + newColor + ";} .lds-eclipse {box-shadow: 0 .25rem 0 0 " + newColor + ";}");
}
};
var getQuote = function() {
var nc = getRandomColor(),
nh = calcNewHeight(quote);
$(".quote-container").children().not($(".loading")).css("opacity", 0);
changeColor(nc);
$(".quote-container, #new-quote").animate({
height: nh / 16 + "rem",
}, {
duration: 1000,
queue: false
});
updateText($(".quote-container"), quote);
$(".quote-container").children().not($(".loading")).fadeTo(750, 1);
};
getQuote();
});
}
;
html,
body {
height: 100%;
width: 100%;
}
body {
margin: 0;
padding: 0;
background: #333;
color: #333;
font-family: sans-serif;
}
.quote-container {
width: 35%;
background: #fff;
margin: 0;
display: inline-block;
vertical-align: middle;
border-radius: 0.1875rem;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
visibility: hidden;
min-width: 15rem;
}
.quote-text {
font-size: 1.625rem;
}
.quote-text i {
margin-right: 0.6rem;
}
.quote-text p {
display: inline;
}
.quote-author {
font-size: 1rem;
margin: 0 0.4rem 2rem 0;
text-align: right;
}
.button {
padding: 0.75rem;
text-align: center;
font-size: 1rem;
color: #fff;
border-radius: 0.1875rem;
display: inline-block;
cursor: pointer;
-webkit-user-select: none;
user-select: none;
}
.button:not(#new-quote):hover {
opacity: 0.8 !important;
}
.button:not(#new-quote) {
min-width: 1rem;
min-height: 1rem;
}
.button i {
vertical-align: middle;
}
#new-quote {
white-space: nowrap;
writing-mode: vertical-lr;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
vertical-align: middle;
background: #fff !important;
margin: 0;
position: relative;
right: 0.25625rem;
color: #333;
visibility: hidden;
}
#new-quote:before {
content: "";
position: absolute;
height: 100%;
width: 0.0625rem;
bottom: 0;
left: 0;
visibility: hidden;
-webkit-transform: scaleY(0);
transform: scaleY(0);
-webkit-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
}
#new-quote:hover:before {
visibility: visible;
-webkit-transform: scaleY(1);
transform: scaleY(1);
}
.v-align {
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
}
.text-center {
text-align: center;
}
footer {
font-size: 0.85rem;
margin-bottom: 1rem;
}
footer a {
text-decoration: none;
color: #fff;
position: relative;
}
footer a:before {
content: "";
position: absolute;
width: 100%;
height: 0.0625rem;
bottom: 0;
left: 0;
background: #fff;
visibility: hidden;
-webkit-transform: scaleX(0);
transform: scaleX(0);
-webkit-transition: all 0.3s ease-in-out 0s;
transition: all 0.3s ease-in-out 0s;
}
footer a:hover:before {
visibility: visible;
-webkit-transform: scaleX(1);
transform: scaleX(1);
}
/* Loading animation */
#keyframes lds-eclipse {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
50% {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
#-webkit-keyframes lds-eclipse {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
50% {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.loading {
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
}
.lds-eclipse {
-webkit-animation: lds-eclipse 1s linear infinite;
animation: lds-eclipse 1s linear infinite;
width: 10rem;
height: 10rem;
border-radius: 50%;
margin: auto;
}
#media (max-width: 62.5em) {
.quote-container {
width: 50%;
}
}
#media (max-width: 50em) {
.quote-container {
width: 65%;
}
}
#media (max-width: 17.96875em) {
.quote-container {
width: 40%;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="v-align text-center">
<div class="quote-container">
<div class="quote-text">
</div>
<div class="quote-author"></div>
<a id="tweet-quote" class="button"><i class="fa fa-twitter"></i></a>
<a id="tumblr-quote" class="button"><i class="fa fa-tumblr"></i></a>
<div class="loading">
<div class="lds-eclipse"></div>
</div>
</div>
<div id="new-quote" class="button">New quote</div>
<footer>
Created by LukasLSC
</footer>
</div>
EDIT 1: Codepen: https://codepen.io/Kestis500/pen/KZvXgB?editors=0110
If you want to align things in CSS you usually have two different positioning concepts you can use for this purpose:
display (flex)
float
Usually it is a good idea to put all elements you want to align in a wrapping container like a div. In this manner you can just focus on your aligning issue and forget about the general layout - means where you want to have your aligned elements in the layout eventually. You can later on just position the wrapper and do not have to worry about the elements inside.
Another best practice is to give all your elements that this container inherits from a dimension (at least width). A common mistake is that elements that should be aligned break just because the parent element does not have enough space to fit all elements on one line. If you want to know why I provide an example at the end, just follow the *.
But lets go back to the two concepts that you can use. Which one you should use depends on one hand what other attributes you need to give the respective elements and what browsers you need to support. If you only want to support newer browser versions you can go with flexbox, the more secure way to do this is use percentages for widths and float.
Flexbox
.container {
display: flex;
flex-direction: row; // this makes your elements align horizontally
}
.child1 {
flex: 1 1 auto;
}
.child2 {
flex: 0 1 auto;
}
The flex attribute determines the dimension of a child. So consider the parent as width: 100%; and the numbers you give as a first parameter to flex is the ratio of the child's dimension compared to the other children.
Float
.container {
overflow: hidden;
width: 100%; // this must be relative to the containers parent of course
}
.child1 {
width: 75%;
float: left;
}
.child2 {
width: 25%;
float: left;
}
Mind that float takes effect on the elements following in the document flow AFTER the element that you give the float attribute. Also take into account that you might need to calculate margins, paddings or borders in additionally to the elements' widths (except for paddings when using box-sizing: border-box) and that elements containing only floated elements lose their "automatic" dimensions as floated elements lose their information about height and width as well. (overflow: hidden on the container solves this issue for you)
*In a responsive design e.g. you should give the highest parent a width of 100%. If you provide to a child width: 50%; it will now have exactly 50% of the entire width. If you now give the child of the child width: 50% it will be 25% of the entire width. This is less error prone then giving the child's child directly 25%. Let's assume later on you give the child a width of 50% the width of the child's child (25%) will relate to the childs width instead of the parent. So you will end up with a width of 12.5% for the child's child relative to the entire width.
I am having a mysterious problem that did not exist yesterday (you know those?). For some reason, these grey boxes are appearing at the edges of an element that appears when a user hovers over its parent element. they appear to the right and bottom. Essentially, everything below the check and x images is a div with a class of .bottom. I have set to 50% of parent height and 100% of its width. These are react components, so it may be a tad hard to follow. The EventDetail component is nested in the Event component.
.eventcontainer {
padding: 5px;
width: 960px;
margin: 20px auto;
}
.event {
margin-top: 2%;
width: 960px;
border-color:#496DD9;
border-style: dotted;
font-size: 0.5em;
height: 300px;
position: relative;
-webkit-transition: height 300ms ease-out;
}
.event:hover {
height: 400px;
-webkit-transition: height 300ms ease-in;
}
.event:hover .hidden {
display: block;
opacity: 1;
-webkit-transition: opacity 300ms ease-in 200ms;
}
.hidden {
opacity: 0;
overflow: scroll;
-webkit-transition: opacity 100ms ease-out;
}
.bottom {
position: absolute;
bottom: 0;
padding-bottom: 2%;
padding-left: 2%;
font-size: 13px;
width: 100%;
height: 50%;
}
const EventDetail = (props) => {
const options = {
color: '#DE5745',
trailWidth: 1,
strokeWidth: 10,
};
const containerStyle = {
width: '100px',
height: '20px',
};
const showUpdate = (e) => {
e.preventDefault();
props.dispatch(renderUpdate(props.id));
};
return (
<div className=" bottom hidden" >
<p>Attendance</p>
<div className="progressbar">
<Line progress={(props.attending / props.capacity)} containerStyle={containerStyle} initialAnimate options={options} containerClassName={'.progressbar'} />
<span>{props.attending}</span><span>/</span><span> {props.capacity}</span>
</div>
{/* <div>{props.attendeeHelperFunction(props.attendeeList)}</div>*/}
<p>Description:</p>
{props.description === '___' ? <p>The owner did not provide a description. So mysterious</p> : <p>{props.description}</p>}
{window.localStorage.getItem('userid') === props.owner_id ?
<div>
<Update
event_title={props.title}
event_description={props.description}
event_capacity={props.capacity}
event_id={props.event_id}
/>
</div>
: null}
</div>
);
};
const Event = (props) => {
const attendHandler = (e) => {
e.preventDefault();
props.dispatch(attendEvent(props.id))
.then(() => {
props.dispatch(fetchEvents());
});
};
const flakeHandler = (e) => {
e.preventDefault();
props.dispatch(flakeEvent(props.id))
.then(() => {
props.dispatch(fetchEvents());
})
.catch(err => console.log(err));
};
return (
<div className="event">
<section className="eventdescription">
<p>{props.title}</p>
<p>{props.date}</p>
<p>Hosted by: {props.owner}</p>
<p>{console.log('EVENT', renderEvents)}</p>
</section>
<section className="attend"><img onClick={attendHandler}className="eventgraphic" src={check} alt="" /></section>
<section className="unattend"><img onClick={flakeHandler}className="eventgraphic" src={crossout} alt="" /></section>
<EventDetail
title={props.title}
event_id={props.id}
owner_id={props.owner_id}
attending={props.attendees}
capacity={props.capacity}
description={props.description}
attendeeList={props.attendeeList}
attendeeHelperFunction={props.attendeeHelperFunction}
/>
</div>
);
};
They are scrollbars, duh! But if anyone ever stumbles onto this thread, here is a style generator for scroll bars https://mikethedj4.github.io/Webkit-Scrollbar-Generator/
I have a page that creates a pop-up notification whenever a message is broadcasted from another user. The pop-up is basically a div that holds content from the sent message with a button that allows you to close it.
Now I've researched a million ways to create transitions that extend properties using pseudo classes but my question is this: Is it possible to create a banner at the top of the page that slides down with the message when it's sent by another using pure CSS3 / transition mixins?
My thought was to transition the max-height property but obviously it isn't working. I'm assuming because there is no height to begin with.
CSS:
.banner-messages {
> div {
background-color: #74bce7;
color: #fff;
top: 0;
left: 0;
padding: 20px 30px;
position: relative;
line-height: 100%;
width: 100%;
max-height: 0;
z-index: 1000;
overflow-y: hidden;
#include drop-down;
}
}
#mixin drop-down {
max-height: 200px;
-webkit-transition: all 1.5s linear;
-moz-transition: all 1.5s linear;
-o-transition: all 1.5s linear;
transition: all 1.5s linear;
}
HTML:
<div id="test" class="banner-messages" data-bind="foreach: messages">
<div class="banner-message">
<img data-bind="imgSrc: 'radio.svg'">
<div class="banner-body">
<p class="banner-title">{{title}}</p>
<pre>{{message}}</pre>
</div>
<span class="exit-dialout-panel icon icon-closes" data-bind="visible: dismissable, click: $parent.dismissMessage.bind($parent, $data)"></span>
</div>
Try adding a class with the css binding that applies transform: translateY:
var Viewmodel = function Viewmodel() {
var that = this;
this.messages = ko.observableArray([]);
this.removeMessages = function removeMessages() {
that.messages.removeAll();
};
this.addMessage = function addMessage() {
that.messages.push("A new message came in");
};
};
ko.applyBindings( new Viewmodel() );
header {
transition: transform 0.3s;
transform: translateY(-110%);
background-color: lightblue;
padding: 2rem;
font-family: sans-serif;
}
header.active {
transform: translateY(0);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<main>
<header data-bind="css: { active: messages().length > 0 }">
<ul data-bind="foreach: messages">
<li data-bind="text: $data"></li>
</ul>
<button data-bind="click: removeMessages">mark all as read</button>
</header>
</main>
<button data-bind="click: addMessage">Add message</button>
Similar to this question, I have a nested div that is the full width and height of its parent. However, unlike the other question, I want to animate a translation of the nested div, so the suggested fix of position:static is not applicable.
The following is my test case:
HTML:
<div id="theBox">
<div id="innerBox"></div>
</div>
CSS:
#theBox {
border: 1px solid black;
border-radius: 15px;
width: 100px;
height: 30px;
overflow: hidden;
}
#innerBox {
width: 100%;
height: 100%;
background-color: gray;
-webkit-transition: -webkit-transform 300ms ease-in-out;
-moz-transition: -moz-transform 300ms ease-in-out;
}
JavaScript:
setTimeout(function () {
var innerBox = document.getElementById("innerBox");
var transformText = "translate3d(70px, 0, 0)";
innerBox.style.webkitTransform = transformText;
innerBox.style.MozTransform = transformText;
}, 1000);
http://jsfiddle.net/pv2dc/
This works fine in Firefox 15.0.1, but in Safari 6.0.1, the inner div is not clipped by the parent div's curved border.
Is there a work-around for this issue?
Interestingly, if instead of translate3d() you use the 2D translate() transform function, then the inner div is clipped after completion of the transition: http://jsfiddle.net/pv2dc/1/
One work-around, then, is to not use transitions, but animate the transform yourself:
CSS:
#theBox {
border: 1px solid black;
border-radius: 15px;
width: 100px;
height: 30px;
overflow: hidden;
}
#innerBox {
width: 100%;
height: 100%;
background-color: gray;
}
JavaScript:
(function() {
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
})();
setTimeout(function () {
var start = window.mozAnimationStartTime || Date.now();
function step(timestamp) {
var progress = timestamp - start;
var transformText = "translate(" + (70 * progress / 300) + "px)";
if (progress >= 300) transformText = "translate(70px)";
innerBox.style.webkitTransform = transformText;
innerBox.style.MozTransform = transformText;
if (progress < 300) {
window.requestAnimationFrame(step);
}
}
window.requestAnimationFrame(step);
}, 1000);
http://jsfiddle.net/pv2dc/2/
This sample uses a linear timing function, but the ease-in-out function can also be used. See: http://www.netzgesta.de/dev/cubic-bezier-timing-function.html