or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

core-scrolling.mdevents.mdfeatures.mdindex.md
tile.json

features.mddocs/

Features & Plugins

Better Scroll's modular architecture provides specialized features through configuration-enabled plugins. Each feature extends the core scrolling functionality with specific capabilities for different use cases.

Capabilities

Snap/Slide Feature

Page-based scrolling with snap-to-position functionality, ideal for carousels, image galleries, and paged content.

interface SnapOptions {
  loop?: boolean;              // Enable infinite loop (default: false)
  threshold?: number;          // Snap threshold (0-1, default: 0.1)
  speed?: number;              // Snap animation speed in ms (default: 400)
  easing?: EasingFunction;     // Snap easing function
  stepX?: number;              // Horizontal step size (default: wrapper width)
  stepY?: number;              // Vertical step size (default: wrapper height)
  el?: HTMLElement | string;   // Snap to specific elements
}

// Methods added when snap enabled
goToPage(x: number, y: number, time?: number, easing?: EasingFunction): void;
next(time?: number, easing?: EasingFunction): void;
prev(time?: number, easing?: EasingFunction): void;
getCurrentPage(): {x: number, y: number, pageX: number, pageY: number} | null;

// Instance properties when snap enabled
currentPage: {
  x: number;                   // Current page X coordinate
  y: number;                   // Current page Y coordinate  
  pageX: number;               // Current page index X
  pageY: number;               // Current page index Y
};
pages: Array<Array<{         // 2D array of page information
  x: number;                 // Page position X
  y: number;                 // Page position Y
  width: number;             // Page width
  height: number;            // Page height
  cx: number;                // Center X
  cy: number;                // Center Y
}>>;

Usage Examples:

// Basic snap scrolling
const scroll = new BScroll('.wrapper', {
  snap: true,
  momentum: false,
  bounce: false
});

// Custom snap configuration
const scroll = new BScroll('.wrapper', {
  snap: {
    loop: true,
    threshold: 0.3,
    speed: 400,
    stepX: 300,
    stepY: 200
  }
});

// Snap to specific elements  
const scroll = new BScroll('.wrapper', {
  snap: {
    el: '.slide-item',
    loop: true
  }
});

// Access current page
console.log('Current page:', scroll.currentPage.pageX, scroll.currentPage.pageY);

// Navigate to specific page
scroll.goToPage(2, 0, 300); // pageX, pageY, duration

Wheel Picker Feature

Wheel-style picker component for selecting items from a list with 3D rotation effects.

interface WheelOptions {
  selectedIndex?: number;      // Initial selected index (default: 0)
  rotate?: number;             // Rotation angle per item in degrees (default: 25)
  adjustTime?: number;         // Animation time for adjustment in ms (default: 400)
  wheelWrapperClass?: string;  // CSS class for wheel wrapper (default: 'wheel-scroll')
  wheelItemClass?: string;     // CSS class for wheel items (default: 'wheel-item')
}

// Methods added when wheel enabled
wheelTo(index: number): void;  // Navigate to specific wheel index
getSelectedIndex(): number | boolean;    // Get currently selected index (returns selectedIndex or false)

// Instance properties when wheel enabled
selectedIndex: number;         // Currently selected item index
items: HTMLElement[];          // Array of wheel item elements

Usage Examples:

// Basic wheel picker
const scroll = new BScroll('.wheel-wrapper', {
  wheel: {
    selectedIndex: 2,
    rotate: 25
  }
});

// Custom wheel configuration
const scroll = new BScroll('.picker', {
  wheel: {
    selectedIndex: 0,
    rotate: 30,
    adjustTime: 300,
    wheelWrapperClass: 'my-wheel',
    wheelItemClass: 'my-wheel-item'
  }
});

// Get selected value
console.log('Selected index:', scroll.selectedIndex);
console.log('Selected item:', scroll.items[scroll.selectedIndex]);

// Programmatically select item
scroll.wheelTo(3); // Select item at index 3

// Get selected index
const selectedIndex = scroll.getSelectedIndex();

Pull-to-Refresh Features

Pull-down refresh and pull-up load functionality with customizable thresholds.

interface PullDownRefreshOptions {
  threshold?: number;          // Pull distance threshold in px (default: 90)
  stop?: number;              // Stop position after pull in px (default: 40)
}

interface PullUpLoadOptions {
  threshold?: number;          // Pull distance threshold in px (default: 50)
}

// Methods added when enabled
/**
 * Complete pull-down refresh action
 * Call after refresh data is loaded
 */
finishPullDown(): void;

/**
 * Complete pull-up load action  
 * Call after more data is loaded
 */
finishPullUp(): void;

/**
 * Dynamically enable/disable pull-down refresh
 */
openPullDown(config?: boolean | PullDownRefreshOptions): void;
closePullDown(): void;

/**
 * Programmatically trigger pull-down refresh
 */
autoPullDownRefresh(): void;

/**
 * Dynamically enable/disable pull-up load
 */
openPullUp(config?: boolean | PullUpLoadOptions): void;
closePullUp(): void;

// Events fired:
// 'pullingDown' - When pull-down threshold reached
// 'pullingUp' - When pull-up threshold reached

Usage Examples:

// Pull-to-refresh setup
const scroll = new BScroll('.wrapper', {
  pullDownRefresh: {
    threshold: 90,
    stop: 40
  },
  pullUpLoad: {
    threshold: 50
  }
});

// Handle pull-down refresh
scroll.on('pullingDown', async () => {
  showRefreshIndicator();
  try {
    await refreshData();
    updateContent();
  } finally {
    hideRefreshIndicator();
    scroll.finishPullDown();
  }
});

// Handle pull-up load more
scroll.on('pullingUp', async () => {
  showLoadingIndicator();
  try {
    const newData = await loadMoreData();
    appendContent(newData);
  } finally {
    hideLoadingIndicator();
    scroll.finishPullUp();
  }
});

Scrollbar Feature

Visual scroll indicators with customizable appearance and behavior.

interface ScrollbarOptions {
  fade?: boolean;              // Auto-fade scrollbar (default: true)
  interactive?: boolean;       // Allow scrollbar interaction (default: false)
}

Usage Examples:

// Basic scrollbar
const scroll = new BScroll('.wrapper', {
  scrollbar: true
});

// Custom scrollbar configuration
const scroll = new BScroll('.wrapper', {
  scrollbar: {
    fade: true,
    interactive: true
  }
});

Mouse Wheel Support

Desktop mouse wheel scrolling support with configurable behavior.

interface MouseWheelOptions {
  speed?: number;              // Scroll speed multiplier (default: 20)
  invert?: boolean;            // Invert scroll direction (default: false)
  easeTime?: number;           // Easing duration in ms (default: 300)
}

Usage Examples:

// Basic mouse wheel support
const scroll = new BScroll('.wrapper', {
  mouseWheel: true
});

// Custom mouse wheel configuration
const scroll = new BScroll('.wrapper', {
  mouseWheel: {
    speed: 20,
    invert: false,
    easeTime: 300
  }
});

Zoom Feature

Pinch-to-zoom functionality with scale limits and smooth transitions.

interface ZoomOptions {
  start?: number;              // Initial zoom scale (default: 1)
  min?: number;                // Minimum zoom scale (default: 1)
  max?: number;                // Maximum zoom scale (default: 4)
}

// Methods added when zoom enabled
/**
 * Zoom to specific scale and position
 * @param scale - Target zoom scale
 * @param x - Target X position  
 * @param y - Target Y position
 * @param time - Animation duration in ms
 */
zoomTo(scale: number, x: number, y: number, time?: number): void;

// Instance properties when zoom enabled
scale: number;                 // Current zoom scale

Usage Examples:

// Basic zoom functionality
const scroll = new BScroll('.wrapper', {
  zoom: {
    start: 1,
    min: 0.5,
    max: 3
  }
});

// Zoom to specific scale and position
scroll.zoomTo(2, 100, 100, 300);

// Get current zoom level
console.log('Current zoom:', scroll.scale);

Infinite Scrolling

Virtual scrolling for large datasets with efficient DOM management.

interface InfinityOptions {
  /**
   * Render function for list items
   * @param item - Data item to render
   * @param div - DOM element to render into
   */
  render(item: any, div: HTMLElement): void;
  
  /**
   * Create tombstone/placeholder elements
   * @returns DOM element for tombstone
   */
  createTombstone(): HTMLElement;
  
  /**
   * Fetch more data when needed
   * @param count - Number of items to fetch
   * @returns Promise resolving to array of data items
   */
  fetch(count: number): Promise<any[]>;
}

Usage Examples:

// Infinite scrolling setup
const scroll = new BScroll('.wrapper', {
  infinity: {
    render(item, div) {
      div.innerHTML = `
        <h3>${item.title}</h3>
        <p>${item.description}</p>
      `;
    },
    
    createTombstone() {
      const tombstone = document.createElement('div');
      tombstone.className = 'tombstone';
      tombstone.innerHTML = '<div class="placeholder"></div>';
      return tombstone;
    },
    
    async fetch(count) {
      const response = await fetch(`/api/items?count=${count}`);
      return response.json();
    }
  }
});

Multi-Feature Configurations

Features can be combined for complex scrolling experiences:

// Gallery with snap and zoom
const gallery = new BScroll('.gallery-wrapper', {
  scrollX: true,
  scrollY: false,
  snap: {
    loop: true,
    stepX: 300
  },
  zoom: {
    start: 1,
    min: 0.5,
    max: 3
  },
  mouseWheel: true
});

// List with pull-to-refresh and scrollbar
const list = new BScroll('.list-wrapper', {
  pullDownRefresh: {
    threshold: 90,
    stop: 40
  },
  pullUpLoad: {
    threshold: 50
  },
  scrollbar: {
    fade: true
  },
  probeType: 2
});

// Picker with multiple wheels
const picker = new BScroll('.picker-wrapper', {
  wheel: {
    selectedIndex: 0,
    rotate: 25,
    wheelItemClass: 'picker-item'
  },
  momentum: false,
  bounce: false
});

Performance Considerations

Feature-Specific Optimizations

// For snap/slide - disable momentum and bounce
const slideScroll = new BScroll('.slides', {
  snap: true,
  momentum: false,
  bounce: false,
  probeType: 0  // No scroll events needed
});

// For infinite scroll - minimal animations
const infiniteScroll = new BScroll('.infinite-list', {
  infinity: { /* config */ },
  useTransition: false,  // Use JS animation for smoother infinite scroll
  probeType: 3          // Real-time events for scroll position tracking
});

// For zoom - hardware acceleration
const zoomScroll = new BScroll('.zoom-container', {
  zoom: { /* config */ },
  HWCompositing: true,   // Enable hardware acceleration
  useTransform: true     // Use CSS transforms
});

Memory Management

// Clean up when switching between features
function switchToInfiniteMode() {
  // Destroy existing instance
  if (currentScroll) {
    currentScroll.destroy();
  }
  
  // Create new instance with different features
  currentScroll = new BScroll('.wrapper', {
    infinity: infinityConfig
  });
}

// Proper cleanup on page unload
window.addEventListener('beforeunload', () => {
  if (scroll) {
    scroll.destroy();
  }
});