offset scroll to in html? - html

I am trying to do the thing in html where you click on a link and it automatically scrolls to where you want in the page. Here is the button/link part of the code:
<li>Origins</li>
And then I have it link to this part of the page represented by this code:
<h3 id="Origins">Origins</h3>
This works perfectly fine, however, my header of the page at the top, which is h1, is set to fixed position.
So when you click the link, it goes too far down to where the header at the top is covering the "origins"
part of the page. I tried adding padding to the top of origins which works but then there is a lot of blank space
above "origins" in the page which I do not want. Does anyone have any ideas? Thanks in advance!

scroll-margin-top did the trick for me.
<h1>Heading</h1>
<ul><li>Origins</li></ul>
<div class="space"></div>
<h3 id="Origins" style="scroll-margin-top: 7em;">Origins</h3>
Source: https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-margin-top

You could do it with Javascript(example below requires jQuery, but could also be accomplished with Vanilla Javascript) by scrolling to the position of the h3 minus the height of the h1:
$(function() {
var h1Height = $('h1').height(); // get height of h1 tag
$('li a').click(function (e) {
e.preventDefault();
var target = $(this.hash);
$('html, body').animate({
scrollTop: target.offset().top - h1Height // scroll to h3 minus height of h1
}, 1000);
return false;
});
});
body,html {
margin:0;
padding:0;
}
h1{
margin:0;
padding:0;
width:100%;
background:#fff;
position:fixed;
top:0;
}
ul {
margin:60px 0 0;
}
.space, h3 {
margin:1000px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Heading</h1>
<ul><li>Origins</li></ul>
<div class="space"></div>
<h3 id="Origins">Origins</h3>

You can use scroll-margin-top.
h3[id] {
scroll-margin-top: 2rem;
}
Visit https://css-tricks.com/fixed-headers-and-jump-links-the-solution-is-scroll-margin-top/

I generally put an anchor where it's semantically correct, give it position relative, and push it up by the height of the header plus a few px.

Related

Jump to a specific part of page

I've experimented with a simple "feature" on my Shopify theme, where I want a link to jump to a specific part of the page - quite simple, and I've done it like this.
Jump to section
<span id="jumpto">The section i want to jump to</span>
It works like a charm, but! I have a sticky header, where the "The section i want to jump to" is hidden behind. Is there any way, with css, push it a bit down down, so "The section I want to jump to" is shown, right beneath the header.
Basically I want the span element to appear for example 50px beneath the header.
My setup looks something like this
<div id="sectiona">
</div>
<span id="jumpto">The section i want to jump to</span>
<div id="sectionb">
</div>
If i use margin og padding, the gab between would be to big.
You can use JavaScript to solve your problem and make smooth scrolling as well.
$('a[href*="#"]').click(function(){
$('html, body').animate({
scrollTop: $( $(this).attr('href') ).offset().top - 50
}, 500);
return false;
});
This might not the prettiest solution, but it should do the trick. By having an empty span (.jump-marker) acting as the jumping point you can offset the position where the anchor jumps to.
.jump-marker {
position: absolute;
margin: -120px 0 0;
}
You could also use JS/jQuery to offset the scroll distance by your header height and also allow smooth scrolling, which is much more pleasing to the eye, but that wasn't asked for! :)
Example:
body {
padding-top: 120px;
}
header {
position: fixed;
top: 0;
left: 0;
right: 0;
background: rgba(255,0,0,0.25);
height: 100px;
}
.more-content {
height: 1000px;
background: #f7f7f7;
}
section {
position: relative;
}
.jump-marker {
position: absolute;
margin: -120px 0 0;
}
<header></header>
Jump to section
<div class="more-content"></div>
<section>
<div class="section-content">
<span id="jumpto" class="jump-marker"></span>
The section i want to jump to
</div>
</section>
<div class="more-content"></div>
I make a basic header fixed and made the links tag link offset from the place I want to link too. This solution is really rough but can work with good CSS and placing
html:
<div class="jumpTo">
<a id="0">0</a>
</div>
<h2>0</h2>
css:
.jumpTo{
margin-bottom: 100px;
font-size: 0;
}
https://jsfiddle.net/ovcx2t9z/
or a fiddle based on the Jquery solution
You can use JavaScript to solve your problem and make smooth scrolling as well.
$('a[href*="#"]').click(function(){
$('html, body').animate({
scrollTop: $( $(this).attr('href') ).offset().top - 50
}, 500);
return false;
});
https://jsfiddle.net/qy03xb1r/2/
How is the page layed out? Have you tried using padding or margin adjustments like.. padding-top:50px; or margin-top:50px.

Div doesn't follow the pointer

I have a div that is supposed to follow the pointer, but it stays very far from the pointer right now, though it follows it.
I've tried some different codes, both written by me, suggested on here, or found online, but nothing helped.
Right now the one that works best is this..
var currentMousePos = { x: -1, y: -1 };
$(document).mousemove(function(event) {
currentMousePos.x = event.pageX;
currentMousePos.y = event.pageY;
$(".hidden-img").css('top', currentMousePos.y);
$(".hidden-img").css('left', currentMousePos.x);
});
I've also tried this http://jsfiddle.net/BfLAh/1/ but it doesn't work as in the fiddle
It follows the pointer but it's very far from the top left of the pointer.
I have managed to go with this code and make it work, at least the positioning
$(document).ready(function() {
$(".list-item").mousemove(function(e) {
var offset = $(".list-item").offset();
$("#hoverDisplay").animate({
left: e.pageX - offset.left,
top: e.pageY - offset.top
}, 1);
});
});
Now the only problem that stays is, I have 20+ "li" items that have to get hovered and show their own hidden div.
Here is the code of just 2 "li" elements.
<li class="list-item" style="background-color: #03C0A4;">
<div class="small-title" style="color:#E07354">nevaly</div>
<a href="a-project-called/nevaly/index.html" style="color:#E07354" class="project-title" onmouseenter=toggleHiddenDisplay("hoverDisplay") onmouseout=toggleHiddenDisplay("hoverDisplay")>Connecting brands and influencers - no limits.</a>
<div class="hidden-img" id="hoverDisplay" style="display:none;">
<img src='a-project-called/nevaly/thumb.gif'>
</div>
</li>
<li class="list-item" style="background-color: #f8e975;">
<div class="small-title" style="color:#e32e1d">Kulturhavn</div>
<a href="a-project-called/kulturhavn/index.html" style="color:#e32e1d" class="project-title" onmouseenter=toggleHiddenDisplay("hoverDisplay") onmouseout=toggleHiddenDisplay("hoverDisplay")>Ahoy! From the cultural harbour of Copenaghen.</a>
<div class="hidden-img" id="hoverDisplay" style="display:none;">
<img src='a-project-called/kulturhavn/thumb.gif'>
</div>
</li>
Now when I hover just the first hidden div content gets shown.
How can I take the hoverDisplay of the hovered "li" element using the JS that I wrote (thanks to you also guys!)?!
Thanks
If you want to match the position of image's top left corner and mouse pointer, then jsut set negative margin-top, and margin-left for you image like below:
$(document).ready(function () {
$("body").mousemove(function (e) {
$("#image").animate({
left: e.pageX,
top: e.pageY
}, 1);
});
});
body {
overflow:hidden;
position:absolute;
height:100%;
width:100%;
background:#efefef;
}
#image {
height:50px;
width:50px;
margin-top:-10px;
margin-left:-10px;
position:absolute;
}
<div id="container">
<img id="image"></img>
</div>
Here is its link to check it online in fiddle.
UPDATE
If your only reason for detecting mouse position is to show and hide the content of list items, then you don't need to detect mouse position manually, you can do it using jQuery with ease. First add this selector to your CSS file:
li.list-item div {
display: none;
}
And then you can show child of each .small-item using mouseover and children like below:
$(document).ready(function() {
$('.list-item').mouseover(function() {
$(this).children('.small-title').show();
}).mouseout(function() {
$(this).children('.small-title').hide();
});
})
We can get rid of this because as you mentioned in your comment you just want to fix the child state.
.mouseout(function() {
$(this).children('.small-title').hide();
})

Disable mouse wheel inside of ul{position:fixed}

I am using wordpress site. I created menu bar, inside of sub-menu, used position:fixed element. Anybody tell me how can i disable mousewheel inside of that sub-menu. That means i don't want page scroll inside of that sub-menu.
Please anyone help me.
You can use CSS property overflow: hidden; which specifies what happens if content overflows an element's box.
Using overflow: hidden; allow you to do not show up the scroll bar and so do not allowing scrolling at all including mouse weal.
Here below a very generic example, please consider to add your real markup in your question for a fix on your real app code.
https://jsfiddle.net/bxohL8tt/2/
#sub-menu{
width:250px;
height: 100px;
background-color:red;
overflow: hidden;
}
If the element that is scrolling on mouse-wheel event is the body, or even some other element, you can use JavaScript to prevent it from scrolling while your menu has "focus" like this:
var menuBar = document.getElementById('menuBar');
menuBar.onmouseover = function()
{
document.body.style.overflow = 'hidden';
};
menuBar.onmouseout = function()
{
document.body.style.overflow = 'auto';
};
Add the above inside a <script> element at the end of your main HTML source-code and it should work.
You can do this by the following code:
$("sub-menu-selector").bind("wheel mousewheel", function() {
return false;
});
For example: (The example shows the disabling on the menu but it's just the same)
$(".menu").bind("wheel mousewheel", function() {
return false;
});
body {
margin:0;
}
.menu {
background:black;
color:#fff;
position:fixed;
width:100%;
padding:15px;
}
.content {
height:1500px;
background:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="menu">
Menu
</div>
<div class="content"></div>

Scroll to a specific Element Using html

Is there a method in html which makes the webpage scroll to a specific Element using HTML !?
Yes you use this
<div id="google"></div>
But this does not create a smooth scroll just so you know.
You can also add in your CSS
html {
scroll-behavior: smooth;
}
You should mention whether you want it to smoothly scroll or simply jump to an element.
Jumping is easy & can be done just with HTML or Javascript. The simplest is to use anchor's. The limitation is that every element you want to scroll to has to have an id. A side effect is that #theID will be appended to the URL
Go to Title
<div>
<h1 id="scroll">Title</h1>
</div>
You can add CSS effects to the target when the link is clicked with the CSS :target selector.
With some basic JS you can do more, namely the method scrollIntoView(). Your elements don't need an id, though it is still easier, e.g.
function onLinkClick() {
document.getElementsByTagName('h2')[3].scrollIntoView();
// will scroll to 4th h3 element
}
Finally, if you need smooth scrolling, you should have a look at JS Smooth Scroll or this snippet for jQuery. (NB: there are probably many more).
<!-- HTML -->
<div id="google"></div>
/*CSS*/
html { scroll-behavior: smooth; }
Additionally, you can add html { scroll-behavior: smooth; } to your CSS to create a smooth scroll.
Year 2020. Now we have element.scrollIntoView() method to scroll to specific element.
HTML
<div id="my_element">
</div>
JS
var my_element = document.getElementById("my_element");
my_element.scrollIntoView({
behavior: "smooth",
block: "start",
inline: "nearest"
});
Good thing is we can initiate this from any onclick/event and need not be limited to tag.
If you use Jquery you can add this to your javascript:
$('.smooth-goto').on('click', function() {
$('html, body').animate({scrollTop: $(this.hash).offset().top - 50}, 1000);
return false;
});
Also, don't forget to add this class to your a tag too like this:
Text
Here is a pure HTML and CSS method :)
html {
scroll-behavior: smooth;
/*Adds smooth scrolling instead of snapping to element*/
}
#element {
height: 100px;
width: 100%;
background-color: red;
scroll-margin-block-start: 110px;
/*Adds margin to the top of the viewport*/
scroll-margin-block-end: 110pxx;
/*Adds margin to the bottom of the viewport*/
}
#otherElement {
padding-top: 500px;
width: 100%;
}
Link
<div id="otherElement">Content</a>
<div id="element">
Where you want to scroll
</div>
<div id="otherElement">Content</a>
<nav>
1
2
3
</nav>
<section id="section1">1</section>
<section id="section2" class="fifty">2</section>
<section id="section3">3</section>
<style>
* {padding: 0; margin: 0;}
nav {
background: black;
position: fixed;
}
a {
color: #fff;
display: inline-block;
padding: 0 1em;
height: 50px;
}
section {
background: red;
height: 100vh;
text-align: center;
font-size: 5em;
}
html {
scroll-behavior: smooth;
}
#section1{
background-color:green;
}
#section3{
background-color:yellow;
}
</style>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript" >
$(document).on('click', 'a[href^="#"]', function (event) {
event.preventDefault();
$('html, body').animate({
scrollTop: $($.attr(this, 'href')).offset().top
}, 500);
});
</script>
I got it working by doing this, consider that top-page is the element that you want to scroll to:
document.getElementById("top-page").scrollTo({ behavior: "smooth", top: 0 });
Yes, you may use an anchor by specifying the id attribute of an element and then linking to it with a hash.
For example (taken from the W3 specification):
You may read more about this in Section Two.
...later in the document
<H2 id="section2">Section Two</H2>
...later in the document
<P>Please refer to Section Two above
for more details.
By using an href attribute inside an anchor tag you can scroll the page to a specific element using a # in front of the elements id name.
Also, here is some jQuery/JS that will accomplish putting variables into a div.
<html>
<body>
Click here to scroll to the myContent section.
<div id="myContent">
...
</div>
<script>
var myClassName = "foo";
$(function() {
$("#myContent").addClass(myClassName);
});
</script>
</body>
Should you want to resort to using a plug-in, malihu-custom-scrollbar-plugin, could do the job. It performs an actual scroll, not just a jump. You can even specify the speed/momentum of scroll. It also lets you set up a menu (list of links to scroll to), which have their CSS changed based on whether the anchors-to-scroll-to are in viewport, and other useful features.
There are demo on the author's site and let our company site serve as a real-world example too.
The above answers are good and correct. However, the code may not give the expected results. Allow me to add something to explain why this is very important.
It is true that adding the scroll-behavior: smooth to the html element allows smooth scrolling for the whole page. However not all web browsers support smooth scrolling using HTML.
So if you want to create a website accessible to all user, regardless of their web browsers, it is highly recommended to use JavaScript or a JavaScript library such as jQuery, to create a solution that will work for all browsers.
Otherwise, some users may not enjoy the smooth scrolling of your website / platform.
I can give a simpler example on how it can be applicable.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
// Add smooth scrolling to all links
$("a").on('click', function(event) {
// Make sure this.hash has a value before overriding default behavior
if (this.hash !== "") {
// Prevent default anchor click behavior
event.preventDefault();
// Store hash
var hash = this.hash;
// Using jQuery's animate() method to add smooth page scroll
// The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
$('html, body').animate({
scrollTop: $(hash).offset().top
}, 800, function(){
// Add hash (#) to URL when done scrolling (default click behavior)
window.location.hash = hash;
});
} // End if
});
});
</script>
<style>
#section1 {
height: 600px;
background-color: pink;
}
#section2 {
height: 600px;
background-color: yellow;
}
</style>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>Smooth Scroll</h1>
<div class="main" id="section1">
<h2>Section 1</h2>
<p>Click on the link to see the "smooth" scrolling effect.</p>
Click Me to Smooth Scroll to Section 2 Below
<p>Note: Remove the scroll-behavior property to remove smooth scrolling.</p>
</div>
<div class="main" id="section2">
<h2>Section 2</h2>
Click Me to Smooth Scroll to Section 1 Above
</div>
</body>
</html>

Fixed position navbar obscures anchors [duplicate]

This question already has answers here:
Fixed page header overlaps in-page anchors
(38 answers)
Closed 7 years ago.
I am trying to clean up the way my anchors work. I have a header that is fixed to the top of the page, so when you link to an anchor elsewhere in the page, the page jumps so the anchor is at the top of the page, leaving the content behind the fixed header (I hope that makes sense). I need a way to offset the anchor by the 25px from the height of the header. I would prefer HTML or CSS, but Javascript would be acceptable as well.
You could just use CSS without any javascript.
Give your anchor a class:
<a class="anchor" id="top"></a>
You can then position the anchor an offset higher or lower than where it actually appears on the page, by making it a block element and relatively positioning it. -250px will position the anchor up 250px
a.anchor {
display: block;
position: relative;
top: -250px;
visibility: hidden;
}
I found this solution:
<a name="myanchor">
<h1 style="padding-top: 40px; margin-top: -40px;">My anchor</h1>
</a>
This doesn't create any gap in the content and anchor links works really nice.
I was looking for a solution to this as well. In my case, it was pretty easy.
I have a list menu with all the links:
<ul>
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
</ul>
And below that the headings where it should go to.
<h3>one</h3>
<p>text here</p>
<h3>two</h3>
<p>text here</p>
<h3>three</h3>
<p>text here</p>
<h3>four</h3>
<p>text here</p>
Now because I have a fixed menu at the top of my page I can't just make it go to my tag because that would be behind the menu.
Instead, I put a span tag inside my tag with the proper id.
<h3><span id="one"></span>one</h3>
Now use 2 lines of CSS to position them properly.
h3{ position:relative; }
h3 span{ position:absolute; top:-200px;}
Change the top value to match the height of your fixed header (or more).
Now I assume this would work with other elements as well.
FWIW this worked for me:
[id]::before {
content: '';
display: block;
height: 75px;
margin-top: -75px;
visibility: hidden;
}
As this is a concern of presentation, a pure CSS solution would be ideal. However, this question was posed in 2012, and although relative positioning / negative margin solutions have been suggested, these approaches seem rather hacky, create potential flow issues, and cannot respond dynamically to changes in the DOM / viewport.
With that in mind I believe that using JavaScript is still (February 2017) the best approach. Below is a vanilla-JS solution which will respond both to anchor clicks and resolve the page hash on load (See JSFiddle). Modify the .getFixedOffset() method if dynamic calculations are required. If you're using jQuery, here's a modified solution with better event delegation and smooth scrolling.
(function(document, history, location) {
var HISTORY_SUPPORT = !!(history && history.pushState);
var anchorScrolls = {
ANCHOR_REGEX: /^#[^ ]+$/,
OFFSET_HEIGHT_PX: 50,
/**
* Establish events, and fix initial scroll position if a hash is provided.
*/
init: function() {
this.scrollToCurrent();
window.addEventListener('hashchange', this.scrollToCurrent.bind(this));
document.body.addEventListener('click', this.delegateAnchors.bind(this));
},
/**
* Return the offset amount to deduct from the normal scroll position.
* Modify as appropriate to allow for dynamic calculations
*/
getFixedOffset: function() {
return this.OFFSET_HEIGHT_PX;
},
/**
* If the provided href is an anchor which resolves to an element on the
* page, scroll to it.
* #param {String} href
* #return {Boolean} - Was the href an anchor.
*/
scrollIfAnchor: function(href, pushToHistory) {
var match, rect, anchorOffset;
if(!this.ANCHOR_REGEX.test(href)) {
return false;
}
match = document.getElementById(href.slice(1));
if(match) {
rect = match.getBoundingClientRect();
anchorOffset = window.pageYOffset + rect.top - this.getFixedOffset();
window.scrollTo(window.pageXOffset, anchorOffset);
// Add the state to history as-per normal anchor links
if(HISTORY_SUPPORT && pushToHistory) {
history.pushState({}, document.title, location.pathname + href);
}
}
return !!match;
},
/**
* Attempt to scroll to the current location's hash.
*/
scrollToCurrent: function() {
this.scrollIfAnchor(window.location.hash);
},
/**
* If the click event's target was an anchor, fix the scroll position.
*/
delegateAnchors: function(e) {
var elem = e.target;
if(
elem.nodeName === 'A' &&
this.scrollIfAnchor(elem.getAttribute('href'), true)
) {
e.preventDefault();
}
}
};
window.addEventListener(
'DOMContentLoaded', anchorScrolls.init.bind(anchorScrolls)
);
})(window.document, window.history, window.location);
Pure css solution inspired by Alexander Savin:
a[name] {
padding-top: 40px;
margin-top: -40px;
display: inline-block; /* required for webkit browsers */
}
Optionally you may want to add the following if the target is still off the screen:
vertical-align: top;
My solution combines the target and before selectors for our CMS. Other techniques don't account for text in the anchor. Adjust the height and the negative margin to the offset you need...
:target::before {
content: '';
display: block;
height: 180px;
margin-top: -180px;
}
This takes many elements from previous answers and combines into a tiny (194 bytes minified) anonymous jQuery function. Adjust fixedElementHeight for the height of your menu or blocking element.
(function($, window) {
var adjustAnchor = function() {
var $anchor = $(':target'),
fixedElementHeight = 100;
if ($anchor.length > 0) {
$('html, body')
.stop()
.animate({
scrollTop: $anchor.offset().top - fixedElementHeight
}, 200);
}
};
$(window).on('hashchange load', function() {
adjustAnchor();
});
})(jQuery, window);
If you don't like the animation, replace
$('html, body')
.stop()
.animate({
scrollTop: $anchor.offset().top - fixedElementHeight
}, 200);
with:
window.scrollTo(0, $anchor.offset().top - fixedElementHeight);
Uglified version:
!function(o,n){var t=function(){var n=o(":target"),t=100;n.length>0&&o("html, body").stop().animate({scrollTop:n.offset().top-t},200)};o(n).on("hashchange load",function(){t()})}(jQuery,window);
For modern browsers, just add the CSS3 :target selector to the page. This will apply to all the anchors automatically.
:target {
display: block;
position: relative;
top: -100px;
visibility: hidden;
}
You can do it without js and without altering html. It´s css-only.
a[id]::before {
content: '';
display: block;
height: 50px;
margin: -30px 0 0;
}
That will append a pseudo-element before every a-tag with an id. Adjust values to match the height of your header.
I had been facing a similar issue, unfortunately after implementing all the solutions above, I came to the following conclusion.
My inner elements had a fragile CSS structure and implementing a position relative / absolute play, was completely breaking the page design.
CSS is not my strong suit.
I wrote this simple scrolling js, that accounts for the offset caused due to the header and relocated the div about 125 pixels below. Please use it as you see fit.
The HTML
<div id="#anchor"></div> <!-- #anchor here is the anchor tag which is on your URL -->
The JavaScript
$(function() {
$('a[href*=#]:not([href=#])').click(function() {
if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'')
&& location.hostname == this.hostname) {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
if (target.length) {
$('html,body').animate({
scrollTop: target.offset().top - 125 //offsets for fixed header
}, 1000);
return false;
}
}
});
//Executed on page load with URL containing an anchor tag.
if($(location.href.split("#")[1])) {
var target = $('#'+location.href.split("#")[1]);
if (target.length) {
$('html,body').animate({
scrollTop: target.offset().top - 125 //offset height of header here too.
}, 1000);
return false;
}
}
});
See a live implementation here.
For the same issue, I used an easy solution : put a padding-top of 40px on each anchor.
As #moeffju suggests, this can be achieved with CSS. The issue I ran into (which I'm surprised I haven't seen discussed) is the trick of overlapping previous elements with padding or a transparent border prevents hover and click actions at the bottom of those sections because the following one comes higher in the z-order.
The best fix I found was to place section content in a div that is at z-index: 1:
// Apply to elements that serve as anchors
.offset-anchor {
border-top: 75px solid transparent;
margin: -75px 0 0;
-webkit-background-clip: padding-box;
-moz-background-clip: padding;
background-clip: padding-box;
}
// Because offset-anchor causes sections to overlap the bottom of previous ones,
// we need to put content higher so links aren't blocked by the transparent border.
.container {
position: relative;
z-index: 1;
}
Solutions with changing position property are not always possible (it can destroy layout) therefore I suggest this:
HTML:
<a id="top">Anchor</a>
CSS:
#top {
margin-top: -250px;
padding-top: 250px;
}
Use this:
<a id="top"> </a>
to minimize overlapping, and set font-size to 1px. Empty anchor will not work in some browsers.
Borrowing some of the code from an answer given at this link (no author is specified), you can include a nice smooth-scroll effect to the anchor, while making it stop at -60px above the anchor, fitting nicely underneath the fixed bootstrap navigation bar (requires jQuery):
$(".dropdown-menu a[href^='#']").on('click', function(e) {
// prevent default anchor click behavior
e.preventDefault();
// animate
$('html, body').animate({
scrollTop: $(this.hash).offset().top - 60
}, 300, function(){
});
});
The above methods don't work very well if your anchor is a table element or within a table (row or cell).
I had to use javascript and bind to the window hashchange event to work around this (demo):
function moveUnderNav() {
var $el, h = window.location.hash;
if (h) {
$el = $(h);
if ($el.length && $el.closest('table').length) {
$('body').scrollTop( $el.closest('table, tr').position().top - 26 );
}
}
}
$(window)
.load(function () {
moveUnderNav();
})
.on('hashchange', function () {
moveUnderNav();
});
* Note: The hashchange event is not available in all browsers.
You can achieve this without an ID using the a[name]:not([href]) css selector. This simply looks for links with a name and no href e.g. <a name="anc1"></a>
An example rule might be:
a[name]:not([href]){
display: block;
position: relative;
top: -100px;
visibility: hidden;
}
Instead of having a fixed-position navbar which is underlapped by the rest of the content of the page (with the whole page body being scrollable), consider instead having a non-scrollable body with a static navbar and then having the page content in an absolutely-positioned scrollable div below.
That is, have HTML like this...
<div class="static-navbar">NAVBAR</div>
<div class="scrollable-content">
<p>Bla bla bla</p>
<p>Yadda yadda yadda</p>
<p>Mary had a little lamb</p>
<h2 id="stuff-i-want-to-link-to">Stuff</h2>
<p>More nonsense</p>
</div>
... and CSS like this:
.static-navbar {
height: 100px;
}
.scrollable-content {
position: absolute;
top: 100px;
bottom: 0;
overflow-y: scroll;
width: 100%;
}
There is one significant downside to this approach, however, which is that while an element from the page header is focused, the user will not be able to scroll the page using the keyboard (e.g. via the up and down arrows or the Page Up and Page Down keys).
Here's a JSFiddle demonstrating this in action.
This was inspired by the answer by Shouvik - same concept as his, only the size of the fixed header isn't hard coded. As long as your fixed header is in the first header node, this should "just work"
/*jslint browser: true, plusplus: true, regexp: true */
function anchorScroll(fragment) {
"use strict";
var amount, ttarget;
amount = $('header').height();
ttarget = $('#' + fragment);
$('html,body').animate({ scrollTop: ttarget.offset().top - amount }, 250);
return false;
}
function outsideToHash() {
"use strict";
var fragment;
if (window.location.hash) {
fragment = window.location.hash.substring(1);
anchorScroll(fragment);
}
}
function insideToHash(nnode) {
"use strict";
var fragment;
fragment = $(nnode).attr('href').substring(1);
anchorScroll(fragment);
}
$(document).ready(function () {
"use strict";
$("a[href^='#']").bind('click', function () {insideToHash(this); });
outsideToHash();
});
I'm facing this problem in a TYPO3 website, where all "Content Elements" are wrapped with something like:
<div id="c1234" class="contentElement">...</div>
and i changed the rendering so it renders like this:
<div id="c1234" class="anchor"></div>
<div class="contentElement">...</div>
And this CSS:
.anchor{
position: relative;
top: -50px;
}
The fixed topbar being 40px high, now the anchors work again and start 10px under the topbar.
Only drawback of this technique is you can no longer use :target.
Adding to Ziav's answer (with thanks to Alexander Savin), I need to be using the old-school <a name="...">...</a> as we're using <div id="...">...</div> for another purpose in our code. I had some display issues using display: inline-block -- the first line of every <p> element was turning out to be slightly right-indented (on both Webkit and Firefox browsers). I ended up trying other display values and display: table-caption works perfectly for me.
.anchor {
padding-top: 60px;
margin-top: -60px;
display: table-caption;
}
I added 40px-height .vspace element holding the anchor before each of my h1 elements.
<div class="vspace" id="gherkin"></div>
<div class="page-header">
<h1>Gherkin</h1>
</div>
In the CSS:
.vspace { height: 40px;}
It's working great and the space is not chocking.
how about hidden span tags with linkable IDs that provide the height of the navbar:
#head1 {
padding-top: 60px;
height: 0px;
visibility: hidden;
}
<span class="head1">somecontent</span>
<h5 id="headline1">This Headline is not obscured</h5>
heres the fiddle: http://jsfiddle.net/N6f2f/7
You can also add an anchor with follow attr:
(text-indent:-99999px;)
visibility: hidden;
position:absolute;
top:-80px;
and give the parent container a position relative.
Works perfect for me.
A further twist to the excellent answer from #Jan is to incorporate this into the #uberbar fixed header, which uses jQuery (or MooTools). (http://davidwalsh.name/persistent-header-opacity)
I've tweaked the code so the the top of the content is always below not under the fixed header and also added the anchors from #Jan again making sure that the anchors are always positioned below the fixed header.
The CSS:
#uberbar {
border-bottom:1px solid #0000cc;
position:fixed;
top:0;
left:0;
z-index:2000;
width:100%;
}
a.anchor {
display: block;
position: relative;
visibility: hidden;
}
The jQuery (including tweaks to both the #uberbar and the anchor approaches:
<script type="text/javascript">
$(document).ready(function() {
(function() {
//settings
var fadeSpeed = 200, fadeTo = 0.85, topDistance = 30;
var topbarME = function() { $('#uberbar').fadeTo(fadeSpeed,1); }, topbarML = function() { $('#uberbar').fadeTo(fadeSpeed,fadeTo); };
var inside = false;
//do
$(window).scroll(function() {
position = $(window).scrollTop();
if(position > topDistance && !inside) {
//add events
topbarML();
$('#uberbar').bind('mouseenter',topbarME);
$('#uberbar').bind('mouseleave',topbarML);
inside = true;
}
else if (position < topDistance){
topbarME();
$('#uberbar').unbind('mouseenter',topbarME);
$('#uberbar').unbind('mouseleave',topbarML);
inside = false;
}
});
$('#content').css({'margin-top': $('#uberbar').outerHeight(true)});
$('a.anchor').css({'top': - $('#uberbar').outerHeight(true)});
})();
});
</script>
And finally the HTML:
<div id="uberbar">
<!--CONTENT OF FIXED HEADER-->
</div>
....
<div id="content">
<!--MAIN CONTENT-->
....
<a class="anchor" id="anchor1"></a>
....
<a class="anchor" id="anchor2"></a>
....
</div>
Maybe this is useful to somebody who likes the #uberbar fading dixed header!
#AlexanderSavin's solution works great in WebKit browsers for me.
I additionally had to use :target pseudo-class which applies style to the selected anchor to adjust padding in FF, Opera & IE9:
a:target {
padding-top: 40px
}
Note that this style is not for Chrome / Safari so you'll probably have to use css-hacks, conditional comments etc.
Also I'd like to notice that Alexander's solution works due to the fact that targeted element is inline. If you don't want link you could simply change display property:
<div id="myanchor" style="display: inline">
<h1 style="padding-top: 40px; margin-top: -40px;">My anchor</h1>
</div>
Here's the solution that we use on our site. Adjust the headerHeight variable to whatever your header height is. Add the js-scroll class to the anchor that should scroll on click.
// SCROLL ON CLICK
// --------------------------------------------------------------------------
$('.js-scroll').click(function(){
var headerHeight = 60;
$('html, body').animate({
scrollTop: $( $.attr(this, 'href') ).offset().top - headerHeight
}, 500);
return false;
});
I ran into this same issue and ended up handling the click events manually, like:
$('#mynav a').click(() ->
$('html, body').animate({
scrollTop: $($(this).attr('href')).offset().top - 40
}, 200
return false
)
Scroll animation optional, of course.