[HTML/CSS] Offset Anchor Links Not Working on Mobile

Here is the code: https://codepen.io/rgilham/full/WNvryBP

I used an .anchor class on an <a> tag to account for offset from fixed header this seems to mostly work as expected on desktop (whatever codepen adds breaks it on desktop but using live server vs code extension it works), however on mobile it doesn’t work. My first thought was to use a @media query to provide a different offset for mobile, but changing the offset on the main anchor class seemed to have no effect even with numbers like 33% or -33%.

Any assistance is appreciated

try adding !important to @media query for the mobile view…i think that should work…

Unfortunately I can’t even get the main property to apply to mobile, setting to 33% or -33% breaks the desktop version (expected) but makes no change to anchor link behavior at all on mobile. If the property was seeming to work then I’d could write it into my @media inquires.

Hello! I’ve taken a look at the pen and notice that your element looks like
<a class="anchor" id="sec1"></a>

To me, it looks like you didn’t put anything in the element and are only using it for padding if I understand correctly?

When I take a look at your CSS I notice that the only reference you have towards .anchor is:

.anchor a {
    padding-top: 3.6%;

But this isn’t following the right CSS selector. W3 schools says:

.name1 .name2

Selects all elements with name2 that is a descendant of an element with name1

I think what you’re looking to do is have the padding-top apply to the .anchor class. If that’s so, you need to change your CSS styling rule to

.anchor a {
    padding-top: 3.6%;

Now that we have this out of the way, let’s get on to the fix of your problem (if I understand it!)

Anchor links (a tags) are inline elements. This means that they can’t have any padding. Super sad, I know. But fear not! CSS knew this could be a problem. In order to have padding on your a tag, you will just need to change your CSS to be inline-block

a {
    padding-top: 3.6%;

I hope this is everything you were looking for @rgil86

Thanks @caleb-mabry for trying to assist!

See this stack post for what I was trying to achieve:

I tried to implement your solution with display inline-block but it didn’t work either.

I think maybe the fault is mine for not being clear enough on what my issue is.

I Have 3 anchor links at top of the page, each one originally pointed to the section ID of each of my 3 sections.

However due to the fixed top nav bar all the anchor links were offset incorrectly.

For instance if you scroll to the very bottom of the page and then click the ‘About’ link rather then taking you to the very top slightly above the text ‘Dev-in-a-Box’ it stop further down and the H1 text is cut off unless the user manually scrolls up.

The solution I need is how to offset where anchor links travel to.

I port forwarded my live server extension so you can see exactly what I’m seeing and tryout and purposed solution.


Sorry it’s taken me so long to reply! I noticed that the stackoverflow article says that you should set the header to have a fixed height element. I went ahead and added it here.

#header {
    display: flex;
    align-items: center;
    top: 0;
    height: 60px;
    position: fixed;
    background-color: black;
    width: 100vw;

This will mean that you need to put a padding-top value of 60px to all of your .anchor

Working with the codepen that you’ve provided earlier, I see that you’re still using

.anchor a {
    padding-top: 3.6%;

This is not altering the <a> tag that has a class of .anchor.
To have the padding-top apply you just need to set the rule to be.

.anchor {
    padding-top: 3.6%;

Now, with all of these steps in motion, because we know the headers height is 60px this allows us to set the appropriate amount of padding-top to our .anchor class! The final CSS style should look like:

.anchor {
    padding-top: 60px; /*This value should equal the header height*/

Because these units are not responsive, you will probably have to add a media query to change the height of the header and the padding-top of the .anchor.

If you’re still having problems implementing this, just let me know. It seems to work on my end.

Happy coding!

Thanks a lot @caleb-mabry, between your last post and some more googling I figure out my issue.

When I first attempted your solution, the anchor still didn’t line up quiet right for me. I tried adding display: block; and visibility: hidden but I got giant gaps in the layout where the body showed through.

I had originally been trying to make things as responsive as possible by letting the header size it’s height according to the height of the logo img which was getting is height set by whatever ratio it was vs the width which was set width: 15vw;

Some more googling led me to try top: Xpx; instead of padding-top I ended up using this:

.anchor {
    display: block;
    position: relative;
    top: -96px;
    visibility: hidden;

Which worked perfectly! So I then tried to change it to top: -3.6%; however that didn’t work!?! Some more searching let me know the reason was the % calculation. It uses the absolute size of the parent element which for my anchor elements was <main> , which didn’t have a height set. I could however use -3.6vh, since that is not based on a parent element.

Unfortunately for me, my idea to size the nav-bar dynamically based on the logo height seems like it is more hassle then any possible benefit. I could use JS to find out the nav height and resize my offset’s dynamically, but I’d rather have a basic layout that doesn’t require JS. So I will just hard set the nav height and add some media queries.

Thanks again for the assist!

1 Like

That’s awesome. I had never even had this issue before but now I will know how to solve it later on down the road. Thanks for letting me know!! @rgil86

@caleb-mabry Sorry! I accidentally saved my previous response before I was finished, I have now added the details I was able to learn. Thank you!

Hey! The more knowledge that you share with everyone else will help us all to learn. Thanks again!