JSFiddle - React, Tailwind, and code Playground
HTML
<div id="header"></div>
<div id="content">
<div class="side" id="stick"></div>
<div class="main"></div>
<div class="main"></div>
<div class="main"></div>
<div class="main"></div>
<div class="main"></div>
</div>
<div id="footer"></div>
<script>
CSS
body {
margin: 0;
padding: 10px;
}
#header {
height: 100px;
margin: 0 0 10px;
background: red;
}
#content {
position: relative;
float: left;
width: 100%;
height: auto;
margin: 0 -110px 0 0;
}
.side {
float: right;
width: 100px;
height: 900px;
margin: 0 0 0 10px;
background: linear-gradient(red, yellow);
}
.main {
height: 600px;
margin: 0 110px 10px 0;
background: lightgray;
}
#footer {
clear: both;
height: 100px;
background: orange;
}
CoffeeScript
$.fn.stickyTopBottom = (options = {}) ->
# only works in browsers that support CSS3 transforms (i.e. IE9+)
## ##############
#initialization
options = $.extend
container: $('body') #reference element for starting and stopping the sticking (doesn't actually have to contain the element)
top_offset: 0 #distance from top of viewport to stick top of element
bottom_offset: 0 #distance from bottom of viewport to stick bottom of element
, options
$el = $(this)
#Get the top of the reference element. If the container moves, would need to move this into scroll handler.
#If the container is translated Y, then this method will fail I believe.
container_top = options.container.offset().top
element_top = $el.offset().top
viewport_height = $(window).height()
$(window).on 'resize', ->
viewport_height = $(window).height()
## #################
# The meat: scroll handler
#
# When moving up or element is shorter than viewport:
# if scrolled above top of element, position top of element to top of viewport
# (stick to top)
# When moving down:
# if scrolled past bottom of element, position bottom of element at bottom of viewport
# (stick to bottom)
current_translate = 0
last_viewport_top = document.documentElement.scrollTop || document.body.scrollTop
$(window).scroll (event) ->
viewport_top = document.documentElement.scrollTop || document.body.scrollTop
viewport_bottom = viewport_top + viewport_height
effective_viewport_top = viewport_top + options.top_offset
effective_viewport_bottom = viewport_bottom - options.bottom_offset
# Need to reset element's height each scroll event because it may have change height
# since initialization.
# Warning: checking height is performance no-no
element_height = $el.height()
is_scrolling_up = viewport_top < last_viewport_top
...