/    Sign up×
Community /Pin to ProfileBookmark

In page “anchor” links

I have a fixed menu bar at the top of my page, say it’s 100px high.

In that menu I have links to content down the page, how can I get the anchor links to bring the content to the bottom of my menu bar.

<a href=”#sectionThree”>This Link</a>

<section id=”sectionThree”></section>

Currently it goes to the top of the window however my position fixed menu bar cover it.

Padding-top:100px; works but when scrolled it has a weird 100px white spce.

to post a comment
CSSHTMLJavaScript

16 Comments(s)

Copy linkTweet thisAlerts:
@SempervivumNov 19.2021 — Try to place your sections in an additional container. Links and anchors will still work. This is a demo I had on hand:
``<i>
</i>&lt;!doctype html&gt;
&lt;html lang="en"&gt;

&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"&gt;
&lt;title&gt;One Page Layout&lt;/title&gt;

&lt;style&gt;
html,
body {
height: 100%;
}

body {
margin: 0;
display: flex;
flex-direction: column;
font-family: arial;
}

header {
flex: 0 0 auto;
}

main {
flex: 1;
overflow-y: auto;
}

main&gt;section {
height: 100%;
}

footer {
font-size: 2em;
}

/* Nav */

nav ul {
list-style: none;
display: flex;
flex-direction: row;
}

nav ul li {
padding: 0.5em;
}
&lt;/style&gt;
&lt;/head&gt;

&lt;body&gt;
&lt;header&gt;
&lt;nav&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="#section1"&gt;Home&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#section2"&gt;Page 1&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#section3"&gt;Page 2&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#section4"&gt;Page 3&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/nav&gt;
&lt;/header&gt;
&lt;main&gt;
&lt;section id="section1"&gt;
Lorem ipsum dolor sit amet, ...
&lt;/section&gt;
&lt;section id="section2"&gt;
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu
feugiat ...
&lt;/section&gt;
&lt;section id="section3"&gt;
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer
possim assum...
&lt;/section&gt;
&lt;section id="section4"&gt;
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus
est Lorem ipsum dolor sit amet ...
&lt;/section&gt;
&lt;/main&gt;
&lt;footer&gt;This is the footer&lt;/footer&gt;
&lt;/body&gt;

&lt;/html&gt;<i>
</i>
``
Copy linkTweet thisAlerts:
@kiwisauthorNov 19.2021 — That works as the header isn't fixed. Make it fixed and it also fails
Copy linkTweet thisAlerts:
@SempervivumNov 19.2021 — Did you test the demo? The header **is** fixed and always visible. Only the content is shifting.
Copy linkTweet thisAlerts:
@kiwisauthorNov 19.2021 — yes, but this isn't "fixed" as I the menu actually sits below other content unless scrolled down

my menu bar is currently

position :fixed;

top: 120px;

Copy linkTweet thisAlerts:
@SempervivumNov 19.2021 — I see. The content above should be included in scrolling and should disappear when scrolling down. And the menu should scroll either but should stop scrolling when reaching the top of the viewport. I. e. the menu should be sticky in terms of CSS. Do I understand correctly?
Copy linkTweet thisAlerts:
@kiwisauthorNov 19.2021 — yeah that's it. So any other content to sit below. currently using padding but when manually scrolling I see big white spaces accommodating these link clicks
Copy linkTweet thisAlerts:
@SempervivumNov 19.2021 — In this case I would recommend to make use of javascript: Make the menu sticky by CSS and calculate the desired scroll position when a link is clicked taking into account the offset. Then scroll to that position.
Copy linkTweet thisAlerts:
@kiwisauthorNov 19.2021 — @Sempervivum#1639611

While you're right in this theory I can't see how to work it.

Option A: use an anchor link, however this defaults to the top of the view port. I can' see a way to override this in JS

Option B: Use JS scroll-to type feature however requires a specific point on the page but given content above any given point I'm connecting to is dynamic such as an article I don't know in advance where exactly on the page it will be. So I can't say scroll to 800px on the Y axis as it might be 1200 etc
Copy linkTweet thisAlerts:
@SempervivumNov 19.2021 — Yes, we have to calculate all positions and measurements dynamically by the script:
``<i>
</i>&lt;!doctype html&gt;
&lt;html lang="en"&gt;

&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"&gt;
&lt;title&gt;One Page Layout, Sticky Nav&lt;/title&gt;

&lt;style&gt;
body {
margin: 0;
display: flex;
flex-direction: column;
font-family: arial;
}

nav {
position: sticky;
top: 0;
}

main&gt;section {
/* height: 100%; */
height: 80vh;
}

footer {
font-size: 2em;
}

/* Nav */

nav ul {
list-style: none;
display: flex;
flex-direction: row;
}

nav ul li {
padding: 0.5em;
}
&lt;/style&gt;
&lt;/head&gt;

&lt;body&gt;
&lt;header&gt;
&lt;p&gt;This is the content above&lt;/p&gt;
&lt;p&gt;More content above&lt;/p&gt;
&lt;/header&gt;
&lt;nav&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="#section1"&gt;Home&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#section2"&gt;Page 1&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#section3"&gt;Page 2&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#section4"&gt;Page 3&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/nav&gt;
&lt;main&gt;
&lt;section id="section1"&gt;
Lorem ipsum dolor sit amet, ...
&lt;/section&gt;
&lt;section id="section2"&gt;
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu
feugiat ...
&lt;/section&gt;
&lt;section id="section3"&gt;
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer
possim assum...
&lt;/section&gt;
&lt;section id="section4"&gt;
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus
est Lorem ipsum dolor sit amet ...
&lt;/section&gt;
&lt;footer&gt;This is the footer&lt;/footer&gt;
&lt;/main&gt;
&lt;script&gt;
const
menu = document.querySelector('nav'),
menuBox = menu.getBoundingClientRect(),
// vertical space the menu or nav takes:
hSpace = menuBox.height;
document.addEventListener('click', event =&gt; {
// was a link in the nav clicked?
if (event.target.matches('nav a')) {
// prevent default action for this link:
event.preventDefault();
const
// get element we have to scroll to:
ele = document.querySelector(event.target.getAttribute('href')),
// get top position of the element relative to the viewport:
offsetEle = ele.getBoundingClientRect().top
// we have to add the scroll position in order to get
// the element's position relative to the document:
+ document.documentElement.scrollTop,
// space the menu requires has to be subtracted
// from the top offset of the element related to the document:
scrollAmount = offsetEle - hSpace;
document.documentElement.scrollTop = scrollAmount;
}
});
&lt;/script&gt;
&lt;/body&gt;

&lt;/html&gt;<i>
</i>
``
Copy linkTweet thisAlerts:
@kiwisauthorNov 19.2021 — Wow! Thanks but If I complicated this and made two sticky sections between a non sticky - is this still possible?

https://jsfiddle.net/nzkiwis/ae29f784/
Copy linkTweet thisAlerts:
@SempervivumNov 20.2021 — This can be achieved easily by wrapping all of the sticky content in one container:
``<i>
</i>&lt;body&gt;
&lt;header class="non-sticky"&gt;
&lt;p&gt;Non-sticky content above&lt;/p&gt;
&lt;p&gt;More content above&lt;/p&gt;
&lt;/header&gt;
&lt;header class="sticky"&gt;
&lt;h1&gt;The Headline Inside Sticky Header&lt;/h1&gt;
More content inside sticky header
&lt;nav&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="#section1"&gt;Home&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#section2"&gt;Page 1&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#section3"&gt;Page 2&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#section4"&gt;Page 3&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/nav&gt;
&lt;/header&gt;
&lt;main&gt;<i>
</i>
`</CODE>
Then make this container sticky:
<CODE>
`<i>
</i> header.sticky {
position: sticky;
top: 0;
}<i>
</i>
`</CODE>
And adjust the javascript:
<CODE>
`<i>
</i> const
stickyHeader = document.querySelector('header.sticky'),
stickyHeaderBox = stickyHeader.getBoundingClientRect(),
// vertical space the menu or nav takes:
hSpace = stickyHeaderBox.height;
document.addEventListener('click', event =&gt; {
// was a link in the nav clicked?
if (event.target.matches('nav a')) {
// prevent default action for this link:
event.preventDefault();
const
// get element we have to scroll to:
ele = document.querySelector(event.target.getAttribute('href')),
// get top position of the element relative to the viewport:
offsetEle = ele.getBoundingClientRect().top
// we have to add the scroll position in order to get
// the element's position relative to the document:
+ document.documentElement.scrollTop,
// space the menu requires has to be subtracted
// from the top offset of the element related to the document:
scrollAmount = offsetEle - hSpace;
document.documentElement.scrollTop = scrollAmount;
}
});<i>
</i>
``

https://jsfiddle.net/Sempervivum/ne5gt79w/1/
Copy linkTweet thisAlerts:
@kiwisauthorNov 20.2021 — Not really because once scrolling I want the content between the top and lower sticky elements to disappear (just to save space)
Copy linkTweet thisAlerts:
@SempervivumNov 20.2021 — You intend to have HTML like this:
``<i>
</i>&lt;header class="non-sticky"&gt;
Content is not sticky
&lt;/header&gt;
&lt;header class="sticky"&gt;
First block of sticky content
&lt;/header&gt;
&lt;section class="non-sticky"&gt;
Another block which is not sticky
&lt;/section&gt;
&lt;section&gt;
Second block of sticky content
&lt;/section&gt;<i>
</i>
``

?

This would be possible but would grow fairly complex. I do not recommend doing this.
Copy linkTweet thisAlerts:
@SempervivumNov 20.2021 — Just for fun I implemented this and it was easier than I expected.

HTML:
``<i>
</i> &lt;header class="non-sticky"&gt;
&lt;p&gt;Non-sticky content above&lt;/p&gt;
&lt;p&gt;More content above&lt;/p&gt;
&lt;/header&gt;
&lt;h1 class="sticky"&gt;Sticky Headline&lt;/h1&gt;
&lt;section class="non-sticky"&gt;
&lt;p&gt;More non-sticky content&lt;/p&gt;
&lt;/section&gt;
&lt;nav class="sticky"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="#section1"&gt;Home&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#section2"&gt;Page 1&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#section3"&gt;Page 2&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="#section4"&gt;Page 3&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/nav&gt;<i>
</i>
`</CODE>
JS:
<CODE>
`<i>
</i> const
sticky1 = document.querySelector('h1.sticky'),
sticky1Box = sticky1.getBoundingClientRect(),
sticky2 = document.querySelector('nav.sticky'),
sticky2Box = sticky2.getBoundingClientRect(),
// vertical space the menu or nav takes:
hSpace = sticky1Box.height + sticky2Box.height;
// sticky position for 2nd sticky element:
sticky2.style.position = 'sticky';
sticky2.style.top = sticky1Box.height + 'px';
// not modified below this line:
document.addEventListener('click', event =&gt; {
// was a link in the nav clicked?
if (event.target.matches('nav a')) {
// prevent default action for this link:
event.preventDefault();
const
// get element we have to scroll to:
ele = document.querySelector(event.target.getAttribute('href')),
// get top position of the element relative to the viewport:
offsetEle = ele.getBoundingClientRect().top
// we have to add the scroll position in order to get
// the element's position relative to the document:
+ document.documentElement.scrollTop,
// space the menu requires has to be subtracted
// from the top offset of the element related to the document:
scrollAmount = offsetEle - hSpace;
document.documentElement.scrollTop = scrollAmount;
}
});<i>
</i>
``

https://jsfiddle.net/Sempervivum/9adqL2uw/1/
Copy linkTweet thisAlerts:
@kiwisauthorNov 20.2021 — Wow, I've never heard of the getBoundingClientRect method before.

So in short, calculating the height of the two sticky elements.

Finding the element with the ID which equals the clicked hyperlink. The scrolling to top setting that value.

Simple but very clever. Thank you.
Copy linkTweet thisAlerts:
@kiwisauthorNov 20.2021 — I should add- while your example wasn't exactly what I needed I've been able to modify it perfectly to suit.
×

Success!

Help @kiwis spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 4.25,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,

tipper: @Samric24,
tipped: article
amount: 1000 SATS,
)...