Skip to content

Instantly share code, notes, and snippets.

@AchalJ
Last active July 1, 2020 19:08
Show Gist options
  • Save AchalJ/02221283deb5ff7e9c07f3c7ec70f04e to your computer and use it in GitHub Desktop.
Save AchalJ/02221283deb5ff7e9c07f3c7ec70f04e to your computer and use it in GitHub Desktop.
jQuery Extension to make an element sticky on scroll
/**
* Sticky 1.0.0
* https://github.com/AchalJ
*
* Copyright (c) 2020 Achal Jain
*
* Licensed under the MIT License
*/
(function(factory) {
if ( typeof define === 'function' && define.amd ) {
// AMD. Register as an anonymous module.
define( ['jquery'], factory );
} else if ( typeof module === 'object' && module.exports ) {
// Node/CommonJS
module.exports = function ( root, jQuery ) {
if ( jQuery === undefined ) {
if ( typeof window !== 'undefined' ) {
jQuery = require( 'jquery' );
} else {
jQuery = require( 'jquery' )( root );
}
}
factory(jQuery);
return jQuery;
};
} else {
// Browser globals
factory(jQuery);
}
}(function($) {
$.fn.sticky = function (options) {
if ( 'string' === typeof options && 'destroy' === options ) {
return this.each(function() {
var $this = $(this);
if ( $this.parent().hasClass( 'element-sticky--wrapper' ) ) {
$this.unwrap();
$this
.removeClass( $this.data( 'sticky-class' ) )
.removeAttr( 'data-sticky-class' )
.removeAttr( 'style' );
} else {
throw Error( 'Cannot destroy before initializing sticky element.' );
}
});
}
var options = $.extend({
offsetY: 0,
zIndex: 99,
outerWidth: false,
cssClass: 'element-sticky'
}, options);
return this.each(function() {
var $this = $(this);
$this.attr( 'data-sticky-class', options.cssClass );
var width = options.outerWidth ? $this.outerWidth() : $this.width(),
height = $this.outerHeight(),
marginTop = parseFloat( $this.css('margin-top') ),
marginBottom = parseFloat( $this.css('margin-bottom') ),
position = $this.prop('style').position,
top = $this.prop('style').top,
offsetTop = $this.offset().top;
var offsetY = ! isNaN( parseFloat( options.offsetY ) ) ? parseFloat( options.offsetY ) : 0,
cssClass = options.cssClass;
$this.wrapAll('<div />').parent().addClass('element-sticky--wrapper').css({
'height': height,
'margin-bottom': ! isNaN( marginBottom ) ? marginBottom : 'auto',
});
$(window).on('scroll', function() {
if ( ! $this.parent().hasClass('element-sticky--wrapper') ) {
return;
}
var scrollY = $(window).scrollTop() + offsetY;
scrollY += ! isNaN( marginTop ) ? marginTop : 0;
if ( scrollY >= offsetTop ) {
$this.css({
position: 'fixed',
top: offsetY + 'px',
width: width + 'px'
});
if ( options.zIndex && ! isNaN( parseInt( options.zIndex ) ) ) {
$this.css( 'z-index', parseInt( options.zIndex ) );
}
if ( ! $this.hasClass( cssClass ) ) {
$this.addClass( cssClass );
}
} else {
$this.css({
position: '' !== position ? position : 'static',
top: '' !== top ? top : offsetY + 'px'
});
if ( $this.hasClass( cssClass ) ) {
$this.removeClass( cssClass );
}
}
});
});
};
}));
@AchalJ
Copy link
Author

AchalJ commented Jul 1, 2020

How to use:
jQuery('<element>').sticky({ offsetY: 32 })

Available options:
offsetY (numeric) - Additional vertical offset | default: 0
zIndex (numeric) - z-index to make element appear top of other elements | default: 99
outerWidth (boolean) - whether to use element's outerWidth | default: false
cssClass (string) - a custom CSS class to apply | default: element-sticky

Destroy
jQuery('<element>').sticky('destroy')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment