Sticky header after some scrolling? - javascript

okay here's an example of what i am trying to ask,
the nav bar of usatoday.
I'm using bootstrap affix. here's my code
<div class="header">
<div class="header-1">
<h1>this is some logo</h1>
</div>
<div class="header-2">
<h3>this is some heading</h3>
</div>
</div>
<div class="content" style="height:2500px;">
</div>
<div class="footer">
this is a footer
</div>
JavaScript
$('.header-2').affix({
});
how can I make the div header-2 to be fixed on the top, (when there is some scrolling and the div header-2 just reach the top position) as of the site I've mentioned earlier?
I would love to see the header-1 and header-2, but some scrolling should hide header-1 and stick header-2 to the top most.
thanks

See this Jsfiddle
you can check the position of the slider and add class accordingly
$(window).scroll(function () {
if( $(window).scrollTop() > $('#header-2').offset().top && !($('#header-2').hasClass('posi'))){
$('#header-2').addClass('posi');
} else if ($(window).scrollTop() == 0){
$('#header-2').removeClass('posi');
}
});

use jquery look at this example
http://jsfiddle.net/5n5MA/2/
var fixmeTop = $('.fixme').offset().top; // Get initial position
$(window).scroll(function() { // Assign scroll event listener
var currentScroll = $(window).scrollTop(); // Get current position
if (currentScroll >= fixmeTop) { // Make it fixed if you've scrolled to it
$('.fixme').css({
position: 'fixed',
top: '0',
left: '0'
});
} else { // Make it static if you scroll above
$('.fixme').css({
position: 'static'
});
}
});

Bootstrapped answer using Bootstrap.affix()
$('.header-2').affix({
offset: {
top: function () {
return (this.top = $(".header-2").offset().top);
}
}
});
This also needs CSS for the fixed positioning (see the Docs).
The affix plugin toggles between three classes, each representing a
particular state: .affix, .affix-top, and .affix-bottom. You must
provide the styles for these classes yourself (independent of this
plugin) to handle the actual positions.
.header-2.affix {
top: 0;
}
Working example at Bootply: http://www.bootply.com/S03RlcT0z0

<style>
.header {
top: 0%;
left: 0%;
width: 100%;
position:fixed;
}
</style>
I'm sorry didnt look at your problem carefully.
This may helps you Issue with Fixed Header and Bootstrap Affix / Scrollspy - Not jumping to correct location

Related

Repositioning element on scroll with jQuery

I am trying to reposition an element on scroll using jQuery scroll event and just adjusting margin-top property.Element is inside bootstrap nav so its showed along all other elements inside nav on desktop and for mobiles its just fixed positioned in upper left corner.element contains two flag links for different page languages.
My code is:
Html:
<div class="navbar yamm navbar-default">
<div class="flags">
<img src="UK_flag.png" alt="English">
<img src="DK_flag.png" alt="Danish">
</div>
<div class="navbar-header">
....
js:
var scrollingDiv = $(".flags").offset().top - $(window).scrollTop();
$(window).scroll(function(){
if(scrollingDiv > 100) {
$(".flags").css("margin-top", "24px");
}
if(scrollingDiv == 92) {
$(".flags").css("margin-top", "10px");
}
console.log(scrollingDiv);
});
console log displays always 92 as its position.One note page contains 1 more navigation which is above bootstrap nav so I need this margin-top fix for that.Whan nav goes down it reposition itself nicely,but whan it comes back it keeps margin-top property at 10px and flags jump out of aligment.
Thanks for all future ansers :)
Put var scrollingDiv = $(".flags").offset().top - $(window).scrollTop(); this inside you're $(window).scroll(function(){});
When you declare it like its current state. The scrollingDiv will keep 92px because it only sets it on page load.
If inside the scroll() function, it will update the value when the user is scrolling.
Small Demo (I dont know you're actual layout)
$(window).scroll(function(){
var scrollingDiv = $(".flags").offset().top - $(window).scrollTop();
if(scrollingDiv > 100) {
$(".flags").css("margin-top", "24px");
}
if(scrollingDiv >= 92 && scrollingDiv < 100) {
$(".flags").css("margin-top", "10px");
}
console.log(scrollingDiv);
});
.scroll-container {
height: 2000px;
overflow: auto;
}
.scroll-container .flags {
position: relative;
top: 120px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="scroll-container">
<div class="flags">
<img src="UK_flag.png" alt="English">
<img src="DK_flag.png" alt="Danish">
</div>
</div>

How to scroll div with page without position: fixed?

I found this script:
$(function(){
var btn = $('.social');
var btnPosTop = btn.offset().top;
var win = $(window);
win.scroll(function(e){
var scrollTop = win.scrollTop();
if(scrollTop >= btnPosTop){
btn.css({position:'fixed',left:'82%'});
}else if(btn.css('position') === 'fixed'){
btn.css({position:'',left:''});
}
});
});
Which works great. I changed the original field to '.social' so that it would work with my code.
I am not looking for a crap fix of "left: 82%" though.
I want to avoid the position: fixed; and simply scroll the div where it sits.
My tree is #container .contain .single-content .social
The position: fixed is my main problem, but if you know, then stopping .social once it reaches the very bottom of .single-content would be a major plus!!
Hopefully I have provided enough information.
HTML:
<div id='container'>
<div class='contain'>
<div class='single-content'>
<div class='first'>
<div class='social'>
content here.. no p tags.. just facebook, twitter buttons etc.
</div>
</div>
</div>
</div>
</div><!-- container -->
EDIT:
website in question: thelackof.com
You can see how the social icons are offset a bit because of my left:82%
If I remove the left:, then the new position: fixed will jump my div out of the containing div and all the way to the left of the next containing div.
I would like it to stay where it is and scroll down once reached.
EDIT no. 2: First of all:
So it will get a value that won't disturb with the main-contents:
#container .contain .single-content .first .social {
float: left;
position: absolute;
width: 15%;
right: 0;
}
Then this:
$(function(){
var btn = $('.social');
var btnPosTop = btn.offset().top;
var win = $(window);
win.scroll(function(e){
var scrollTop = win.scrollTop();
if(scrollTop >= btnPosTop){
btn.css({position:'fixed'});
}else if(btn.css('position') === 'fixed'){
btn.css({position:''});}
if (btnPosTop >= $('.single-content').offset().top-92){
btn.css({position:''});
}
});
});
I might be getting your question wrong but I think this is what you asked for. I removed the left property.
Hope it helps :)
EDIT: I've added:
if (btnPosTop >= $('.single-content').offset().top){
btn.css({position:''});
}
So it will scroll until the btnPosTop is greater than the offset().top of .single-content
Please let me know if it works

How do I make a div (menu) fixed positioned after some scrolling has happened?

I'm making a theme for a website and I was given permission to play with the HTML files. The thing is I'm just familiarised with CSS and HTML, but I'm a complete noob when it comes to Javascript, JQuery, etc. and, sadly, it seems I need those to add some features I want.
I'd like a menu that works like this one: https://www.planetside2.com/news
The HTML is basically this:
<div id="wrap">
<div id="page-header">
<div class="headerbar">
</div>
</div>
And plenty stuff inside, but I hope the containers are enough
This is the CSS:
#wrap {
margin: 0 auto;
width: 1024px;
}
.headerbar {
background: url("{T_THEME_PATH}/images/headerbarbg.png") no-repeat ;
background-position: center;
width: 1054px;
margin:0 -15px;
margin-top:3px;
height: 120px;
position: relative;
padding-top: 70px;
}
I've checked out some other solutions, but, as I said, I'm a complete noob at scripting and when I try to apply such scripts to the theme, they don't work, most likely because there are some things that I should change that I don't know (except classes and IDs, of course).
I hope someone can help me.
First of all you need to detect scrolling and window resize
$(document).ready(function(){
$(window).on("scroll resize", function(e){
var elem = $(".headerbar");
// check if your header is visible by subtracting
// the top offset of your div from the scrolltop distance
if ((elem.offset().top - $(window).scrollTop()) <= 0 && elem.css("position") !== "fixed") {
console.log("not visible");
elem.css({
position:"fixed",
"z-index":"9999",
top:"0px"
});
// check if your header height is greater or equal to the scrolltop distance
} else if (elem.height() >= $(window).scrollTop()) {
console.log("visible");
elem.css({
position:"relative"
});
}
});
})
And here is a simple demo: JSFIDDLE
Some thing i have done previously in fiddle just check this one out will help you to have a scratch.
$(document).ready(function () {
var top_fixed;
if ($('#header-con').length > 0)
{
top_fixed = $('#header-con').offset().top;
}
$(window).scroll(function () {
if ($('#header-con').length > 0)
{
$('#header-con').toggleClass('fixed', $(window).scrollTop() > top_fixed);
}
});
});
DEMO
This short jquery code is what you need.
Tested and was working in a website i had develop lately.
$(window).scroll(function() {
if($(window).scrollTop() != 0) {
$('#fixed-menu-top').css('position', 'fixed').fadeIn();
} else {
$('#fixed-menu-top').css('position', 'absolute').fadeOut();
}
});
Just edit the ids to yours ex #fixed-menu-top to #wrap or any ids in ypur mark up
See website

Change margin-top position of an fixed positioned element after reaching the bottom of the page?

I need to change top-margin of an fixed div element from margin-top: 200px to margin top 0px after reaching the bottom of the page (or 200px from bottom) using vertical scrollbar.
And toggle return back if scrolling back to the top.
I guess some javascript/jQuery code code do that.
my html/layout code:
<div id="header" style="position: fixed; margin-top: 0px;">
Header content
</div>
<div id="main">
<div id="left" style="position: fixed; margin-top: 200px;">Google Ads here</div>
<div id="right">Content posts here</div>
</div>
<div id="footer">
Footer content
</div>
EDIT: Here are some images to make my question more clear.
normal state when you load the page:
problem when you scroll down, and the google ads column is in conflict with footer:
how it needs to be solved:
Derfder...
Voila, my proposed solution:
http://jsfiddle.net/YL7Jc/2/
The animation's a tad jerky, but I think it does what you want
(It's my take on an earlier s/o post:
Can I keep a DIV always on the screen, but not always in a fixed position? )
Let me know what you think!
Try below code which binds an event to window.scroll to check if the page hits the bottom (bottom in 200px) and moves the #left to top (margin-top: 0)..
DEMO: http://jsfiddle.net/6Q6XY/4/ ( added some demo code to see when it hits the bottom.)
$(function() {
var $left = $('#left');
$(window).bind('scroll', function() {
if (($(document).height()
- (window.pageYOffset + window.innerHeight)) < 200) {
$left.css('marginTop', 0);
} else {
$left.css('marginTop', 200);
}
});
});
Reference: https://stackoverflow.com/a/6148937/297641
You need to implement the window scroll function, this is a jquery implementation so please ensure you include the latest jquery libaries
$(window).scroll(function () {
if ($(window).scrollTop() + $(window).height() == $(document).height()) {
//if it hits bottom
$('#left').css("margin-top", "0px");
}
else {
$('#left').css("margin-top", "200px");
}
});
HTML
<div id="main" style="width: 960px; margin: 0px auto;">
<div id="left" style="position: fixed; top: 200px; left: 0px; background: #000; width: 100%; color: #fff;">Google Ads here</div>
<div id="right"></div>
</div>
JAVASCRIPT
<script type="text/javascript">
$(function() {
var documentHeight = $(document).height();
var windowHeight = $(window).height();
var left = $('#left');
var leftTopPosition = $('#left').css('top');
leftTopPosition = parseInt(leftTopPosition.substring(0, leftTopPosition.length-2));
$(window).scroll(function(){
var pageOffsetY = window.pageYOffset;
if((documentHeight - pageOffsetY - windowHeight) <= 200 && leftTopPosition == 200) {
left.stop().animate({
'top': '0px'
});
leftTopPosition = 0;
}
else if((documentHeight - pageOffsetY - windowHeight) > 200 && leftTopPosition == 0) {
left.stop().animate({
'top': '200px'
});
leftTopPosition = 200;
}
});
});
</script>
Hi Firstly you should have been more clearer in the first place before marking people down, as everyone give similar answers then it shows the question was not clear.
See Js Fiddle for a potential fix, please tweak as you need it with the pixels etc
for this problem you should use z-index in css
Try somethins like this
if ($(window).scrollTop() == $(document).height() - $(window).height())
{
document.getElementById(yourid).setAttribute("style","margin-top:0px");
}
Try this:
$(window).bind('scroll', function(){
if(($(window).height()-$(window).scrollTop())<200)
{
$('#left').css('margin-top',$(window).scrollTop());
}
else
{
$('#left').css('margin-top',200);
}
});

offsetting an html anchor to adjust for fixed header [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.

Categories