Sticky Header and Anchored Sections SASS Mixin

If you have a sticky header on a site and stacked anchored sections (probably what that header’s links scroll to), you may have run into the problem where loading the url with the hash of a section displays that section at the top of the browser but the sticky header overlaps it.

When I searched for some solutions for this I found that they generally involved attaching a span or pseudo element inside the anchored section and giving it a height and negative top margin equal to the height of the sticky header.  (If you’re not familiar with this, you can read more about the thinking about it here: https://css-tricks.com/hash-tag-links-padding/).

One potential problem with this solution, though, is that the span/pseudo element overlaps the bottom of the section above it so that the user can’t click anything in that area.  If you go here and scroll up above the anchored section, you can see that you can’t highlight any text in the bottom of the section above it.  That’s because an invisible element is overlapping that content.  This would probably not be an issue if the un-clickable section is just text, but there could be links in there.

What makes more sense to me is to give each anchored section a lower z-index than the section before it.  That way the section before it is still clickable.  And, less importantly, just add some top padding equal to the height of the sticky header for each section.  (I also had to overcome an issue in Firefox when I first started this by adding display:inline-block and width:100% to .page-section to make them overlap each other.  So maybe those declarations will not be needed in the future.)

The CSS of cascading z-index values would be tedious to write with css because it would look something like…

.page-section {
    display: inline-block;
    width: 100%;
    position: relative;
    padding-top: 51px;
    margin-top: -51px;
}
.page-section {
    z-index: 7
}
.page-section+.page-section {
    z-index: 6
}
.page-section+.page-section+.page-section {
    z-index: 5
}
.page-section+.page-section+.page-section+.page-section {
    z-index: 4
}
.page-section+.page-section+.page-section+.page-section+.page-section {
    z-index: 3
}
.page-section+.page-section+.page-section+.page-section+.page-section+.page-section {
    z-index: 2
}
.page-section+.page-section+.page-section+.page-section+.page-section+.page-section+.page-section {
    z-index: 1
}

Here’s a SASS solution that looks nicer, is faster to write/update, and renders the same thing:

$siblings: 7;
$class: '.page-section';
$sel: '';
$offset: 51px;
#{$class} {
	display: inline-block;
	width: 100%;
	position: relative;
	padding-top: $offset;
	margin-top: $offset*-1;
}
@for $i from 0 to $siblings {
	$sel: if($sel == '', $class, $sel + ' + ' + $class);
	#{$sel} {
		z-index: $siblings - $i;
	}
}

Done!