using affix in Bootstrap 4

In bootstrap 4 Dropped the Affix jQuery plugin.

So we need to manually ad the plugin component or use custom script to work affix feature in bootstrap 4. there are so many methods we can use for this.

but i recommend following script for the scenario. this is acctualy found from the bootstrap 3 version in github.

(function ($) {
'use strict';

// AFFIX CLASS DEFINITION
// ======================

var Affix = function (element, options) {
this.options = $.extend({}, Affix.DEFAULTS, options)

var target = this.options.target === Affix.DEFAULTS.target ? $(this.options.target) : $(document).find(this.options.target)

this.$target = target
.on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
.on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))

this.$element     = $(element)
this.affixed      = null
this.unpin        = null
this.pinnedOffset = null

this.checkPosition()
}

Affix.VERSION  = '3.4.0'

Affix.RESET    = 'affix affix-top affix-bottom'

Affix.DEFAULTS = {
offset: 0,
target: window
}

Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
var scrollTop    = this.$target.scrollTop()
var position     = this.$element.offset()
var targetHeight = this.$target.height()

if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false

if (this.affixed == 'bottom') {
if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
}

var initializing   = this.affixed == null
var colliderTop    = initializing ? scrollTop : position.top
var colliderHeight = initializing ? targetHeight : height

if (offsetTop != null && scrollTop <= offsetTop) return 'top' if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'

return false
}

Affix.prototype.getPinnedOffset = function () {
if (this.pinnedOffset) return this.pinnedOffset
this.$element.removeClass(Affix.RESET).addClass('affix')
var scrollTop = this.$target.scrollTop()
var position  = this.$element.offset()
return (this.pinnedOffset = position.top - scrollTop)
}

Affix.prototype.checkPositionWithEventLoop = function () {
setTimeout($.proxy(this.checkPosition, this), 1)
}

Affix.prototype.checkPosition = function () {
if (!this.$element.is(':visible')) return

var height       = this.$element.height()
var offset       = this.options.offset
var offsetTop    = offset.top
var offsetBottom = offset.bottom
var scrollHeight = Math.max($(document).height(), $(document.body).height())

if (typeof offset != 'object')         offsetBottom = offsetTop = offset
if (typeof offsetTop == 'function')    offsetTop    = offset.top(this.$element)
if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)

var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)

if (this.affixed != affix) {
if (this.unpin != null) this.$element.css('top', '')

var affixType = 'affix' + (affix ? '-' + affix : '')
var e         = $.Event(affixType + '.bs.affix')

this.$element.trigger(e)

if (e.isDefaultPrevented()) return

this.affixed = affix
this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null

this.$element
.removeClass(Affix.RESET)
.addClass(affixType)
.trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
}

if (affix == 'bottom') {
this.$element.offset({
top: scrollHeight - height - offsetBottom
})
}
}

// AFFIX PLUGIN DEFINITION
// =======================

function Plugin(option) {
return this.each(function () {
var $this   = $(this)
var data    = $this.data('bs.affix')
var options = typeof option == 'object' && option

if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
if (typeof option == 'string') data[option]()
})
}

var old = $.fn.affix

$.fn.affix             = Plugin
$.fn.affix.Constructor = Affix

// AFFIX NO CONFLICT
// =================

$.fn.affix.noConflict = function () {
$.fn.affix = old
return this
}

// AFFIX DATA-API
// ==============

$(window).on('load', function () {
$('[data-spy="affix"]').each(function () {
var $spy = $(this)
var data = $spy.data()

data.offset = data.offset || {}

if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
if (data.offsetTop    != null) data.offset.top    = data.offsetTop

Plugin.call($spy, data)
})
})

})(jQuery);

How it works

The affix plugin toggles between three classes: .affix.affix-top, and .affix-bottom. Each class represents a particular state. You must add CSS properties to handle the actual positions, with the exception of position:fixed on the .affix class.

    • The plugin adds the .affix-top or .affix-bottom class to indicate the element is in its top-most or bottom-most position. Positioning with CSS is not required at this point.

 

    • Scrolling past the affixed element triggers the actual affixing – This is where the plugin replaces the .affix-topor .affix-bottom class with the .affix class (sets position:fixed). At this point, you must add the CSS top or bottom property to position the affixed element in the page.

 

  • If a bottom offset is defined, scrolling past it replaces the .affix class with .affix-bottom. Since offsets are optional, setting one requires you to set the appropriate CSS. In this case, add position:absolute when necessary.

by kushan


avatar
1 Comment threads
1 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
2 Comment authors
kushanGayan Alahakoon Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
Gayan Alahakoon
Guest
Gayan Alahakoon

this article is helpful.Thank You 🙂