33

I'm currently building a webpage where some elements are placed on fixed positions near the top edge. So whenever I navigate to anchors, those get placed right under those fixed elements. I wonder if there's some style or other method that when navigating to a anchor, this happens with some additional offset/margin?

Example source code

<html>
<body>

<div style="position:fixed; top:0px; height:100px; background:white;">
This covers the top 100px of the screen.
</div>

<div style="position:absolute; top:0px;">

<div>
<a name="foo" id="foo"><h2>Foo</h2></a>
<p>
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam
nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
sed diam voluptua. 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. Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam
erat, sed diam voluptua. At vero eos et accusam et justo duo dolores e
ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem
ipsum dolor sit amet.
</p>
</div>

<div>
<a name="bar" id="bar"><h2>Bar</h2></a>
<p>
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse
molestie consequat, vel illum dolore eu feugiat nulla facilisis at
vero eros et accumsan et iusto odio dignissim qui blandit praesent
luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam
nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat
volutpat.   
</p>
</div>

</div>

</body>
</html>

Say this HTML is available at http://example.com/foobar.html one could link to http://example.com/foobar.html/#bar – a browser will scroll to the anchor named/id "bar". But in this example there's that 100px high fixed element, that will obstruct the upper parts of the "Bar" contents. Now I'd like to have some style/option that tells the browser, not to scroll the element to the top of the document window, but to leave a certain "scroll margin" (in this case a scroll margin of about 200px). This is not about element margins, as these influence the layout. But this is not about layout, but giving hints for the scrolling behaviour.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • 1
    I don't understand this question, can you show us your work? Either by linking us to your page or making a temporary example at jsfiddle.net :) – Kyle Feb 21 '11 at 20:16
  • 2
    Have a look at my answer over there: http://stackoverflow.com/a/9506604/143684 – ygoe Feb 29 '12 at 21:07

3 Answers3

29

In order to get a cross-browser/cross-device solution where your anchor is truly invisible in the sense that it does not take up any space on the page, it is important that you format your anchor tag like this:

<a name="foo" class="top"></a>

We used a class so you can style all of your anchor tags at once, (assuming the fixed div is part of your normal page template)... you could set it as an ID as the question poses though.

And format your CSS as follows:

a.top {
position: relative;
top:-100px;
display: block;
height: 0;
width:0;
}

Using Position: relative allows you to pull the anchor our of the normal page flow.

setting the top to a negative dimension that equals the height of your fixed element will push the content you are jumping to into full view.

Browsers such as Chrome do not respect this positioning unless the anchor actually displays. Adding content to the anchor such as &nbsp; will force the anchor to display but in many instances that would create a vertical space as big as the line-height of the <a>, so it is better to set the display to block and the width and height to 0.

pathfinder
  • 1,606
  • 18
  • 22
  • Good solution. On Safari on iOS 7-something it does not quite cut it, though. Flawless on Chrome on iOS. – fcar Sep 17 '14 at 19:35
  • good to know, thanks. Can you elaborate on what it does not cut? I would be happy to update answer with a solution for iOS 7. – pathfinder Sep 17 '14 at 21:05
  • The first time only one hits the the link, and safari jumps to the named anchor, it seems not to consider the top value. The stuff I want to be below my fixed navbar thus end up partially buried beneath it. Mind you, the *second* time it seems to always work in the intended way. Also, the first time it could very well be ignoring *all* of the CSS, I don't know. In Chrome, as I said, it just works with the exact same code served. – fcar Sep 18 '14 at 04:40
  • Addendum: in Safari, for each of the links pointing to a named anchor, the *first time* it fails. The second time all is well. If I hit another anchor on the same page (not reloaded), hitherto untouched by human hands, the same thing happens: first time fails, second and following succeeds. I shall debug my client side code to see that the problem indeed lies with the above solution - this is far from certain. – fcar Sep 18 '14 at 08:14
  • Addendum secundum (or something): I rather think there's something amiss with my client code. To be sure, something is amiss with the way Safari handles the above solution as well, but my code being in the way of all the trees, it isn't easy to tell exactly what must be fixed (if you understand my mixed metaphors). – fcar Sep 18 '14 at 08:32
  • ok, I will do some testing too. Just gotta get something with iOS7 on it. Have you considered that it may be failing because of the address bar being part of the height until you scroll? – pathfinder Sep 18 '14 at 15:05
12

Here is my solution: http://jsfiddle.net/ufewB/

HTML

<div id="container">
    <div id="fixed">
        Fixed position element
        <a href="#foo" alt="foo">Jump to foo</a>   
    </div>
    <div id="spacer"></div>
    <a id="foo"></a><h2>Foo</h2>

    <p>Lorem ipsum text</p>
    <div id="spacer"></div>
</div>

CSS

#fixed {
    position:fixed;
    top:0;
    left:0;
    width:100%;
    height:100px;
    background-color:red;
}
#spacer { height:800px; }
* { margin:0px; padding:0px; }
#container { width:960px; margin:auto; }
#foo { position:relative; top:-100px; }

Basically, I gave the <a id="foo">&nbsp;</a> the CSS position:relative; top:-100px and I took all the elements contained inside the anchor and put them next to the anchor instead. I did this because you are in essence creating an invisible link, removing it from the normal document flow, and positioning it 100px higher than it would normally be.

Doing it this way, when the page places the hash link at the top of the page, whatever content was next to the link will be 100px lower. Additionally, another benefit of doing it this way is you don't have to mess with tweaking the flow of the document; you're just changing the flow of an invisible anchor tag, which makes maintenance much easier

datenwolf
  • 159,371
  • 13
  • 185
  • 298
Moses
  • 9,033
  • 5
  • 44
  • 67
1

scroll-margin-top is a good solution now (2022)

dras
  • 138
  • 4
  • 14