# Setting header color on scroll for each post

On this site this site, I have some code which you can see below which figures out the offset for each post from the top of the document and assigns a colour from each post to the header when it scrolls into view. I am having to wait for the window load event until the code works which really is not very elegant. Can anyone see how I can improve this code?

$(window).load(function() { var$header = $("header"); var numberOfSections =$("section").length;
var sectionOffsets = [];

for(var i = 0; i < numberOfSections; i++) {
sectionOffsets.push($("section").eq(i).offset().top); }$(window).scroll(function () {
$("section").each(function () { if ($(window).scrollTop() > $(this).offset().top - 180) {$("header").css('color', $(this).data("colour")); } }); }).scroll(); });  • What's the point of $header, numberOfSections, and sectionOffsets? – 200_success May 24 '15 at 10:50
• What's wrong with load event for you? – smt May 24 '15 at 21:00
• The load event is not very good as there are a lot of images on the page and the function does not work until all of the images are loaded – 2ne May 25 '15 at 15:24

jsBin demo

Instead of storing section positions on window onload time, which can be always kind of inaccurate since your images might still load...

get dynamically the current position / size data of an element using:

element.getBoundingClientRect()

using that JS method you don't even need to calculate the $(window).scrollTop() cause the returned value is the element's position respective to the client top (viewport top edge). To retrieve only the one element that matches a top criteria you can use the jQuery's .filter() method and return the element which... $section.filter(function(){
var r = this.getBoundingClientRect();
return  r.top + r.height - 100  > 0; // ...matches this
})


(100 is the header height in this demo; set as desired or calculate dynamically)

Now, since jQuery filtered more than one element that matches that criteria of (gbcr.top + gbcr.height - headeroffser) > 0 by going directly to chain another method to it like .data(), the value will be respective to the first of elements returned in the .filter() collection:

$header.css({ color :$section.filter(function(){
var r = this.getBoundingClientRect();
return  r.top + r.height - 100 > 0;
}).data().colour // is the colour data of the first of filtered elements
});


Store that colouring stuff inside a setScrollColors function and use like:

$(function() { // DOM ready shorthand var$header  = $("header"); // Cache selectors var$section = $("section"); function setScrollColors() {$header.css({
color : $section.filter(function(){ var r = this.getBoundingClientRect(); return r.top + r.height - 100 > 0; }).data().colour }); } setScrollColors(); // Call inside dom ready$(window).on("load scroll", setScrollColors); // call also on load and scroll

});
*{margin:0;}
position:fixed;
z-index:1;
top:0;
width:100%;
background:#f9f9f9;
height:100px;
border-bottom:1px solid currentColor;
}
#content{
margin-top:100px;
}
section{
min-height: 1000px;
min-height: calc(100vh - 100px);
border-top:1px solid #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</div>