Code Monkey home page Code Monkey logo

skrollr's Introduction

Build Status

Please note:

skrollr hasn't been under active development since about September 2014 (check out the contributions graphs on https://github.com/Prinzhorn/skrollr/graphs/contributors) and I don't have any plans for doing major changes to it. Please consider this before using skrollr in production as problems with new browser versions, especially on mobile, will most definitely surface. To be honest, mobile support always sucked (because mobile browsers are hard) and you shouldn't compromise UX for some fancy UI effects. Ever.

skrollr 0.6.30

Stand-alone parallax scrolling JavaScript library for mobile (Android, iOS, etc.) and desktop in about 12k minified.

Designer friendly. No JavaScript skills needed. Just plain CSS and HTML.

Actually, skrollr is much more than "just" parallax scrolling. It's a full-fledged scrolling animation library. In fact, you can use it and still have no parallax scrolling at all. But I wanted to sound hip and use some buzz-words. By the way, skrollr leverages HTML5 and CSS3 ;-)

Resources

Plugins

Official

Third party

In the wild

Check out the wiki page for websites using skrollr and feel free to add your own website :). You can also shamelessly add yourself to the list here if you are offering paid skrollr support.

Further resources (tutorials etc.)

Moved to the wiki.

Documentation

First of all: look at the examples and read the source ;-). This might give you a feeling of how stuff works and you can see how some patterns can be implemented.

Abstract

skrollr allows you to animate any CSS property of any element depending on the horizontal scrollbar position. All you need to do is define key frames for each element at certain points in top scroll offset.

Other libraries require you to write JavaScript in order to define your animations. This introduces two main problems:

  • Animation and element are not at one place. In order to find out if any animations are defined for a given element, you have to scroll through many (sometimes thousands) of lines of JavaScript.
  • You have to learn a new syntax which is often very verbose and limited at the same time.

With skrollr, you put the definition of your key frames right where they belong (to the element) using a syntax you already know (plain CSS).

If you would rather have the keyframes inside a separate file, take a look at skrollr-stylesheets.

If you prefer to use JavaScript to define your animations make sure to take a look at ScrollMagic. It depends on both jQuery and the Greensock Animation Platform (GSAP) and gives you full control over every detail of your animations.

Let's get serious

First of all you want to include the skrollr.min.js file at the bottom of your document (right before the closing </body>) and then call skrollr.init(). Or you can place it inside the <head> if you want to, but make sure to call init() once the document has been loaded (e.g. jQuery's ready event or even window.onload).

	<script type="text/javascript" src="skrollr.min.js"></script>
	<script type="text/javascript">
	var s = skrollr.init();
	</script>
</body>

If you are using require.js to structure your project, you can use skrollr as a module as well.

require(['skrollr'], function(skrollr){
	var s = skrollr.init();
});

If you're familiar with CSS, you already know the style attribute. In order to create an animation you would need several, at least two, of them. That's what skrollr does. You use the HTML5 data- attributes to define multiple sets of styles (we call each of them keyframe) and skrollr interpolates between them.

Let's change the background-color of a div starting at #00f when the scrollbar is at the top and ending with #f00 when the user scrolled 500 pixels down

<div data-0="background-color:rgb(0,0,255);" data-500="background-color:rgb(255,0,0);">WOOOT</div>

View in browser

Lessons learned
  • Skrollr ensures that you can actually scroll down 500 pixels or more, even if there's not enough content. You can suppress this by using the forceHeight option.
  • You can't use #00f or #0000ff. You need to use rgb or hsl and explicitly decide which color space you want because they result in different animations (HSL is much cooler most of the time). Don't worry, the IE plugin teaches IE < 9 to display rgb and hsl correctly.

Now let's do a barrel roll at the same time

<div data-0="background-color:rgb(0,0,255);transform:rotate(0deg);" data-500="background-color:rgb(255,0,0);transform:rotate(360deg);">WOOOT</div>

View in browser

Lessons learned
  • Skrollr handles all these nasty CSS prefixes for you. Just -moz-relax and get yourself a cup of -webkit-coffee.

Now let the rotation bounce like it were a hip-hop video

<div data-0="background-color:rgb(0,0,255);transform[bounce]:rotate(0deg);" data-500="background-color:rgb(255,0,0);transform[bounce]:rotate(360deg);">WOOOT</div>

View in browser

Lessons learned

  • Skrollr allows non-linear animations. The so called easing functions can be used per-property by putting them in square brackets behind the property. There's a built-in list of easing functions (see below in the JavaScript section) and you can use your own functions by using the easings options.

Now you may have noticed that using 500 as a keyframe position is kind of random and the look depends on your browser size.

Let's have the animation end when the top of the element reaches the top of the viewport (element leaves the viewport)

<div data-0="background-color:rgb(0,0,255);transform[bounce]:rotate(0deg);" data-top="background-color:rgb(255,0,0);transform[bounce]:rotate(360deg);">WOOOT</div>

View in browser

Lessons learned

That's the end of this short intro. The following sections will explain some more things in detail.

If you're not a fan of data-attributes or if you're planning a big website where you want a better and more flexible structure, take a look at skrollr-stylesheets.

Mobile support

Starting with version 0.5.0 skrollr officially supports mobile browsers including Android and iOS. Furthermore, mobile support has been rewritten from scratch for skrollr 0.6.0.

The Problem with mobile and the solution

(If you're not interested in the details, just scroll down a bit to see what you need to do for mobile support.)

Some words on why this is an important milestone and why others failed: Mobile browsers try to save battery wherever they can. That's why mobile browsers delay the execution of JavaScript while you are scrolling. iOS in particular does this very aggressively and completely stops JavaScript. In short, that's the reason why many scrolling libraries either don't work on mobile devices or they come with their own scrollbar which is a usability nightmare on desktop. It was an important requirement while I developed skrollr that I don't force you to scroll the way I want it. skrollr on desktop uses a native scrollbar and you can scroll the way you want to (keyboard, mouse, etc.).

You just told me it doesn't work on mobile, but why does it? The answer is simple. When using skrollr on mobile you don't actually scroll. When detecting a mobile browser, skrollr disables native scrolling and instead listens for touch events and moves the content (more specific the #skrollr-body element) using CSS transforms.

What you need in order to support mobile browsers

Starting with skrollr 0.6.0 there's just one thing you need to do: Include an element on your page with the id skrollr-body. That's the element we move in order to fake scrolling. The only case where you don't need a #skrollr-body is when using position:fixed exclusively. In fact, the skrollr website doesn't include a #skrollr-body element. If you need both fixed and non-fixed (i.e. static) elements, put the static ones inside the #skrollr-body element.

Or to put it differently: On mobile the skrollr-body element is moved using CSS transforms. You can't have position:fixed or background-attachment:fixed inside elements which use CSS transforms as per CSS spec (http://meyerweb.com/eric/thoughts/2011/09/12/un-fixing-fixed-elements-with-css-transforms/). That's why those elements need to be outside of the skrollr-body element.

The skrollr-body element might be configured within the init-options.

AMD

Starting with 0.6.22 there's experimental AMD support. Please note that only skrollr core has AMD support so far. We will update the plugins in the future.

require(['skrollr'], function(skrollr){
	skrollr.init();
});

Absolute vs relative mode

Being only able to define key frames in absolute values is simply insufficient for some cases. For example, if you don't know exactly where an element will be in the document. That's why there are two modes for key frames, namely absolute and relative mode.

absolute mode (or document mode)

The key frames are defined as absolute values describing how much the document has been scrolled down.

The syntax is data-[offset]-[anchor], where offset can be any integer (0 is default) and anchor can be either start (default) or end. Either offset or anchor can be omitted in some situations. Here are some examples of key frames and their meaning.

  • data-0 = data-start = data-0-start: When the scroll top is 0.
  • data-100 = data-100-start: When the scroll top is 100.
  • data--100 = data--100-start: When the scroll top is -100 (sounds like nonsense, but keep in mind that interpolation will be relative to this point).
  • data-end = data-0-end: When offset is 0, but counting from the bottom of the document instead of from the top. In short: when you reach the bottom of the page.
  • data-100-end: 100px before we reach the bottom.
  • data--100-end: 100px after we reach the bottom (again, it's up to you whether you need it).

relative mode (or viewport mode)

Instead of defining key frames relative to the document (i.e. absolute), we are able to define them depending on the position of any element in relation to the viewport.

The syntax is data-[offset]-(viewport-anchor)-[element-anchor], where offset can again be any integer and defaults to 0. Both viewport-anchor (mandatory) and element-anchor (optional) can be one of top, center or bottom. If element-anchor is omitted, the value of viewport-anchor will be taken (just like with background-position). Here are some examples of key frames and their meaning.

  • data-top = data-0-top = data-top-top = data-0-top-top: When the element's top is aligned with the top of the viewport.
  • data-100-top = data-100-top-top: When the element's top is 100px above the top of the viewport.
  • data--100-top = data--100-top-top: When the element's top is 100px below the top of the viewport.
  • data-top-bottom = data-0-top-bottom: When the bottom of the element is at the top of the viewport (it's just not visible).
  • data-center-center = data-0-center-center: When the element is at the center of the viewport.
  • data-bottom-center = data-0-bottom-center: When the element's center is at the bottom of the viewport, thus the upper half of the element is visible.

By default the keyframes are triggered by the position of the element where the keyframes are described. However there are times when the position of a second element should trigger the first element's keyframes. The data-anchor-target attribute can be used in these cases. The data-anchor-target attribute accepts any CSS selector and the position of the first element on the page matching the selector will be used to trigger keyframes on the element where the attribute is defined. data-anchor-target requires IE 8 or greater.

Examples: <div data-anchor-target="#foo"> will have it's keyframes tiggered by the position of the #foo element. Any CSS selector can be used, i.e data-anchor-target=".bar:not(.bacon) ~ span > a[href]"

Note: If you need to support IE 7, then you may only use IDs as anchor-targets, i.e. #foo. The IE plugin maps querySelector to getElementById.

Here's an infographic for better understanding of anchors (click to open PDF):

Anchors Guide

Important: All those values will be calculated up-front and transformed to absolute mode. So if either the element's box height changes (height, padding, border) or the elements position within the document, you probably need to call refresh() (see documentation in JavaScript section below). Window resizing is handled by skrollr.

Percentage offsets

All offsets shown above are given in absolute pixel values, e.g. data-300 for 300px from the top or data-13-top-bottom for a 13px offset to the top-bottom anchor. As of skrollr 0.6.13 you can also have offsets as percentages of the viewport by appending a p to the number. For example data-75p for when you scrolled down 75% of the viewport or data-10p-center to have a 10% offset from the center anchor.

Hash navigation

Check out the skrollr-menu plugin.

Working with constants

I was lying to you. The syntax for absolute mode is not data-[offset]-[anchor] and for relative mode it's not data-[offset]-(viewport-anchor)-[element-anchor]. In both cases, offset can be preceded by a constant which can be passed to the init method. The name of the constant needs to be preceded with an underscore.

Example:

skrollr.init({
	constants: {
		foobar: 1337
	}
});
<div data-_foobar="left:0%;" data-_foobar--100="left:50%;" data-_foobar-100="left:100%;"></div>

<!--Equal to-->

<div data-1337="left:0%;" data-1237="left:50%;" data-1437="left:100%;"></div>

Valid characters for a constant are [a-z0-9_].

Dynamic constants

Starting with skrollr 0.6.19 the word "constants" doesn't quite fit anymore, but who cares.

You can now use functions and percentages as constants. They are automatically evaluated when the window is resized or if you call refresh.

skrollr.init({
	constants: {
		foo: function() {
			//Note: you can access the skrollr instance with `this` for things like `this.relativeToAbsolute`
			return Math.random() * 100;//trolololol
		},
		vh: '100p'
	}
});

CSS classes

skrollr will add a skrollr class to the HTML element when calling init and will remove a no-skrollr class if present. Additionally, it will add a skrollr-desktop or skrollr-mobile class depending on which it detects. This allows fallback CSS rules to create a good user experience on unsupported devices or when JavaScript or skrollr are disabled.

All elements under skrollr's control (elements with appropriate data-attributes) will get the skrollable class. In addition, we add either the skrollable-before, skrollable-between or skrollable-after class, depending on whether the current scroll position is before, between or after the first/last (smallest/largest) keyframe of an element.

Animating attributes

Starting with skrollr 0.6.24 you can also animate attribute and not just style properties. This is especially a big thing because in the SVG world many properties are implemented as attributes and not in CSS. Animating an attribute couldn't be simplier, just prefix the property with an @ symbol!

<polygon
	points='426,720   -200,720   -200,0   955,0'
	data-0="@points:426,720   -200,720   -200,0   955,0"
	data-500="@points:380,720   -200,720   -200,0   1302,0">
</polygon>

Note: as always, skrollr doesn't do any magic. It doesn't understand what a polygon or points are. It's only interpolating numbers, that's it. So make sure you have the same number of numbers in your keyframes (8 in this case).

Filling missing values

Imagine the following animation

<div data-100="left:0%;" data-200="top:0%;" data-300="left:50%;" data-400="top:50%;"></div>

One could expect left to have a value of 25% at keyframe 200. That is not the case. By design, skrollr only interpolates values between key frames which are direct neighbors. What actually happens is that skrollr internally fills out all holes once from left and then from right. So the above is equivalent to

<div data-100="left:0%;top:0%;" data-200="left:0%;top:0%;" data-300="left:50%;top:0%;" data-400="left:50%;top:50%;"></div>

Preventing interpolation

The reason why skrollr is so lightweight and powerful is because it literally interpolates every number it can find. If you want to prevent some side effect, you can suppress interpolation for a specific value by prepending an exclamation point.

Example:

<!-- This will get your image url f***** up because there's no "kitten1.4561799.jpg" and the like -->
<div data-0="background-image:url(kitten1.jpg);" data-100="background-image:url(kitten2.jpg)"></div>

<!-- Better -->
<div data-0="background-image:!url(kitten1.jpg);" data-100="background-image:!url(kitten2.jpg)"></div>

Note: The values for both keyframes (if they contain a number) need to be prefixed if you want to avoid skrollr throwing an exception at you!

Limitations

There are some limitations of skrollr you should be aware of.

  • All numeric values have to have the same unit, even 0 needs a unit. It's not possible to animate from 5% to 100px. skrollr won't complain, but results are undefined.
  • Animations between values which are composed of multiple numeric values like margin:0 0 0 0; are only possible for the same number of values. margin:0px 0px 0px 0px; to margin:0px 100px 50px 3px; is fine, but not margin:10px; to margin:5px 10px;.
  • Animations between CSS transforms only work when they use the same functions in same order. From rotate(0deg) scale(1) to rotate(1000deg) scale(5) is fine.
  • Color animations don't support named values like "red" or hex values like "#ff0000". Instead, you have to use rgb(), rgba(), hsl() and hsla(). Don't worry, there's a skrollr plugin for IE < 9 to support hsl() (without "a"!) and to fall rgba back to rgb.
  • Color animations only work for same color functions. hsl() to hsl() or hsla() is fine, but not rgb() to hsl(). Which makes sense, because animating from the same colors in rgb space and in hsl space results in different animations (hsl gives you the nice rainbow stuff).

But feel free to send in a pull request to fix any of them. Just keep in mind that keeping skrollr as lightweight as possible has high priority.

JavaScript

On the JavaScript part there's not much to do (you can, if you want to!). So if you only know CSS and HTML, perfect.

skrollr.init([options])

All there is to do is to call skrollr.init([options]); which returns an instance of the singleton skrollr class. Subsequent calls to init() will just return the same skrollr instance again.

Possible options for init() are

smoothScrolling=true

Smooth scrolling smoothens your animations. When you scroll down 50 pixels, the animations will transition instead of jumping to the new position.

The global setting can be overridden per element by setting data-smooth-scrolling to on or off.

smoothScrollingDuration=200

The number of milliseconds the animations run after the scroll position changed the last time.

constants={}

An object containing integers as values. The keys can contain [a-z0-9_]. They do not need a leading underscore.

Example: data-_myconst-200 and skrollr.init({constants: {myconst: 300}}) result in data-500.

scale=1

By default, skrollr uses the largest key frame and makes document height + viewport height this high, thus the max possible scroll top offset. If your animation runs too fast or too slow, just adjust the scale value.

scale only affects keyframes in absolute mode.

When forceHeight is set to false, scale is ignored.

scale affects constants as well.

scale does only affect key frames in absolute mode, e.g. data-500 but not data-top.

###forceHeight=true

true: Make sure the document is high enough that all key frames fit inside. Example: You use data-1000, but the content only makes the document 500px high. skrollr will ensure that you can scroll down the whole 1000px. Or if you use relative mode, e.g. data-top-bottom, skrollr will make sure the bottom of the element can actually reach the top of the viewport.

false: Don't manipulate the document and just keep the natural scrollbar.

###mobileCheck=function() {...}

This option allows you to pass a function to skrollr overwriting the check for mobile devices. The function should return true when mobile scrolling should be used and false if not.

The default looks like this

function() {
	return (/Android|iPhone|iPad|iPod|BlackBerry/i).test(navigator.userAgent || navigator.vendor || window.opera);
}

mobileDeceleration=0.004

The amount of deceleration for momentum scrolling on mobile devices. This options tells skrollr how fast or slow you want the scrolling to stop after the user lifted his finger.

Set it to 1 to disable momentum scrolling.

skrollrBody='skrollr-body'

This option allows you to override the default id-selector used for supporting mobile browsers. It might come in handy when the element in question already has a assigned id or if you would like to define more then one skrollrBody depending on preceding JavaScript-logic.

edgeStrategy='set'

This option specifies how to handle animations when the scroll position is outside the range on the keyframes (i.e. before the first or after the last keyframe).

One of three options are possible

  • set (default): When before/after the first/last keyframe, apply the styles of the first/last keyframe to the element.
  • ease: Same as set, but the values will be transformed using the given easing function.
  • reset: When before/after the first/last keyframe, apply the styles which the element had before skrollr did anything. This means resetting the class attribute as well as removing all styles which have been applied to the style property. This means the element won't have any skrollable-* CSS classes.

Example:

Given the following element with two keyframes

<div data-1000="left:0%;top:0%;" data-2000="left:50%;top:100%;" style="left:-100%;" class="section"></div>

and the following easing function which always returns 0.5 (I know it's pointless, but it's just an example. A real world example would be an easing function that represents a curve and starts somewhere between 0 and 1, but not at 1)

function(p) {
	return 0.5;
}

and imagine the scrollbar is at 237, which is below the first keyframe which is at 1000.

  • set will result in <div style="left:0%;top:0%;" class="section skrollable skrollable-before"></div> which is plain data-1000.
  • ease will result in <div style="left:25%;top:50%;" class="section skrollable skrollable-before"></div> which is 0.5 * data-1000.
  • reset will result in <div style="left:-100%;" class="section"></div> which is what the element originally had. Note how top is missing.

beforerender

A listener function that gets called each time right before we render everything. The function will be passed an object with the following properties:

{
	curTop: 10, //the current scroll top offset
	lastTop: 0, //the top value of last time
	maxTop: 100, //the max value you can scroll to. curTop/maxTop will give you the current progress.
	direction: 'down' //either up or down
}

Returning false will prevent rendering.

render

A listener function that gets called right after we finished rendering everything. The function will be passed with the same parameters as beforerender.

Example

skrollr.init({
	render: function(data) {
		//Log the current scroll position.
		console.log(data.curTop);
	}
});

keyframe

Experimental

In order to receive keyframe events from an element, add the data-emit-events attribute to the element. The keyframe function will be called with three arguments

  1. The element that passed the keyframe.
  2. The name of the keyframe, camel-cased (see example).
  3. The direction the user is scrolling.

Example:

<div
	data-500="..."
	data-top-bottom="..."
	data-_offset-center="..."
	data-emit-events
>
	Some content
</div>
skrollr.init({
	keyframe: function(element, name, direction) {
		//name will be one of data500, dataTopBottom, data_offsetCenter
	}
});

Note: this is experimental, expect the API to change! Originally I wanted to emit the events right on the element, so you could do this

//Wouldn't this be nice?
document.querySelector('#foo').addEventListener('skrollr.dataTopBottom.up', function() {
	//#foo just passed the data-top-bottom keyframe while scrolling up
}, false)

but IE.

easing

An object defining new easing functions or overwriting existing ones. Easing functions get just one argument, which is a value between 0 and 1 (the percentage of how much of the animation is done). The function should return a value between 0 and 1 as well, but for some easings a value less than 0 or greater than 1 is just fine.

An easing function basically transforms the timeline for an animation. When the animation should be 50% done, you can transform it to be 90% done or whatever your function does.

Example:

skrollr.init({
	easing: {
		//This easing will sure drive you crazy
		wtf: Math.random,
		inverted: function(p) {
			return 1 - p;
		}
	}
});

You can now use the easing functions like any other.

skrollr ships with some built in functions:

  • linear: The default. Doesn't need to be specified.
  • quadratic: To the power of two. So 50% looks like 25%.
  • cubic: To the power of three. So 50% looks like 12.5%
  • begin/end: They always return 0 or 1 respectively. No animation.
  • swing: Slow at the beginning and accelerates at the end. So 25% -> 14.6%, 50% -> 50%, 75% -> 85.3%
  • sqrt: Square root. Starts fast, slows down at the end.
  • outCubic
  • bounce: Bounces like a ball. See https://www.desmos.com/calculator/tbr20s8vd2 for a graphical representation.

Custom easing

  • Use this generator
  • Insert the given polynomial coeficients instead of t, t2, t3, t4 and t5
t5*(p*p*p*p*p) + t4*(p*p*p*p) + t3*(p*p*p) + t2*(p*p) + t*p

Example shown with the values for easeOutElasticBig

easeOutElasticBig: function(p) {
  return 56*(p*p*p*p*p) - 175*(p*p*p*p) + 200*(p*p*p) - 100*(p*p) + 20*p;
}

skrollr.get()

Returns the skrollr instance if init() has been called before or undefined.

Public API

Calling init() returns an instance of skrollr which exposes a public api.

refresh([elements])

Reparses all given elements. You can pass a single element or an array-like element (Array, NodeList or jQuery object)

Useful when

  • Elements in relative mode change and need to be updated.
  • Data-attributes are manipulated dynamically.
  • New elements are added to the DOM and should be controlled by skrollr.

When no elements are given, all elements in the document will be parsed again. In fact, when calling skrollr.init() skrollr uses refresh() without parameters internally.

Time consuming operations, should not be called on every rendering.

relativeToAbsolute(element, viewportAnchor, elementAnchor)

Returns an integer which represents the absolute scroll position which correlates to the relative anchor.

element must be a DOM element.

viewportAnchor and elementAnchor must be one of top, center or bottom

Example:

var offset = s.relativeToAbsolute(document.getElementById('foo'), 'top', 'bottom');

//offset contains the scroll position at which #foo's bottom is at the top of the viewport.
//If you now use setScrollTop(offset) or animateTo(offset) #foo's bottom will be perfectly aligned with the top of the viewport. Yay.

getScrollTop()

Returns the current scroll offset in pixels. Normalizes different browser quirks and handles mobile scrolling.

getMaxScrollTop()

Returns the number of pixels that can be scrolled down in total. If forceHeight is true, that's usually the largest keyframe. Otherwise it's the height of the document minus the viewport height.

setScrollTop(top[, force = false])

Sets the top offset using window.scrollTo(0, top) on desktop or updating the internal state in case of mobile scrolling.

When force is set to true, skrollr will jump to the new position without any kind of transition. By default, the global smoothScrolling setting applies.

isMobile()

Returns if skrollr runs in mobile mode (see also mobileCheck option).

animateTo(top[, options])

Animates the scroll position from current position to top. Possible options are

duration

How long the animation should run in milliseconds. The default is 1000 or one second.

easing

The name of an easing function. The same functions can be used as for property animations. Default is linear .

done

A function to be called after the animation finished. When you pass a top value, which is the same as the current, then the function will be called immediately. The function gets a boolean argument interrupted which indicates if the animation was interrupted by stopAnimateTo or finished to the end.

stopAnimateTo()

Stops the animation and calls the done callback passing true as interrupted arguments.

isAnimatingTo()

Returns if an animation caused by animateTo is running.

on(name, fn)

Set a listener function for one of the events described in the options section (beforerender, render, keyframe). Only one listener can be attached at a given time. This method overwrites the current listener, if any.

off(name)

Removes the listener for the given event.

destroy()

Destroys skrollr. All class and style attributes will be set to the values they had before.

Changelog

See HISTORY.md.

skrollr's People

Contributors

alexjeng avatar asavin avatar bentedder avatar capnslipp avatar chuckjhardy avatar crispen-smith avatar dhharker avatar ethanresnick avatar heston avatar karbassi avatar konstantinkobs avatar nhall avatar oilart avatar prinzhorn avatar rcartwright avatar reed avatar silvenon avatar slidych avatar stianlik avatar suven avatar thinktherefore avatar tridnguyen avatar trysound avatar yvesvanbroekhoven avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

skrollr's Issues

Add something like "data-end-[offset]" to count from end

The "data-end" attribute is already available as a convenience method to make it easier to have multiple animations end at the end (ha!).

For large skrollr instances it would be helpful to say "hey, I want this animation to start 100 px before the end".

Example:

<!-- Some other elements -->
<div data-end-100="opacity:1;" data-end="opacity:0;">Hey ma, I will fade away for the last 100px of scrolling!</div>

If the offset is larger than the maximum, it should be threated as "data-0".

add /examples

In addition to the "main" example (the gh-page), add some more examples of common tasks.

  • simple effects without skrollr.css and absolute/fixed positioning. just a "normal" website with some spice (parallax background maybe?).
  • circular motion using custom easing (using sin/cos for left/top properties)

KISS parser system

Right now, skrollr automatically detects what you want to animate and how to parse. The flow is like this:

  • Is it a transform value (scale, etc.)? -> parse transform value
  • Is it a color? -> parse color
  • Is it a numeric value/multiple numeric values with unit? -> parse them
  • It must be a constant value like "block" or "center"

We could probably throw this away completely, because at the end, they are all based on numeric values.

Instead do this:

  • Extract all numeric values from the string and remember where they were.

That's it. No matter if the string is rotate(0deg) scale(1.2) or rgb(100,20,40) or just 10px or even block, we will just parse all of them in a simple structure using a regex. For example

rotate(0deg) scale(1.2) will result in something like ["rotate(?deg) scale(?)", 0, 1.2]

or

rgb(100, 20,40) will result in something like ["rgb(?, ?,?)", 100, 20, 40]

Without looking at the code, this will probably save 20% or even more of the current code.

It get's even better: With this change, we will get support for all kinds of properties which would be hard to handle, for example gradients or shorthand values like "background", where position, image and color are mixed.

The only thing we need to keep in mind is, that there are some CSS properties that don't support floats and need <integer> CSS value. All properties in this table with either <integer> or <color> need special handling.

rename "hidden" class to "unrendered"

When a skrollable is currently not render, that means the current scroll position is not within it's key frames, we add a CSS class called "hidden". That's incorrect and adds semantic. Call it "unrendered" instead and add "rendered" as counterpart.

let anchors point to different elements instead of just self

The anchor feature will allow defining key frames related to the element's current position.

The idea is to be able to use child or parent element's as well. I'm not sure how this could look like, but that shit cray.

There could be some logic like with CSS, where certain things are able to cascade up (heh) and down.

<div>
    foo
    <div data-cascade="../div" data-bottom="background:rgb(0,0,0);" data-top="background:rgb(0,0,0);">bacon</div>
   bar
</div>

The inner DIV would change color while the outer DIV is fully inside the viewport.

I'm completely open to syntax suggestions. This could be some sort of CSS selectors. Instead of just parents/children it could be any element (not sure if useful).

Add support for zynga/scroller

This is related to #8 and #9

By using https://github.com/zynga/scroller we could solve the iOS problem. skrollr's init method could get a new parameter scroller which expects an instance of zynga/scroller. We then use getValues().top instead of the native scroll offset if a scroller instance is available.

To keep skrollr painless for non-JavaScript programmers it may be worth to abstract this. Maybe put zynga/scroller into the skrollr repo and just call it "touch.min.js" or something (with proper attributions inside the file of course). This touch.min.js file would include all zynga stuff that is needed plus a small shim that creates an instance of scroller and exposes it globally so skrollr can use it (like window.skrollrScrollerInstance).

The changes to skrollr core would be a one liner like window.skrollrScrollerInstance && window.skrollrScrollerInstance.getValues().top inside getScrollTop

Edit: Almost forgot: setScrollTop needs to be changed accordingly. Cake.

SVG

Seems like the only thing which keeps skrollr from working with SVG elements is that we use className where SVG needs to be className.baseVal

prefixed values

Not only properties use prefixes, but values as well e.g. -moz-linear-gradient

Add prefixes if needed. Prefixed values are currently not working.

Add templating to separate key frames from document

Just an idea:

Similar to how skrollr uses the inline-style syntax, we could create a templating language which looks similar to a CSS stylesheet.

#foo {
    bottom-top {
        left:100%;
    }

    top-bottom {
        left:0%;
    }

    100 {
        color:rgb(0,0,0);
    }
}

//Or maybe

#foo@bottom-top {
    left:100%;
}

#foo@top-bottom {
    left:0%;
}

#foo@100 {
    color:rgb(0,0,0);
}
<div id="foo">woooooot</div>

will be transformed on the fly to

<div id="foo" data-bottom-top="left:100%;" data-top-bottom="left:0%;" data-100="color:rgb(0,0,0);">woooooot</div>

This way we could have separate templates for different resolutions/devices. This is against the idea of having the key frames close to the element, but it's still better than mixing it with JS like $('#foo').skrollr({"100": "color:rgb(0,0,0);"}). I'ts something we are used to.

This would of course be a separate project/file, kind of like a less or sass preprocessor.

Separate demo/examples from core

The gh-pages branch should contain only the HTML/CSS files needed for the demos/examples, whereas the master branch should only contain files needed for skrollr development.

Plugin system

I'm thinking about dropping hsl support from skrollr core, because it's only needed for IE < 9 (and some very old Firefox etc.). I'd drop the IE "filter" stuff at the same time.

Instead of having those in core, it would available be as a plugin which transforms hsl to hex on the fly. This change could make skrollr core close to 5k small.

How plugins could work or how the api could look like: Allow plugins to hook into the setStyle method. This would allow transforming hsl as well as adding the IE filter style. Other entry points for plugins could later be specified.

Well, actually I'm not thinking about this, I will just do it.

Tablet performance

Seems like the performance on (Android) tablets is poor. Could someone with a tablet do some CPU profiling? I don't have one and I have no idea how JS can be debugged on those.

Percentage visible / dynamic elements?

Hi there, sorry for the issue bomb, but figured I would ask while it was on my mind.

Say I have several 'full screen panels' that each are to fill the entire screen, based on the window size; therefore the position of each of the panels can vary based on different monitor / window sizes.

How would you suggest I perform animations on objects within these panels as you enter / leave them? Maybe easier to just scrap the full screen height of each of the panels and set them to hardcoded values, yes?

You can see what I'm referring to on my personal site I hacked together this week. The first panel (my photo) is set to fill the window area (try resizing the window to see what I mean).

http://www.andrewmart.in

Just thought I'd reach out and see if you had any suggestions for a solution.

Remove private members from skrollr prototype

In order to save bytes and clean up the code base, we should remove all members, which should not be accessible form outside, from the prototype. Instead they should just be scope variables inside the main wrapper function.

Example:

//Before
Skrollr.prototype._fillProps = function(sk) {/*...*/}

//After
var _fillProps = function(sk) {/*...*/}

//Same for non-methods

//Before
self.curTop = 1337;

//After
_curTop = 1337; //Declared elsewhere.

Since only one instance of skrollr will be instantiated anyway. (Note: make skrollr a proper singleton)

Remove "scroll" event

Since scrolling and rendering are now decoupled, why still have a onscroll listener in first place? It's just a wast of cycles to listen for each scroll event when we only use the data of some of them. The _render method can easily call getScrollTop() as well.

This will not necessarily cause a push to 0.3.0, because 0.. is highly unstable anyway.

This change may as well fix #9, because iOS (and others) don't fire a scroll event while scrolling with a touch gesture. Not sure if getScrollTop() will report the correct value then.

CSS transitions performance

I'm thinking about removing CSS transitions for the demo page, because it's really hurting performance. It would be as easy as using the "notransition" class on body element. skrollr itself doesn't know about transitions anyway, it just sets properties.

While adding more documentation I would of course mention that (documentation about the default skrollr.css file is missing right now). I have to make clear what skrollr does and that the skrollr.css file is just to get started and may be fully customized.

Page flickering on AJAX load

I'll preface this by saying it may not even be related directly to Skrollr, but I'm wondering what might be causing this. I'm using Isotope and appending in some content using Waypoints once an area has been reached.

Once this is appended, it works great, but when I scroll the page flickers randomnly––throughout all of the panels, regardless of whether the Isotope area is in view or not. It works smoothly without flickering until this stuff is appended.

I would show the project but would rather DM a link if you like.

I am only writing because I'm wondering if it may be related to the Refresh issue since I'm using AJAX to append the content.

Add refresh() method

When the content of a page or element changes dynamically, for example due to an AJAX request, it's needed to refresh the internal skrollr calculations.

There should be a new method named refresh([elements]) with an optional argument. The method will either parse anything again or just the given object(s).

Example:

<div data-0="left:0px;" data-end="left:500px;">bacon</div>
var s = skrollr.init({forceHeight: false});

//The body is now larger, thus data-end needs to be recalculated
document.body.innerHTML += 'foo<br>foo<br>foo<br>foo';

s.refresh();

//or
s.refresh(document.querySelectorAll('[data-end]'));

refractor documentation

The README should be much shorter and easier. All those technical details should be separated.

Maybe we should set up the GitHub wiki and have this stuff nicely organized.

Add "skrollr" class to HTML

A skrollr class should be added to the top most element (html). At the same time, any no-skrollr class should be removed. This way it's easier to create pages that work with and without skrollr at the same time (useful for mobile amongst others).

IE 7/8 exception

When starting the example a popup opens:

Line 752: '0' is null or not an object.

Have to investigate further.

Class removing broken

Just found that skrollr seems to remove one whitespace too much when stripping a className. Investigating.

Add method to allow animating scroll position

We already have a render loop and different easing functions, why not allow animating the scroll position?

Example will animate from current position to 1000 offset:

skrollrInstance.animateTo(1000);

Optional arguments could include: duration, callback and name of easing function.

skrollrInstance.animateTo(1000, {
    duration: 500, //ms    
    done: function() {},
    easing: 'cubic' //same set as for other animations
});

Add option to stop animateTo when user interacts

I hate websites that do a scroll animation much longer than 2 seconds and don't allow interruption.

After I pulled #55 it will easily be possible to add an option for that.

//User interaction won't impress this selfish animation
s.animateTo(2000, {interruptible: false});

//When the user scrolls, the animation gracefully stops
s.animateTo(2000, {interruptible: true});

Allow refering to the original style of the element

We should implement a keyword like inherit which will be replaced by the computed style of this element during parse time.

Example

div {font-size:100px;}
<div data-100="font-size:inherit;" data-200="font-size:200px;"></div>

<!--equivalent to-->

<div data-100="font-size:100px;" data-200="font-size:200px;"></div>

Add option to suppress interpolation

Just that I don't forget this:

Skrollr interpolates ALL numbers. For example if you set background-image and the url contains a number, skrollr interpolates it. Thus, we need to be able to suppress interpolation on a per-property-basis. I already know how I want to this be done, but no time.

Anchor hyperlinks within a page do not work even with scrolldeck.js

I'm using John Polacek's Scroll Deck plug-in with my current skrollr based page. When I add navigation and links that travel to different parts of a page, the scrolling stops not even 1000 pixels down the page. What settings need to be configured in the Javascript, CSS, or HTML code or what needs to be done to be able to have a user scroll anywhere within a page?

Relative scroll

I like to know if it's possible to define animations to an element based of its own scroll position instead document scroll position. I'd like to have somethin like this:

<div data-self-1000="opacity:0" data-self-0="opacity:1"></div>

So, when the distance between the top of the element and the top of the window is 1000px, the animation starts and when the top of element is just near the top of the window, the animation stops.

this is useful when you have a lot of elements and you want take the animation control of each element individually, no matter where the element is placed.

automatic background scroll?

Not sure if this is the right place to ask. . . My apologies if this is not right.

Is it possible to have scrolling start automatically on page load?

Would this have a big impact on performance?

Thanks.

requestAnimationFrame

The ideal way to do this is to debouce the scroll event against requestAnimiationFrame and keep that rAF going until the scroll is done.
That way you net out with 60fps and your action matches against screen refresh. It should provide the most smooth output possible.

Unfortunately I don't have any code to provide on this but this recommendation is straight from the chrome engineers who work on smooth graphics. :)

create a base test "factory" for common tasks

When writing async tests with QUnit we often want to scroll to X and then check conditions after position X has been rendered. Copying the logic all over produces redundant code which is hard to maintain.

We need a base test, to which we pass the scroll position and some checks to perform. The actual call should look similar to this

/*
    After scrolling to 100 and waiting for a render to occur, check all DOM elements in "$obj" against the rules.
*/
scrollTest(100, $obj, {
    //Check if the given styles match the ones of the element (using $.fn.css)
    styles: {
        "left": "500px",
        "color": ""
    },

    //Check if the elements all match the given selector
    selector: ".foo:not(.bar)",

    //Arbitrary tests
    custom: function() {
        //Do some custom synchronous tests
    }
});

The Test should also be aware of browser differences. Testing for "opacity" on IE < 9 does not make sense.

Create new website

The current skrollr page does not show everything that's possible and is kind of pointless. But the most important point about updating it is that it's not working on Android, even though skrollr itself works perfectly (tryied it on ice cream sandwich default browser on Galaxy S2). That's because it uses the outdated absolute mode in combination with fixed positioning.

Maybe we should find a designer to create a kick ass page for skrollr with skrollr.

Add option to manually set max key frame

Right now skrollr doesn't fit some use cases. For example if I have a "normal" website and want to spice it up, I don't need things like automatically setting the body height to the max key frame. Instead it has to be the other way round. The original web page needs to stay untouched and skrollr just lives within the page.

Add option maxKeyFrame. Example:

skrollr.init({
    //data-end will now be equal to data-1000, no matter how much you can actually scroll
    maxKeyFrame: 1000
});

Now one could pass the document height as maxKeyFrame and have animations matching the actual scrolling of the original page.

Strange ordering issue

Hey there, loving this plugin.

For CSS position attributes, I had to reverse the order in order to get it to work:

data-end-1600="right:-180px; opacity:0;" data-end-500="right:0px; opacity:1;

worked, for example, whereas:

data-end-1600="opacity:0; right:-180px;" data-end-500="opacity:1; right:0px;"

..fails. Any idea why?

iOS support

Doesn't seem to work on iOS devices. I tested on an iPad with no luck.

I forked the repo and will look into this.

Variables/Constants

Allow setting of constant variables to provide quicker/easier placement of elements.

Say I have 3 major sections of my page: about, how to, documentation

<div id="about" data-about-0="top:0%;" data-about-100="top:20%" data-about-400="top:100%">About</div>
<div id="about" data-how_to-0="left:0%;" data-about-100="left:20%" data-about-400="left:100%">About</div>
<div id="about" data-docs-0="top:100%;" data-about-100="top:50%" data-about-400="top:0%">About</div>

skrollr.init({ 
  constants: { 
      about: 500,
      how_to: 2000,
      docs: 3000}  
   });

would be equivalent to the current

<div id="about" data-500="top:0%;" data-600="top:20%" data-900="top:100%">About</div>
<div id="about" data-2000="left:0%;" data-2100="left:20%" data-2400="left:100%">About</div>
<div id="about" data-3000="top:100%;" data-3100="top:50%" data-3400="top:0%">About</div>

skrollr.init({ });

This would allow you to shift things forward and back easier by changing variables definitions.

prefixed properties

Currently skrollr sets all properties prefixed, which of course is just a temporary solution. That means we are setting things like MozLeft or webkitBackgroundColor which is just wasting cycles. We should rather have a test, if the value needs to be prefixed. Instead of having a whitelist of values and doing a regex Test, it would probably a good idea to test if the property is supported by doing something like this:

var properties = document.createElement('div').style;

//...

//The unprefixed value is not supported
if(!hasProp.call(properties, prop)) {
    //Set all prefixes
}

And maybe instead of looping over all prefixes we should detect which one to use (ua sniffing?).

Add copyright notice

Just a reminder for me.

Add something like this to skrollr.js (UglifyJS will keep it in the minified version automatically).

/*!
 * skrollr v0.2.3
 * parallax scrolling for the masses.
 *
 * Copyright 2012, Alexander Prinzhorn (@Prinzhorn) and contributors.
 *
 * skrollr can be used by everyone under the terms of the MIT license.
 *
 * Demo: http://prinzhorn.github.com/skrollr/
 * Source: https://github.com/Prinzhorn/skrollr
*/

Without the copyright notice people would violate the MIT license without even knowing about. Even though the MIT license states that it shall be included in it's entirety, we all agree that such a header at the beginning of a source code file is enough.

Allow defining fallback animations

Given the following example (which is nonsense btw.):

<div data-0="background:red;background:linear-gradient(red, green);"></div>

The background will have a gradient in browsers which support them and no background in browsers that don't.

The desired behavior would be a red background in browsers that don't support gradients. Skrollr currently implements this by using an object to store property/value pairs. Instead, it should be property/values-array pairs.

Not sure if needed though. A static fallback can still be added as style attribute or via external stylesheet. Only animated fallbacks are currently not supported. Just keep this ticket in mind until someone cries loud enough.

evaluate grunt as build tool

grunt could be used for:

  • testing
  • minification
  • linting

and maybe to automatically add the Version number to the different files.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.