Skip to content

Commit 731d031

Browse files
antifuchsJoshua Nelson
authored and
Joshua Nelson
committed
Use scroll-padding-top to position anchors correctly in the viewport
This (fairly new) CSS attribute gets browsers that support it perfectly set up to skip the top nav bar. Unfortunately, Safari (both macOS and iOS) don't support it for this purpose yet, so we work around them in JS.
1 parent 364b5db commit 731d031

File tree

2 files changed

+38
-12
lines changed

2 files changed

+38
-12
lines changed

templates/rustdoc/page.html

+26-12
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,34 @@
3131
</body>
3232

3333
<script>
34-
var doc_body = document.getElementById("rustdoc_body_wrapper");
34+
// Reset the scroll offset on browsers that don't support
35+
// scroll-padding-top (Desktop & Mobile Safari):
36+
const maybeFixupViewPortPosition = function() {
3537
if (window.location.hash) {
36-
var notFirefox = typeof InstallTrigger === 'undefined';
37-
if (notFirefox) {
38-
var hash = window.location.hash;
39-
window.location.hash = "";
40-
setTimeout(function () {
41-
window.location.hash = hash;
42-
doc_body.focus();
43-
}, 1);
44-
}
45-
} else {
46-
doc_body.focus();
38+
const anchorElement = document.getElementById(window.location.hash.substr(1));
39+
const navBarHeight = document.getElementsByClassName("nav-container-rustdoc")[0].offsetHeight;
40+
if (anchorElement &&
41+
anchorElement.getBoundingClientRect().top <= navBarHeight &&
42+
Math.abs(anchorElement.getBoundingClientRect().top) >= 0) {
43+
// It's just overlapped by the nav bar. This can't be a coincidence, scroll it into view:
44+
requestAnimationFrame(function() {
45+
scrollBy(0, -navBarHeight);
46+
});
47+
}
4748
}
49+
};
50+
window.addEventListener("hashchange", maybeFixupViewPortPosition, false);
51+
// Fix up the scroll position if this was a direct visit to the page
52+
// (not back/forward navigation):
53+
if (window.performance) {
54+
const navEntries = window.performance.getEntriesByType('navigation');
55+
const usedBack = navEntries.length > 0 && navEntries[0].type === 'back_forward' ||
56+
(window.performance.navigation &&
57+
window.performance.navigation.type == window.performance.navigation.TYPE_BACK_FORWARD);
58+
if (!usedBack && window.location.hash) {
59+
window.addEventListener("scroll", maybeFixupViewPortPosition, {"once": true});
60+
}
61+
}
4862
</script>
4963

5064
</html>

templates/style.scss

+12
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,18 @@ body {
9292
margin: 0;
9393
// Since top navbar is fixed, we need to add padding to the body content.
9494
padding-top: $top-navbar-height;
95+
// The scroll padding on the <body> is necessary for Chrome
96+
// browsers for now (see
97+
// https://css-tricks.com/fixed-headers-on-page-links-and-overlapping-content-oh-my/
98+
// for an explanation)
99+
scroll-padding-top: $top-navbar-height;
100+
}
101+
102+
html {
103+
// Offset anchor jump targets down by this much, so they don't
104+
// overlap the top navigation bar (not supported on Desktop/Mobile
105+
// Safari yet):
106+
scroll-padding-top: $top-navbar-height;
95107
}
96108

97109
// this is a super nasty override for help dialog in rustdocs

0 commit comments

Comments
 (0)