17

I have used css to make a "sticky header" that is always visible at the top of the page and the other content placed below it. In the header I have some internal links. The problem is that when a link is clicked then the page is scrolled so that the target is positioned at the top of the page - hidden by my sticky header - instead of just below it.

Any suggestions on how to solve this problem?

css:

#header {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 3.5em;
    padding:0;
    margin: 0;
}

#container {
    width: 100%;
    margin: 3.5em 0 0 0;
    padding: 0;
    overflow:auto;
}

#content {
    padding: 0 4em;
    margin: 0;
}

html:

<body>

    <div id="header">
        <div id="content">
            <p>
                <a href="#xyz">XYZ</a>
            </p>
        </div> <!--end content-->
    </div> <!--end header-->

    <div id="container">
        <div id="content">
            <p>A lot of text.</p>
            <a name="xyz"></a>
            <p>A lot of text</p>
        </div><!--end content-->
    </div><!--end container-->

</body>
user635817
  • 181
  • 1
  • 7

7 Answers7

23

At first, it's better to use blocks with id instead of name — it's more standard way.

Then, add class to an anchor and then make it have absolute position + move it with a negative top margin equal to the header's height.

Look at this fiddle: http://jsfiddle.net/kizu/gfXJJ/

Or, alternatively, for browsers that support pseudo-elements, you can add one with the desired height and compensate it's height by negative top margin, so it would amount as the start of the block to which you'd make a link. Doing so you can add ids to already existent elements rather than creating extra ones.

Here is a version with pseudo-element: http://jsfiddle.net/kizu/gfXJJ/2/

Or you can add top padding and negative margin to an element with id itself: http://jsfiddle.net/kizu/gfXJJ/2/ — but in that case there can be problems with backgrounds on it, 'cause the block is physically extended at the top.

kizu
  • 42,604
  • 4
  • 68
  • 95
1

I believe this question overlaps the one in this link: offsetting an html anchor to adjust for fixed header which offers even more possible solutions. I believe the questions could be merged, but I don't have the priviliges to do that. (Which is the same reason I'm entering this as an answer allthough I know it should have been a comment. But I'm not allowed to comment.)

Community
  • 1
  • 1
1

A little bit of javascript (jQuery used here) can do it:

$('#header a').click(function (e) {
  e.preventDefault();

  var offset = $('a[name=' + $(this).attr('href').substr(1) + ']').offset();

  $('html, body').animate({ scrollTop: offset.top - $('#header').outerHeight() }, 'fast');
});

This finds the element with a name attribute that matches the href attribute of the link clicked, and then animates a scroll to that element's position less the height of the header.

http://jsfiddle.net/blineberry/bTa8b/

Brent
  • 2,961
  • 1
  • 17
  • 18
0

Pseudo elements don't appear to work in all scenarios. I had luck just applying a negative top margin and a positive top padding to offset to negative margin.

eg. <a id="xyz" style="margin-top:-50px; padding-top:50px">Title</a>

Eric Warnke
  • 1,325
  • 12
  • 18
0

One simple thing to do is to place the <a name="xyz"></a> slightly higher up the text.

This would require some trial and error, but it might be the quickest/easiest thing to do.


Another thing you could do is to dynamically add margin or padding when the link is clicked.

Jason Gennaro
  • 34,535
  • 8
  • 65
  • 86
0

You could also set a top-margin as high as the sticky header for your xyz-fragment in your CSS file. That might result in an empty gap in your result HTML-page though...

supertopi
  • 3,469
  • 26
  • 38
0

Start with getting unique ID's for the content part in the header and inside the container. Maybe you can put an ul inside the header for the internal links. Set the position of the content inside the wrapper absolute, et voila!

Is there any place we can get a look at your problem?

oceanmountain
  • 121
  • 2
  • 9