Don’t you hate it when you create an anchor link and it gets covered up by a fixed header? And isn’t it a bummer when the browser jumps to that link instantaneously all abrupt-like?
Well here’s a quick CSS snippet to create a lightweight, CSS based way to offset anchor links, and have them scroll smoothly:
html {
scroll-behavior: smooth;
}
:target:before {
content: "";
display: block;
height: 100px;
margin: -100px 0 0;
}
CSS Smooth Scroll
The scroll-behavior
is a CSS property that’s got some – but not full – browser support so you mileage will vary. My browser of choice, Safari, does not currently support this property, but I’ve implemented it on this site anyway. You can add it to an individual element, or enable site wide on html
.
Offset Anchors
There are quite a few offset anchor tutorials out there, but most target the :target
(heh heh heh) pseudo-class directly, hiding and moving it around. The only way this really works is to set the anchor on an additional element so you don’t lose the actual anchor you want to skip to. Something like this:
// Do not use this
:target {
display: block;
position: relative;
top: -100px;
visibility: hidden;
}
The key here is the additional :before
pseudo element. This allows you to keep the markup clean while still offsetting, and not have the target disappear.
Offset Smooth Anchor Demo
Click this link right here and you should be smoothly whisked to a section above. Unless you’re on Safari. So abrupt!
Bonus points to those who try it and can leave a comment about which section it links to.
13 Comments
Hey,
Granted, I know very little about CSS or any code, but it looks like you have given us an example snipet of what you are saying is not the best way, but haven’t given the example of what you suggest. Like you say, I have seen the above in many places. I still can’t get it to work.
Hi Lindsay. Sorry if I wasn’t clear, but the first method works for me (try this link) and is the one I recommend using. The second is just something that I found being posted quite a bit and its not recommended.
commenting to follow
Like Lindsay, I can’t get this to work. Refreshing the page gives different results. Sometimes scrolls too far and the offset doesn’t always apply.
If you’d like to post the code you’re using here or an example URL I’d be happy to take a quick look.
Awesome! Thanks for this Bryan :)
No problem Andrew!
Actually, I thought this was working but now it’s not. I have a position fixed header that has a height of 100px. I have a link within the first div following the header that has a link to a div with the id of “about” . When I click the anchor it isn’t adding the required 100px of space to offset the height of the header. Am I implementing this incorrectly?
html {
overflow-x: hidden;
overflow-y: auto;
scroll-behavior: smooth;
}
:target:before {
content: “”;
display: block;
height: 100px;
margin: -100px 0 0;
}
Do you have a URL I could take a look at?
Sure. https://boydells.oxwebdevelopment.com.au/ Click on the white arrow in the first section to scroll down :)
Hi Andrew. I’m not quite sure what you are expecting to happen… It seems to be working okay for me. Here’s a screen recording where it’s behaving as expected: https://share.getcloudapp.com/BluQkLvr
If you’re expecting something else, let me know – you an also jump on a chat during work hours Mountain time USA here: https://cinchws.com
Gday Bryan, thanks for your time. As currently coded, the scroll-to doesn’t scroll to the very top of the #about div including its top padding.
Hey Andrew. I think to get it the way you want it to work, you’ll need to move the target link inside the current div you’re targeting. Here’s what I mean: https://share.getcloudapp.com/yAuZd0Yp