
Selectables is a tiny, zero-dependency JavaScript library that allows you to select multiple html elements with mouse drag and touch interactions through the Pointer Events API.
It’s ideal for developers who need interactive selection in file managers, image galleries, or data grids.
Features:
- Collision Detection Modes: Choose between ‘touch’ (partial overlap) or ‘fit’ (full containment) selection logic.
- Programmatic API: Control selection state with methods like
selectAll(),invertSelection(), andgetSelected(). - Auto-Scroll Capability: Automatically scrolls the viewport when dragging near window edges.
- Selection Modes: Toggle, add, remove, or replace selection behavior based on user interactions.
- Keyboard Modifiers: Configure which keys enable selection or add to existing selections.
See also:
How to use it:
1. Install Selectables with NPM and import it into your project.
# NPM $ npm install selectables
// Import the library (ES Module) import Selectables from 'selectables'; import 'selectables/css';
2. Or include directly from CDN:
<link rel="stylesheet" href="https://unpkg.com/selectables/dist/selectables.css"> <script src="https://unpkg.com/selectables/dist/selectables.min.js"></script>
3. Create a container with selectable items:
<div id="gallery"> <div class="photo">Image 1</div> <div class="photo">Image 2</div> <div class="photo">Image 3</div> <!-- More items... --> </div>
4 Initialize the Selectables and specify the target container & elements to select.
const selectable = new Selectables({
// Container element selector
zone: '#gallery',
// Items that can be selected
elements: '.photo',
// CSS class applied to selected items
selectedClass: 'selected',
// Fires when an item is selected
onSelect: (element) => {
console.log('Selected:', element);
}
});5. All configuration options and callback functions.
zone(string | HTMLElement): The container element that contains selectable items. Accepts a CSS selector string or direct DOM element reference. Default:'#wrapper'.elements(string): CSS selector for items within the zone that can be selected. Default:'a'.selectedClass(string): CSS class name applied to selected elements. Default:'active'.key(string | false): Keyboard key required to activate selection. Options:'altKey','ctrlKey','metaKey', orfalsefor no requirement. Default:false.moreUsing(string): Keyboard key that adds to existing selection instead of replacing it. Options:'shiftKey','altKey','ctrlKey'. Default:'shiftKey'.enabled(boolean): Automatically enable selection on initialization. Default:true.appendTo(string): Where to append the selection box element. Default:'body'.selectionMode(string): How selection behaves during drag. Options:'toggle'(flip each item’s state),'add'(only select),'remove'(only deselect),'replace'(clear previous). Default:'toggle'.tolerance(string): Collision detection mode.'touch'selects items with any overlap,'fit'requires items to be fully inside the selection box. Default:'touch'.minDragDistance(number): Minimum pixels the mouse must move before selection starts. Prevents accidental selections on clicks. Default:0.scrollOnEdge(boolean): Enable automatic viewport scrolling when dragging near window edges. Default:false.scrollSpeed(number): Pixels to scroll per frame when auto-scrolling. Default:10.scrollEdgeSize(number): Distance from window edge in pixels that triggers auto-scroll. Default:50.start(function): Callback fired when selection drag begins. Receives the pointer event.stop(function): Callback fired when selection drag ends. Receives the pointer event and array of selected elements.onSelect(function): Callback fired each time an individual element is selected. Receives the element.onDeselect(function): Callback fired each time an individual element is deselected. Receives the element.onChange(function): Callback fired when selection state changes. Receives array of currently selected elements and the triggering event.
const selectable = new Selectables({
zone: '#wrapper',
elements: 'a',
selectedClass: 'active',
key: false, // 'altKey', 'ctrlKey', 'metaKey', false
moreUsing: 'shiftKey', // Key to add more to selection
enabled: true,
appendTo: 'body', // Where to append selection box
selectionMode: 'toggle', // 'toggle', 'add', 'remove', 'replace'
tolerance: 'touch', // 'touch' or 'fit' (partial or full overlap)
minDragDistance: 0, // Min pixels to drag before selecting
scrollOnEdge: false, // Auto-scroll when dragging near edges
scrollSpeed: 10,
scrollEdgeSize: 50,
// Callbacks
start: null,
stop: null,
onSelect: null,
onDeselect: null,
onChange: null
});6. API methods.
// Enable or disable selection functionality
selectable.enable(); // Activates drag-to-select behavior
selectable.disable(); // Deactivates all selection interactions
selectable.destroy(); // Cleanup: removes all event listeners and references
// Check current state
const isActive = selectable.isEnabled(); // Returns boolean
// Programmatic selection - accepts selector string, element, or array
selectable.select('.photo'); // Select by CSS selector
selectable.select(document.querySelector('.photo')); // Select specific element
selectable.select([el1, el2, el3]); // Select multiple elements
// Deselect items
selectable.deselect('.photo'); // Deselect by selector
selectable.deselectAll(); // Clear entire selection
// Bulk operations
selectable.selectAll(); // Select all items in the zone
selectable.invertSelection(); // Flip selection state of all items
// Toggle individual items
selectable.toggle('.photo'); // Toggle selection state
// Query selection state
const selected = selectable.getSelected(); // Returns array of selected HTMLElements
const count = selectable.getSelectedCount(); // Returns number of selected items
const total = selectable.getItemCount(); // Returns total selectable items
// Update configuration at runtime
selectable.setOptions({
selectedClass: 'highlighted',
minDragDistance: 10
});
// Retrieve current configuration
const currentOptions = selectable.getOptions();FAQs:
Q: Does Selectables work on mobile devices and tablets?
A: Yes. Selectables uses Pointer Events which handle both mouse and touch input through a unified API. The library detects touch gestures the same way it processes mouse drags.
Q: How do I prevent selection from interfering with click events on items?
A: Use the minDragDistance option to require a minimum pixel movement before selection activates. Set it to 5 or 10 pixels. This allows simple clicks to pass through while drag gestures trigger selection. The library also automatically prevents click events from firing on items when a drag operation has occurred.
Q: Can I customize the appearance of the selection box?
A: Yes. The selection box has an ID of s-rectBox. Override the default styles in your CSS. You can change the border, background color, opacity, or add effects like border-radius or box-shadow. The library only sets position and dimensions inline.
Q: What happens if I dynamically add items to the container after initialization?
A: Call the selection methods to refresh the internal item cache. Running selectable.selectAll() followed by selectable.deselectAll() forces an update. Alternatively, disable and re-enable the instance. The library queries for items when selection starts, so new items added before the next drag will be detected automatically.
Changelog:
v2.0.0 (01/23/2025)
- ES6+ Rewrite: Complete modernization with ES6 classes, arrow functions, const/let
- Touch Support: Pointer Events API for universal mouse/touch/pen input
- TypeScript Support: Full type definitions in selectables.d.ts
- New API Methods
- New Options
- Minimum browser support now modern browsers only
- Module system now supports ESM, CommonJS, and UMD
- Selection box uses better collision detection
- Performance improvements with cached DOM queries and Set data structure
- Bugfixes








How do I prevent this from conflicting with my HTML5 drag and drop?