16

There've been a few similar posts (offsetting an html anchor to adjust for fixed header, for example), but those solution doesn't work for my particular case.

I am using jQuery to populate a Table of Contents, specifically the method described here: http://css-tricks.com/automatic-table-of-contents/. It searches for the h2 tags within the article, and then creates anchors links.

The problem is I'm using a fixed header. When I click on one of these anchor links, the target h2 is underneath the header. One temporary solution I'm using is:

h2:target{
  padding-top:[header-height];
}

This works until you scroll back up, and there's a huge gap in the middle of the content. Do y'all have any ideas on how I can offset these anchor links to account for the header? I'd like to keep the HTML as semantic as possible. Any help would be appreciated.

Here's a jsFiddle of what exactly I'm talking about: http://jsfiddle.net/aweber9/GbNFv/

Thanks.

Community
  • 1
  • 1
aaronweber
  • 185
  • 1
  • 1
  • 6

5 Answers5

45

You could include padding-top and then use negative margin-top to balance it out.

jsFiddle

h2 {
    padding-top: 70px;
    margin-top: -70px;
}
Daniel Imms
  • 47,944
  • 19
  • 150
  • 166
  • This is exactly what I was trying to do. Can't believe it was that simple. Thanks, man. – aaronweber Mar 31 '13 at 06:10
  • I just found that this can cause display issues in Firefox. I have a lot of

    anchors on a page with submit buttons. The minus margins prevent some of the submit buttons from being clicked as they 'overlap' the submit button elements.

    – AfromanJ Sep 06 '13 at 09:06
  • This works like a charm in Chrome and Firefox, but is there an IE-friendly solution? Doesn't work in IE8, IE9 or IE10 for me. It's possible this is due to some other code of course but if anyone has insight... – Ennui Sep 11 '13 at 19:27
  • I've found this works some of the time, but can cause layout issues in other situations. In those situations, try [this answer](https://stackoverflow.com/a/65016689/884640) – floer32 Jun 19 '22 at 03:37
17

Well. I had this issue as well. The best and fastest solution I could find here is to use the following code snippet in your Style tag or CSS file.

html
{
  scroll-padding-top: 12vw; /* height of sticky header */
}
iWiiCK
  • 361
  • 5
  • 13
9

@Daniel Imms solution is good but if headers had top margin it would be reset by this negative top margin. I found a solution that uses pseudoclasses:

h2:before {
    display: block;
    content: " ";
    height: 20px;  /* Give height of your fixed element */
    margin-top: -20px; /* Give negative margin of your fixed element */
    visibility: hidden;
}

Thus this doesn't reset original top-margin.

jstice4all
  • 1,878
  • 4
  • 22
  • 33
  • Thank you very much! This should be upvoted, since this does also work on mobile browsers (chrome, safari) whereas padding/margin-only does not work on mobile. – Grimm Nov 15 '22 at 11:58
2

I find both answers together provides the most robust solution across multiple browsers. I include both in my CSS...

a[name]:not([href]) {
    padding-top: 90px;
    margin-top: -90px;
}
a[name]:not([href]):before {
    display: block;
    content: " ";
    padding-top: 90px;
    margin-top: -90px;
    visibility: hidden;
}
Bryan
  • 41
  • 3
2

This worked for me.

:target {
    display: block;
    position: relative;
    top: -100px;
    visibility: hidden;
}
Nealio
  • 21
  • 2