If I have a non-scrolling header in an HTML page, fixed to the top, having a defined height:
Is there a way to use the URL anchor (the #fragment
part) t
I think this approach is more useful:
<h2 id="bar" title="Bar">Bar</h2>
[id]:target {
display: block;
position: relative;
top: -120px;
visibility: hidden;
}
[id]:target::before {
content: attr(title);
top: 120px;
position: relative;
visibility: visible;
}
If you can’t or don’t want to set a new class, add a fixed-height ::before pseudo-element to the :target pseudo-class in CSS:
:target::before {
content: "";
display: block;
height: 60px; /* fixed header height*/
margin: -60px 0 0; /* negative fixed header height */
}
Or scroll the page relative to :target
with jQuery:
var offset = $(':target').offset();
var scrollto = offset.top - 60; // minus fixed header height
$('html, body').animate({scrollTop:scrollto}, 0);
I'm using @Jpsy's answer, but for performance reasons I'm only setting the timer if the hash is present in the URL.
$(function() {
// Only set the timer if you have a hash
if(window.location.hash) {
setTimeout(delayedFragmentTargetOffset, 500);
}
});
function delayedFragmentTargetOffset(){
var offset = $(':target').offset();
if(offset){
var scrollto = offset.top - 80; // minus fixed header height
$('html, body').animate({scrollTop:scrollto}, 0);
$(':target').highlight();
}
};
Implemented using :before
worked great until we realized that the pseudo element was actually covering and blocking pointer events that sat within the pseudo element's area. Using something like pointer-events: none
on the :before
or even directly on the anchor had no affect.
What we ended up doing was making the anchor's positioning absolute and then adjusting it's position to be the offset/height of the fixed area.
Offset Anchor without Blocking Pointer Events
.section-marker {
position: absolute;
top: -300px;
}
The value with this is that we're not blocking any elements that might fall within those 300px. The downside is that grabbing that element's position from Javascript needs to take into account that offset so any logic there had to be adjusted.
You can do this with jQuery:
var offset = $('.target').offset();
var scrollto = offset.top - 50; // fixed_top_bar_height = 50px
$('html, body').animate({scrollTop:scrollto}, 0);
Just discovered another pure CSS solution that worked like a charme for me!
html {
scroll-padding-top: 80px; /* height of your sticky header */
}
Found on this site!