Convert Figma logo to code with AI

jakiestfu logoSnap.js

A Library for creating beautiful mobile shelfs in Javascript (Facebook and Path style side menus)

5,980
661
5,980
155

Top Related Projects

6,784

Swipe is the most accurate touch slider.

12,858

Smooth scrolling for the web

24,314

A javascript library for multi-touch gestures :// You can touch this

18,604

Polyfill to remove click delays on browsers with touch UIs

15,086

Zepto.js is a minimalist JavaScript library for modern browsers, with a jQuery-compatible API

41,170

Most modern mobile touch slider with hardware accelerated transitions

Quick Overview

Snap.js is a lightweight JavaScript library that enables the creation of side menus with smooth sliding animations. It provides an easy way to implement off-canvas navigation patterns in web applications, supporting both left and right side menus with customizable settings.

Pros

  • Simple and lightweight, with minimal dependencies
  • Supports both left and right side menus
  • Highly customizable with various options for animation and behavior
  • Touch-friendly, works well on mobile devices

Cons

  • Limited to side menu functionality, not a comprehensive UI framework
  • May require additional styling to match specific design requirements
  • Documentation could be more extensive
  • Not actively maintained (last update was several years ago)

Code Examples

  1. Basic initialization:
var snapper = new Snap({
    element: document.getElementById('content')
});
  1. Opening the left side menu:
snapper.open('left');
  1. Adding event listeners:
snapper.on('start', function(){
    console.log('Starting animation');
});

snapper.on('end', function(){
    console.log('Animation finished');
});
  1. Customizing settings:
var snapper = new Snap({
    element: document.getElementById('content'),
    dragger: null,
    disable: 'right',
    addBodyClasses: true,
    hyperextensible: true,
    resistance: 0.5,
    flickThreshold: 50,
    transitionSpeed: 0.3,
    easing: 'ease',
    maxPosition: 266,
    minPosition: -266,
    tapToClose: true,
    touchToDrag: true,
    slideIntent: 40,
    minDragDistance: 5
});

Getting Started

  1. Include the Snap.js library in your HTML file:
<script src="snap.js"></script>
  1. Set up your HTML structure:
<div id="content">
    <!-- Your main content here -->
</div>
<div class="drawer-left">
    <!-- Left side menu content -->
</div>
<div class="drawer-right">
    <!-- Right side menu content -->
</div>
  1. Initialize Snap.js in your JavaScript:
var snapper = new Snap({
    element: document.getElementById('content')
});

// Open left menu
document.getElementById('open-left').addEventListener('click', function(){
    snapper.open('left');
});

// Open right menu
document.getElementById('open-right').addEventListener('click', function(){
    snapper.open('right');
});
  1. Add some basic CSS to position your elements:
.drawer-left, .drawer-right {
    position: absolute;
    top: 0;
    height: 100%;
    width: 266px;
}
.drawer-left { left: 0; }
.drawer-right { right: 0; }
#content {
    position: relative;
    z-index: 2;
    background: #fff;
}

Competitor Comparisons

6,784

Swipe is the most accurate touch slider.

Pros of Swipe

  • Lightweight and focused solely on swipe gestures, making it more efficient for simple swipe interactions
  • Supports both horizontal and vertical swipes out of the box
  • Easier to implement for basic swipe functionality in web applications

Cons of Swipe

  • Limited to swipe gestures only, lacking the broader range of interactions offered by Snap.js
  • Less customizable in terms of animation and behavior compared to Snap.js
  • May require additional libraries or custom code for more complex UI interactions

Code Comparison

Swipe implementation:

var swiper = new Swipe(document.getElementById('slider'));
swiper.onLeft(function() { console.log('left'); });
swiper.run();

Snap.js implementation:

var snapper = new Snap({
  element: document.getElementById('content')
});
snapper.on('open', function(){
  console.log('opened');
});

Summary

Swipe is a lightweight library focused on swipe gestures, making it ideal for simple swipe interactions in web applications. It's easy to implement but limited in scope. Snap.js, on the other hand, offers a broader range of interactions and customization options, making it more suitable for complex UI requirements. The choice between the two depends on the specific needs of the project and the desired level of functionality.

12,858

Smooth scrolling for the web

Pros of iScroll

  • More comprehensive scrolling solution with support for various scroll types (vertical, horizontal, infinite, etc.)
  • Better performance optimization for mobile devices
  • Extensive API and customization options

Cons of iScroll

  • Larger file size and potentially more complex implementation
  • May have a steeper learning curve due to its extensive features
  • Less focused on specific side-menu functionality compared to Snap.js

Code Comparison

Snap.js (basic usage):

var snapper = new Snap({
  element: document.getElementById('content')
});

iScroll (basic usage):

var myScroll = new IScroll('#wrapper', {
  scrollX: true,
  scrollY: true,
  mouseWheel: true
});

Both libraries offer simple initialization, but iScroll provides more options for customization in its constructor. Snap.js focuses on side-menu functionality, while iScroll is a more general-purpose scrolling solution.

iScroll offers a wider range of scrolling behaviors and optimizations, making it suitable for complex mobile applications. However, this comes at the cost of a larger file size and potentially more complex implementation.

Snap.js, on the other hand, is more lightweight and specifically designed for creating side menus, making it easier to implement for that particular use case. It may be preferable for projects that only require side-menu functionality without the need for advanced scrolling features.

24,314

A javascript library for multi-touch gestures :// You can touch this

Pros of Hammer.js

  • More comprehensive touch gesture support, including multi-touch gestures
  • Actively maintained with regular updates and a larger community
  • Better cross-platform compatibility, including desktop and mobile devices

Cons of Hammer.js

  • Larger file size and potentially higher overhead
  • Steeper learning curve due to more complex API and options
  • May be overkill for simple touch interactions

Code Comparison

Snap.js (basic drawer implementation):

var snapper = new Snap({
  element: document.getElementById('content')
});
snapper.open('left');

Hammer.js (basic swipe detection):

var hammer = new Hammer(document.getElementById('content'));
hammer.on('swipe', function(ev) {
  console.log(ev.direction);
});

Summary

Hammer.js is a more feature-rich and actively maintained touch gesture library, offering a wide range of gestures and better cross-platform support. However, it comes with a larger file size and potentially more complex implementation. Snap.js, on the other hand, is more focused on specific drawer-like interactions and may be simpler to implement for basic use cases. The choice between the two depends on the specific requirements of your project and the complexity of touch interactions needed.

18,604

Polyfill to remove click delays on browsers with touch UIs

Pros of FastClick

  • Specifically designed to eliminate the 300ms delay on mobile devices, improving touch responsiveness
  • Lightweight and focused on a single purpose, making it easy to integrate
  • Widely adopted and well-maintained by the Financial Times Labs team

Cons of FastClick

  • Limited in scope compared to Snap.js, which offers more comprehensive touch interaction features
  • May require additional libraries or code for more complex touch-based interactions
  • Not actively maintained since 2016, which could lead to compatibility issues with newer devices or browsers

Code Comparison

Snap.js (basic usage):

var snapper = new Snap({
  element: document.getElementById('content')
});

FastClick (basic usage):

if ('addEventListener' in document) {
  document.addEventListener('DOMContentLoaded', function() {
    FastClick.attach(document.body);
  }, false);
}

Summary

FastClick is a specialized library focused on eliminating touch delays, while Snap.js offers a broader range of touch-based interaction features. FastClick is simpler to implement for its specific use case, but Snap.js provides more flexibility for complex touch interactions. The choice between the two depends on the project's requirements and the desired level of touch interaction complexity.

15,086

Zepto.js is a minimalist JavaScript library for modern browsers, with a jQuery-compatible API

Pros of Zepto

  • Lightweight jQuery-compatible JavaScript library, offering a broader range of functionality
  • Better suited for general-purpose web development tasks
  • Extensive browser compatibility, including mobile devices

Cons of Zepto

  • Not specifically designed for creating off-canvas menus or side panels
  • Requires more custom code to achieve similar functionality to Snap.js
  • Larger file size compared to Snap.js, which is more focused on a single task

Code Comparison

Snap.js (Creating a drawer):

var snapper = new Snap({
  element: document.getElementById('content')
});
snapper.open('left');

Zepto (Implementing a similar drawer):

$('#drawer').animate({left: '0'}, 300);
$('#content').animate({marginLeft: '250px'}, 300);

Summary

Zepto is a versatile JavaScript library that can be used for various web development tasks, including creating off-canvas menus. However, it requires more custom code to achieve the specific functionality that Snap.js provides out of the box. Snap.js is more focused on creating off-canvas menus and side panels, making it easier to implement these specific features with less code. The choice between the two depends on the project's requirements and the developer's preference for a more specialized tool versus a general-purpose library.

41,170

Most modern mobile touch slider with hardware accelerated transitions

Pros of Swiper

  • More feature-rich with advanced functionality like lazy loading, parallax effects, and virtual slides
  • Better documentation and extensive API, making it easier to customize and integrate
  • Actively maintained with frequent updates and a larger community

Cons of Swiper

  • Larger file size, which may impact page load times for simpler projects
  • Steeper learning curve due to its extensive feature set
  • May be overkill for basic sliding functionality

Code Comparison

Snap.js (basic initialization):

var snapper = new Snap({
  element: document.getElementById('content')
});

Swiper (basic initialization):

var swiper = new Swiper('.swiper-container', {
  slidesPerView: 3,
  spaceBetween: 30,
  pagination: {
    el: '.swiper-pagination',
    clickable: true,
  },
});

While both libraries offer sliding functionality, Swiper provides more options out of the box, as seen in the initialization code. Snap.js focuses on side menus and off-canvas navigations, whereas Swiper is primarily designed for content sliders and carousels. The choice between the two depends on the specific project requirements and desired features.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Snap.js

A Library for creating beautiful mobile shelfs in Javascript

View Video Preview

View Demos

Features

  • Library Independent
  • High Customization
  • Flick Support
  • User Intent Detection
  • Disable Hyperextension
  • Event Hooks
  • CSS3 Powered Animations with IE fallbacks
  • Drag Support
  • Drag Handle Support
  • Programatic API
  • "No-Drag" Elements
  • Definable Easing Mode
  • Enable/Disable Events
  • Disabled Sides (left or right)
  • Supports Ratchet (with templates!)

Support

  • Firefox 10+
  • Wide Webkit Support (including Android WebKit 2.3.X)
  • IE 10
  • IE 9 Supports Toggling, Dragging but no Transitions
  • IE 7/8 Supports Toggling but no dragging or Transitions

Installation

As standalone just include the file in a script tag:

<script src="snap.js"></script>

As a web component do:

$ component install jakiestfu/Snap.js

Usage

var snapper = new Snap({
  element: document.getElementById('content')
});

Settings and Defaults

settings = {
    element: null,
    dragger: null,
    disable: 'none',
    addBodyClasses: true,
    hyperextensible: true,
    resistance: 0.5,
    flickThreshold: 50,
    transitionSpeed: 0.3,
    easing: 'ease',
    maxPosition: 266,
    minPosition: -266,
    tapToClose: true,
    touchToDrag: true,
    slideIntent: 40,
    minDragDistance: 5
}
  • element: The element which the user will be sliding side to side
  • dragger: The element which the user will be using to slide the target element side to side
  • disable: String, set to 'left' or 'right' to disable the respective side
  • addBodyClasses: Add classes to the body to signify which side is being opened
  • hyperextensible: If false, pane may not be slide past the minPosition and maxPosition
  • resistance: The cooeficcient used to slow sliding when user has passed max or min threshold
  • flickThreshold: Number of pixels the user needs to swiftly travel to activate a "flick" open
  • transitionSpeed: The speed at which the pane slides open or closed
  • easing: The CSS3 Easing method you want to use for transitions
  • maxPosition: Maximum number of pixels the pane may be slid to the right
  • minPosition: Maximum number of pixels the pane may be slid to the left
  • tapToClose: If true, tapping an open pane will close it
  • touchToDrag: If true, dragging the target settings.element will open/close the pane
  • minDragDistance: The minimum amount of pixels the user needs to drag within the slideIntent degrees to move the pane
  • slideIntent: The number of degrees the user must initiate sliding in towards the left or right (see diagram below)

Notes on Slide Intent: The slide intent is an int between 0 and 90, and represents the degrees in the first quadrant of a circle that you would like to have mirrored on the X and Y axis. For example, if you have 40 set as your slideIntent value, the user would only be able to slide the pane by dragging in the blue area in the diagram below. Once intent has been defined, it will not change until the user releases.

Public Methods

open: Opens the pane to the specified side

snapper.open('left');
// OR
snapper.open('right');

close: Closes the pane

snapper.close();

expand: Opens the pane entirely

snapper.expand('left');
// OR
snapper.expand('right');

disable: Disables sliding events

snapper.disable();

enable: Enables sliding events after disabling

snapper.enable();

on: Adds an event hook

snapper.on('start', function(){
  // Do Something
});

The available methods to hook into are as follows:

  • start: Fired when touching down on the draggable pane and it begins to move
  • drag: Fired when the pane has been moved or slid
  • end: Fired when the pane has been let go of
  • animating: Fired when the pane is animating
  • animated: Fired when the pane is finished it's animations
  • ignore: Fired when trying to drag the pane but ended up dragging on an ignored element
  • close: Fired when close is called directly or if tapToClose is set to true
  • open: Fired when the menu is opened
  • expandLeft: Fired on expand('left')
  • expandRight: Fired on expand('right')
  • enable: Fired on enable
  • disable: Fired on disable

off: Removes an event hook

snapper.off('drag');

The event names listed above apply for the off method.

settings: Updates the settings for an already instantiated object

snapper.settings({yourSettings});

Currently, settings.element, settings.touchToDrag cannot be updated. To update the element, instantiate a new object. To allow listening to a drag, use snapper.enable()

state: Returns detailed information about the state of the pane

var data = snapper.state();

The data returned from the state method will look like the following:

{
    state: "closed", // State of the Pane
    info:{
        opening: "left", // Side which user intends to open
        towards: "right", // Direction user is dragging towards
        hyperExtending: false, // True if user is pulling past predefined bounds
        halfway: false, // True if pane is at least halfway open
        flick: false, // True if user has moved pane X amount of pixels in the open/close direction without changing directions
        translation:{
            absolute: 20, // Pixels pane has translated
            relative: 21, // Pixels pane has translated relative to starting translation
            sinceDirectionChange: 10, // Pixels pane has translated since the direction of the pane has changed
            percentage: 40.571649 // The percentage that the Pane is open. Good or animating other things
        }
    }
} 

Gotchas

Layout

The layout itself is what most people will have a hard time emulating, so the simplest approach I have found is as follows:

Two absolute elements, one to represent all the content, and another to represent all the drawers. The content has a higher z-index than the drawers. Within the drawers element, it's direct children should represent the containers for the drawers, these should be fixed or absolute. Assigning classes to your drawers to specify which side it is on is recommended. All absolutely positioned elements should have 0 for top, left, right, bottom properties, excluding your panes which will have auto set to their respective sides and a width assigned. The width of your drawers is usually the same number you want to use for minPosition and maxPosition

div.drawers {position: absolute;}
    div.left-drawer  {position: absolute;}
        [content]
    div.right-drawer  {position: absolute;}
        [content]
div#content {position: absolute;}
    [top-bars]
    [content] {overflow: auto}
    [bottom-bars]

A sample layout is found in demo/apps/default.html.

Independent Scrolling

Some CSS is required to get some smooth ass scrolling. Utilize the CSS below to apply this to any of your elements:

.scrollable{
    overflow: auto;
    -webkit-transition-property: top, bottom;
    transition-property: top, bottom;
    -webkit-transition-duration: .2s, .2s;
    transition-duration: .2s, .2s;
    -webkit-transition-timing-function: linear, linear;
    transition-timing-function: linear, linear;
    -webkit-overflow-scrolling: touch;
}

Z-Indeces and Display

Because of the nature of this code, drawers are just kind of stacked behind the content. To bring the proper drawer to the front, you can hook into Snaps.js' CSS classes:

With addBodyClasses set to true in your initialize options, one of the two classess will be added to the body tag: .snapjs-left or .snapjs-right, depending on which pane is being open, respectively. This being said, you can apply your CSS like the following to show the proper drawers:

.snapjs-right .left-drawer,
.snapjs-left .right-drawer {
    display: none;
}

FAQ

- How do I make a toggle button?

Toggles have been a popular request, but rather than bog the library down with additional methods, you can utilize the powerful API of Snap.js to create your own toggle. Toggles can be done like the following:

myToggleButton.addEventListener('click', function(){

    if( snapper.state().state=="left" ){
        snapper.close();
    } else {
        snapper.open('left');
    }

});

- How do I disable Snap.js dragging for my touch slider?

Snap.js supports cascading cancellation of events via a data attribute data-snap-ignore. If you were to use a slider, your markup might look like the following:

<div class="slider" data-snap-ignore="true">
    <ul>
        <li><img src="slide.jpg"></li>
        <li><img src="slide.jpg"></li>
        <li><img src="slide.jpg"></li>
        <li><img src="slide.jpg"></li>
        <li><img src="slide.jpg"></li>
    </ul>
</div>

All interactions on children elements of the element with the data-snap-ignore attribute will have their Snap.js events ignored.

- I am using Push.js from Ratchet, I keep losing my events on my elements, how can I fix this?

Simple. As wack as Push.js is (yes, it is in desperate need of attention as of v1.0.0), we can still solve this problem with it's only callback, 'push'.

// The function that will initialize your Snap.js instance
var doSnap = function(){
    if(window.snapper){
         // Snap.js already exists, we just need to re-bind events
        window.snapper.enable();
    } else {
        // Initialize Snap.js
        window.snapper = new Snap({
            element: document.getElementById('content')
        });
    } 
};

window.addEventListener('push', doSnap);
doSnap();

- Snap.js works on my Android device but i cannot scroll the content in my drawers, what gives?

Older Android devices (and iPhone as well) do not have native support for overflow scrolling. To solve this, you may use the wonderful library called iScroll

- transform: translate3d() breaks my fixed child elements, how can I solve this?

This is a problem with Chromium and should be fixed soon. I would advise not having your direct children element set to fixed, that may possibly solve your problem.

- I am experiencing a weird flicker when the CSS transform is applied

To solve the flicker, apply the following CSS to the element in question

#content{
    backface-visibility:hidden;
    -webkit-backface-visibility:hidden; /* Chrome and Safari */
    -moz-backface-visibility:hidden; /* Firefox */
    -ms-backface-visibility:hidden; /* Internet Explorer 10+ */
}

Compliments

This code attempts to make your webapp's feel more "native". These other repos go well with it, too!

Licensing

MIT, dawg