- Overview
- Documents
Sliding views (incoming views that “push” old ones off-screen) have become so commonplace in mobile design we tend to take them for granted. They’re useful because they allow content to be broken into bite-sized chunks while maintaining hierarchy through the use of spacial animation. They look pretty neat, too.
There are a lot of existing JavaScript solutions for this sort of thing, but most are built for hybrid mobile apps with a lot of complexity and stringent markup requirements… understandably so given the goals of those projects! Others seem catered to carousels over body content. We needed something web-focused and super simple, with the ability to activate/deactivate for responsive layouts.
What it does
Sliding views let you present content in distinct, bite-sized chunks while maintaining hierarchy through the use of spacial animation. They look neat, too.
There are many wonderful JavaScript frameworks out there that pull this off beautifully... but they can get kind of complicated. When your needs are simple or responsive,SimpleSlideView may do the trick.
Getting started
SimpleSlideView requires two types of elements to be present in your markup:
- A container for the views that will be sliding.
- An element for each of the views themselves. These don't have to be immediate children of the container, but they should be nested somewhere inside of it.
A very simple example:
<div class="container"> <!-- the container --> <div class="view">...</div> <!-- first view (shown by default) --> <div class="view">...</div> <!-- second view --> <div class="view">...</div> <!-- and so on... --> </div>
You then call simpleSlideView on the containing element:
$('.container').simpleSlideView();
If you'd like to use a different selector than .view for the views, you can specify an argument:
$('.container').simpleSlideView('.my-view-selector');
More options are available and can be passed as an object.
Navigating between views
Once the plugin is active, only the active view will be visible, so we probably want some way to navigate to the other views. There are two types of navigation that can occur... a "push" (target view animates in from right) or a "pull" (target view animates in from left).
With HTML
If you want to specify view navigation in your markup, the data-popview and data-pushview attributes are the way to go.
If you have a link with an href that already resolves to a view, just add one or the other attribute:
<a href="#view-1" data-popview>Backward!</a> <a href="#view-3" data-pushview>Forward!</a>
You can also specify an attribute value. This is useful if you want to use a more complicated selector that would be invalid as an href, you want to link to a different destination while the SimpleSlideView is active, or you want to use an element that isn't a link at all:
<div data-pushview=".view.weird:first">To the first weird view!</div>
With JavaScript
The simpleSlideView method returns an object with methods you can use to navigate with JavaScript.
// Instantiates the SimpleSlideView var slideView = $('.container').simpleSlideView(); // Pushes the view with an ID of 'my-view-selector' slideView.pushView('#my-view-selector');
See methods for more info.
Getting responsive
A sliding view isn't always appropriate when the viewport can show more content. Luckily, you can turn SimpleSlideView off and on whenever it makes sense for your project using the toggle, on and offmethods.
By default, SimpleSlideView will activate itself when initialized, but you can disable this by setting the deferOnoption to true. An example:
var slideView = $('.container').simpleSlideView({ // Do not activate unless the viewport is larger than 768pt deferOn: ($(window).width() >= 768) }); // Turn on/off if window size changes $(window).on('resize', function(){ slideView.toggle($(window).width() < 768); });
See the responsive demo for a more in-depth example.
Options
You can pass an object to the simpleSlideView method as the first or second argument:
// This... $('.container').simpleSlideView('.my-view-selector', { duration: 250 }); // ...is the same as this: $('.container').simpleSlideView({ views: '.my-view-selector', duration: 250 });
Here are all the options and their defaults:
# The default view selector. An object will be a # jQuery or Zepto object, a string will be used # as a selector within the container. views: '.view' # The view that should be initially active. Can # also be an object or string. If 'null', the first # view in the container will be used. activeView: null # If 'true', SimpleSlideView will not activate # until the on() method is called. deferOn: false # The speed of animations. Defaults to the current # jQuery or Zepto default. duration: $.fx.speeds._default # The easing method to use for animations. Defaults # to 'ease-out' for Zepto and 'swing' for jQuery. easing: if Zepto? then 'ease-out' else 'swing' # If true, animations will act on the 'transform' # properties rather than 'right' or 'left'. Defaults # to 'true' for Zepto. useTransformProps: Zepto? # When 'true', 3D transforms will be used. Can sometimes # improve performance. 'true' by default if Modernizr and # the 'csstransforms3d' test are included. use3D: Modernizr? and Modernizr.csstransforms3d # The CSS prefix to use for the 'transform' property. # Defaults to the one the framework is using (if any). cssPrefix: if $.fx.cssPrefix? then $.fx.cssPrefix else '' # If 'true', the height of the container will be resized # to match the height of the active view (both initially # and as the views change. You should set to 'false' if # your container's height is fixed. resizeHeight: true # Duration of the height animations when 'resizeHeight' # is true. If 'null', the value of the duration option # will be used. heightDuration: null # If 'true', the height change will not wait for the # slide to complete before resizing. This can feel # snappier but may affect performance. concurrentHeightChange: ! Zepto? # If 'start', the scrollCallback will happen before # the rest of the slide. If 'end', it will happen # after. If false, scrolling will be disabled. scrollOn: 'start' # The callback to use for scrolling when the view # change completes. Supports jQuery scrollTo, # ZeptoScroll and no scroll plugin, but you can # define your own. The callback should expect to # receive three arguments: a Y-coordinate for the # intended scroll position, a duration for the # animation (if supported), and an optional callback # when the action completes. scrollCallback: scrollCallback # Duration of the scroll animation if the callback # supports it. If 'null', the value of the duration # option will be used. scrollDuration: null # If 'true', the scroll will move to the top of the # container. If 'false', the top of the window will # be used. scrollToContainerTop: true # If scrollOn is 'start' and this is 'true', the # slide will not wait for the scroll to complete # before triggering other events. This can feel # snappier but may affect performance. concurrentScroll: ! Zepto? # If 'true', the height of the viewport will never # lower. If 'null', the value will be based on whether # or not resizeHeight and scrollOnStart are both truthy. # This is useful for avoiding odd animation in browsers # that resize the viewport as they scroll, such as # iOS Safari. maintainViewportHeight: null # The event that the magic data-attribute events will # be bound to. If 'false', no events will be bound. dataAttrEvent: 'click' # The names of the data attributes to use for the magic # event bindings. dataAttr: push: 'pushview' pop: 'popview' # Class names that get added to the different elements as # the plugin does its thing. These have no utility to the # plugin, they are merely for styling and convenience. classNames: container: 'SimpleSlideView-container' view: 'SimpleSlideView-view' activeView: 'SimpleSlideView-view-active' # Names of events that will get triggered. See the # README for more info. eventNames: on: 'slideViewOn' off: 'slideViewOff' beforeOn: 'slideViewBeforeOn' beforeOff: 'slideViewBeforeOff' deferred: 'slideViewDeferred' viewChangeStart: 'viewChangeStart' viewChangeEnd: 'viewChangeEnd'
Methods
Save the output of the plugin to a variable if you intend to use methods:
var slideView = $('.container').simpleSlideView(); slideView.pushView('#view-2');
on, off and toggle
on() off() toggle(activate)
These methods activate or deactivate the plugin. You don't have to fire on() unless you've set deferOn to true or you've called off() or toggle().
Without arguments, toggle() will call on() if the plugin is off and off() if the plugin is on. You can also pass a boolean value (true for on).
pushView and popView
pushView(targetView) popView(targetView)
Will push or pop to targetView. This will get passed to $, so it can be whatever kind of selector jQuery or Zepto would accept.
These are shortcut methods for...
changeView
changeView(targetView, action)
This works the same as pushView or popView, accept it needs a value for action of either 'push' or 'pop'.
Events
These are triggered on the containing element. All event names can be customized using the eventNamesoption.
viewChangeStart and viewChangeEnd
Triggered at the start and end of any view change (push or pop). In addition to the usual event object, your callback can also receive the targetView and action arguments the changeView function did:
$('.container').on('viewChangeStart', function (event, targetView, action) { console.log(targetView); // Whatever you or a magic method passed console.log(action); // 'push' or 'pop' });
slideViewOn and slideViewOff
These events are triggered when the plugin is activated or deactivated. This can be useful if you want to use the plugin in some layouts but not others. You can see an example of this in the responsive demo.
slideViewBeforeOn and slideViewBeforeOff
Similar to the "on" and "off" events, except they are triggered before the plugin begins to be activated or deactivated. See the responsive demo for an example.
slideViewDeferred
Triggered if the plugin is initialized but deferOn is truthy. See the responsive demo for an example.
Known issues and limitations
Hashes and maintaining history
There are entire libraries devoted to maintaining history with JavaScript. Frankly, the task seemed too large for this library to handle. If you have ideas for integrating history, please consider contributing to the project.
Multi-view transitions
Some interfaces will animate multiple views in a row if you pop a view far into its history. This isn't part of SimpleSlideView right now because we don't maintain history and we don't require views exist in any particular hierarchy we could infer history from.
Dynamic content
This plugin was designed with static webpages in mind. It currently maintains jQuery/Zepto objects for the views available to it when instantiated. Because of this, it is not particularly well-suited for interfaces that load a large amount of content dynamically. There is an existing issue for this; additional feedback, ideas and pull requests are welcome.
Animation performance
We've noticed that some pages perform better with CSS animations and some with JavaScript. Speaking broadly, pages with a lot of complex or animating content tend to perform better with JS, while most other pages seem to perform better with CSS. We hope that by relying on the $.animate method and providing options for useTransformProps and use3D we've given you the ability to experiment with what works best for your project.
As of 1.1.x, you can now disable some concurrent animations by setting concurrentScroll and/or concurrentHeightChange to false. This may improve performance for some projects.
Nested instances
You will probably run into conflicts if you try nesting one sliding view in another. You can remedy some conflicts by specifying different names for conflicting attributes. For example:
var parentSlideView = $('#parent').slideView({ dataAttr: { push: 'parent-pushview', pop: 'parent-popview' } }); var childSlideView = $('#child').slideView({ dataAttr: { push: 'child-pushview', pop: 'child-popview' } });