I'm trying to achieve a page with a certain number of divs, each of which has a bookmark (a name). The problem is, when I jump to one of the bookmarks, part of the text is gone, caused by the design. I'd like to know if there's a way to change the behaviour of the bookmark, so it won't set the start of it at the top of the page, but a set number of pixels below.
The page can be accessed here: Not longer online, sorry.
The behaviour occurs when you go to any of the bookmarks (except #6, because the document ends there), like on here: Not longer online, sorry.
Can this be solved by a css property or any other way? (update) I'd prefer this over a javascript solution because I'm planning to use javascript to tab them, and keep the bookmarks in case of disabled javascript
You can do it with JavaScript using scrollBy. Put this in a load listener or onload handler:
if(window.location.hash.length > 1) {
window.scrollBy(0, -60); // Adjust to suit your needs.
}
window.onhashchange = window.onload = function () {
if( window.location.hash.length && window.scrollY > window.pageYOffset ) {
window.scrollBy( 0, -100 ); // Scroll up 100 pixels on hash change
};
};
I got the answer myself, so this is basically for references.
To ignore the 100px offset that is caused by the header, I added a padding-top of 100px to each single div element, and then I changed the links to go to the div's instead of the a elements I added. This padding-top basically makes the text appear where it should and thus solved my problem.
Related
I am aware this had been asked before, but no answer actually did the trick as far as I tested them.
Basically what I need is to change some element styles as soon as it "hits" the top border of the screen while scrolling down. This element is a 'Back to Top' button that will be sitting in a section and start following the user when they scroll pass said section.
I am not asking about CSS properties, I am asking about some JS property or method that allow me to know this. IE:
$('#back').distanceFromTopOfTheScreen() // This value will decrease as I scroll down
I know there are other soultions, but the client has asked for this behavior.
Any idea?
You can :
distance = $('#eleId')[0].getBoundingClientRect().top;
For more about getBoundingClientRect() look at the MDN Documentation
Note: This value change when you're scrolling, it gives you the distance between the top border of the element and the top of the Page
Sometimes JQuery make's everything more confusing than Native Javascript, even forgothing the very basics functions:
window.onscroll = function() { fixPosition()};
function fixPosition() {
var Yplus = 4; //number of lines in every scroll
document.getElementById('element').style.top = document.body.scrollTop + Yplus ;
}
This will allows you to move an "element" static on the window following the scroll.
Sorry, but I am a complete noob with JS. I am using Bootstrap to try build my first website.
The website has a fixed top navbar. I want to change the navbar's border-bottom properties when it reaches the bottom of the header div (about 480/500px down the page).
Currently the border-bottom is white, but I want to change it to blue when scrolled beyond a certain point (bottom of header) and then change back to white if scrolled back up again. The effect I want is the appearance of the fixed nav 'picking up' the bottom border of the banner section when it scroll's past.
I have given the navbar div an id of id="n1", and created a class .navbar1{border-bottom: 1px solid rgba(46,152,255,1)!Important;} to add to override the existing css.
I am not using jQuery because I don't use much JS and I don't want to call it just for a few things - it is a big file. I have tried various things without any success. Probably because they relied on jQuery? I don't know. For example, the last one was:
$(window).scroll( function(){
if($(window).scrollTop() > 50) $("n1").addClass("navbar1");
else $("n1").removeClass("navbar1");
});
Anyway, I was hoping someone may be able to help me with the plain/pure JS to change the attribute properties as described. Thank you in advance for any assistance.
EDIT:
This has been kindly answered below. But given some comments, I thought it might be useful to clarify my use of JS: My website requires very little JS functionality so I have chosen to inline my JS, rather than call an external JS file or files - such as jquery.js and bootstrap.js which are relatively large files.
Although I lose the benefit of caching the JS, and my HTML is slightly larger, I am happy to do that because in my case I feel those losses are more than made up for the increased initial page load speed from:
not having to make additional http requests,
not having to load relatively large files.
It is certainly not for everyone, but I feel that it suits my case. Having said that, when all is done and my website is up and running I will probably do some testing to see whether a custom external JS file is better again. Basically, I am only using Bootstrap for its CSS functionality, not its JS functionality. I hope that makes sense.
This demo may help you!
It doesn't use jQuery.
Here is the javascript code:
window.onscroll = function() {
var nav = document.getElementById('nav');
if ( window.pageYOffset > 100 ) {
nav.classList.add("navbar1");
} else {
nav.classList.remove("navbar1");
}
}
I did a small change on #radonirina-maminiaina amazing answer.
While it works, I do prefer avoiding doing unnecessary DOM calls during the onScroll event. The onScroll event can be triggered quite often on some devices, so it's best to keep its handler as fast as possible.
In my solution, I cache the nav DOM element on a closure and I only update its classes if the offset changes.
window.onscroll = function () {
let isScrolled = false
const scrollPoint = 100
const nav = document.getElementById('navbar')
function onScroll () {
if ( window.pageYOffset > scrollPoint && !isScrolled ) {
nav.classList.add("scroll");
isScrolled = true
} else if (window.pageYOffset <= scrollPoint && isScrolled) {
nav.classList.remove("scroll");
isScrolled = false
}
}
onScroll() // Makes sure that the class is attached on the first render
return onScroll
}()
This may come as a huge surprise to some people but I am having an issue with the IE browser when I am using the $(window).scroll method.
My goal:
I would like to have the menu located on the left retain it's position until the scroll reaches > y value. It will then fix itself to the top of the page until the scroll returns to a < y value.
My error:
Everything seems just fine in Chrome and Firefox but when I go to Internet Explorer it would seem the browser is moving #scroller every time the scroll value changes, this is causing a moving/flickering event.
If someone could point me to a resource or give me a workaround for this I would be very grateful!
Here is a fiddle:
http://jsfiddle.net/CampbeII/nLK7j/
Here is a link to the site in dev:
http://squ4reone.com/domains/ottawakaraoke/Squ4reone/responsive/index.php
My script:
$(window).scroll(function () {
var navigation = $(window).scrollTop();
if (navigation > 400) {
$('#scroller').css('top',navigation - 220);
} else {
$('#scroller').css('top',183);
$('#scroller').css('position','relative');
}
});
You might want to take a look at the jQuery Waypoints plugin, it lets you do sticky elements like this and a lot more.
If you want to stick with your current method, like the other answers have indicated you should toggle fixed positioning instead of updating the .top attribute in every scroll event. However, I would also introduce a flag to track whether or not it is currently stuck, this way you are only updating the position and top attributes when it actually make the transition instead of every scroll event. Interacting with the DOM is computationally expensive, this will take a lot of load off of the layout engine and should make things even smoother.
http://jsfiddle.net/WYNcj/6/
$(function () {
var stuck = false,
stickAt = $('#scroller').offset().top;
$(window).scroll(function () {
var scrollTop = $(window).scrollTop();
if (!stuck && scrollTop > stickAt) {
$('#scroller').css('top', 0);
$('#scroller').css('position','fixed');
stuck = true;
} else if (stuck && scrollTop < stickAt) {
$('#scroller').css('top', stickAt);
$('#scroller').css('position','absolute');
stuck = false;
}
});
});
Update
Switching the #scroller from relative to fixed removes it from the normal flow of the page, this can have unintended consequences for the layout as it re-flows without the missing block. If you change #scroller to use an absolute position it will be removed from the normal flow and will no longer cause these side-effects. I've updated the above example and the linked jsfiddle to reflect the changes to the JS/CSS.
I also changed the way that stickAt is calculated as well, it uses .offset() to find the exact position of the top of #scoller instead of relying on the CSS top value.
Instead of setting the top distance at each scroll event, please consider only switching between a fixed position and an absolute or relative position.All browsers will appreciate and Especially IE.
So you still listen to scroll but you now keep a state flag out of the scroll handler and simply evaluate if it has to switch between display types.
That is so much more optimized and IE likes it.
I can get flickers in Chrome as well if I scroll very quickly. Instead of updating the top position on scroll, instead used the fixed position for your element once the page has scrolled below the threshold. Take a look at the updated fiddle: http://jsfiddle.net/nLK7j/2/
I'm currently working under some tight restrictions with regard to what I can do with JavaScript (no frameworks such as jQuery for example, and nothing post Firefox 2.0).
Here's my problem; I have a persistent header floating at the top of the page. I have input elements scattered throughout (we're replicating a paper form exactly, including the background image). There is a field nearing the bottom of the page that gets tabbed out (using keyboard tab button) and puts the focus on a field at the top of the page. Firefox will automatically scroll the field "into view". However, while the browser believes the field is in view, it's actually hidden beneath the persistent header.
http://imageshack.us/a/img546/5561/scrollintoviewproblem.png
The blue field above is accessed by hitting "tab" from another location on the page. The browser believes the field has been scrolled into view, but it's in fact hidden beneath the floating persistent header.
What I'm looking for is ideas as to how I can detect that the field is beneath this header and scroll the entire page accordingly.
I've tried a few variations of margin & padding (see other considerations at http://code.stephenmorley.org/javascript/detachable-navigation/#considerations) without luck. I've also tried calling the JavaScript function "scrollIntoView(element)" each time we focus on a field, but given the amount of fields on the form (and the fact that we're aligning them to match the background image of a paper form exactly), this was causing some pretty severe "jumping" behavior when tabbing through fields close to each other that were at slightly different heights.
I can change how the persistent header is done, so long as it doesn't require too much effort. Unfortunately, frames are out of the question because we need to interact with the page content from the persistent header.
Ideally the solution would be in CSS, but I'm open to JavaScript if it solves my problem.
Another note, we require that the input elements have a background color, which means that adding padding to them would make the background color stretch, which hides parts of the background image. BUT, the input elements are in a div, so we might be able to use this to our advantage.
So after doing some more searching (thanks to #Kraz for leading on this route with the scrollTo() suggestion) I've found a solution that works for me.
I've added an onFocus call to each element dynamically, so they always call the scrollScreenArea(element) function, which determines if they're hidden beneath the top header or too close to the footer area (this solves another problem entirely, using the same solution).
/* This function finds an element's position relative to the top of the viewable area */
function findPosFromTop(node) {
var curtop = 0;
var curtopscroll = 0;
if (node.offsetParent) {
do {
curtop += node.offsetTop;
curtopscroll = window.scrollY;
} while (node = node.offsetParent);
}
return (curtop - curtopscroll);
}
/* This function scrolls the page to ensure that elements are
always in the viewable area */
function scrollScreenArea(el)
{
var topOffset = 200; //reserved space (in px) for header
var bottomOffset = 30; //amount of space to leave at bottom
var position = findPosFromTop(el);
//if hidden beneath header, scroll into view
if (position < topOffset)
{
// to scroll up use a negative number
scrollTo(el.offsetLeft,position-topOffset);
}
//if too close to bottom of view screen, scroll into view
else if ((position + bottomOffset) > window.innerHeight)
{
scrollTo(0,window.scrollY+bottomOffset);
}
}
Let me know if you have any questions. Thanks #Kraz for sending me onto this solution.
As well, I'd like to reference Can I detect the user viewable area on the browser? since I took some code from there and that partially described my problem (with a neat diagram to boot).
The easiest method for doing this will be listening for each element's focus event and then seeing if it is on the page. In pure JS, it is something like:
var input = Array.prototype.slice.call(document.getElementsByTagName('input'));
for ( var i in input )
input[i].addEventListener( 'focus', function (e) {
var diff = 150 /* Header height */ - e.target.getBoundingClientRect().top;
if ( diff > 0 ) {
document.body.scrollTop += diff;
document.documentElement && document.documentElement.scrollTop += diff;
}
}, false );
I didn't include the IE addEvent method, but it should be pretty easy to make that on your own given this base.
I have a link on a long HTML page. When I click it, I wish a div on another part of the page to be visible in the window by scrolling into view.
A bit like EnsureVisible in other languages.
I've checked out scrollTop and scrollTo but they seem like red herrings.
Can anyone help?
old question, but if anyone finds this through google (as I did) and who does not want to use anchors or jquery; there's a builtin javascriptfunction to 'jump' to an element;
document.getElementById('youridhere').scrollIntoView();
and what's even better; according to the great compatibility-tables on quirksmode, this is supported by all major browsers!
If you don't want to add an extra extension the following code should work with jQuery.
$('a[href=#target]').
click(function(){
var target = $('a[name=target]');
if (target.length)
{
var top = target.offset().top;
$('html,body').animate({scrollTop: top}, 1000);
return false;
}
});
How about the JQuery ScrollTo - see this sample code
You can use Element.scrollIntoView() method as was mentioned above. If you leave it with no parameters inside you will have an instant ugly scroll. To prevent that you can add this parameter - behavior:"smooth".
Example:
document.getElementById('scroll-here-plz').scrollIntoView({behavior: "smooth", block: "start", inline: "nearest"});
Just replace scroll-here-plz with your div or element on a website. And if you see your element at the bottom of your window or the position is not what you would have expected, play with parameter block: "". You can use block: "start", block: "end" or block: "center".
Remember: Always use parameters inside an object {}.
If you would still have problems, go to https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
There is detailed documentation for this method.
Click here to scroll
<A name='myAnchorALongWayDownThePage"></a>
No fancy scrolling but it should take you there.
The difficulty with scrolling is that you may not only need to scroll the page to show a div, but you may need to scroll inside scrollable divs on any number of levels as well.
The scrollTop property is a available on any DOM element, including the document body. By setting it, you can control how far down something is scrolled. You can also use clientHeight and scrollHeight properties to see how much scrolling is needed (scrolling is possible when clientHeight (viewport) is less than scrollHeight (the height of the content).
You can also use the offsetTop property to figure out where in the container an element is located.
To build a truly general purpose "scroll into view" routine from scratch, you would need to start at the node you want to expose, make sure it's in the visible portion of it's parent, then repeat the same for the parent, etc, all the way until you reach the top.
One step of this would look something like this (untested code, not checking edge cases):
function scrollIntoView(node) {
var parent = node.parent;
var parentCHeight = parent.clientHeight;
var parentSHeight = parent.scrollHeight;
if (parentSHeight > parentCHeight) {
var nodeHeight = node.clientHeight;
var nodeOffset = node.offsetTop;
var scrollOffset = nodeOffset + (nodeHeight / 2) - (parentCHeight / 2);
parent.scrollTop = scrollOffset;
}
if (parent.parent) {
scrollIntoView(parent);
}
}
This worked for me
document.getElementById('divElem').scrollIntoView();
Answer posted here - same solution to your problem.
Edit: the JQuery answer is very nice if you want a smooth scroll - I hadn't seen that in action before.
Why not a named anchor?
The property you need is location.hash. For example:
location.hash = 'top'; //would jump to named anchor "top
I don't know how to do the nice scroll animation without the use of dojo or some toolkit like that, but if you just need it to jump to an anchor, location.hash should do it.
(tested on FF3 and Safari 3.1.2)
I can't add a comment to futtta's reply above, but for a smoother scroll use:
onClick="document.getElementById('more').scrollIntoView({block: 'start', behavior: 'smooth'});"
<button onClick="scrollIntoView()"></button>
<br>
<div id="scroll-to"></div>
function scrollIntoView() {
document.getElementById('scroll-to').scrollIntoView({
behavior: 'smooth'
});
}
The scrollIntoView method accepts scroll-Options to animate the scroll.
With smooth scroll
document.getElementById('scroll-to').scrollIntoView({
behavior: 'smooth'
});
No animation
document.getElementById('scroll-to').scrollIntoView();
There is a jQuery plugin for the general case of scrolling to a DOM element, but if performance is an issue (and when is it not?), I would suggest doing it manually. This involves two steps:
Finding the position of the element you are scrolling to.
Scrolling to that position.
quirksmode gives a good explanation of the mechanism behind the former. Here's my preferred solution:
function absoluteOffset(elem) {
return elem.offsetParent && elem.offsetTop + absoluteOffset(elem.offsetParent);
}
It uses casting from null to 0, which isn't proper etiquette in some circles, but I like it :) The second part uses window.scroll. So the rest of the solution is:
function scrollToElement(elem) {
window.scroll(0, absoluteOffset(elem));
}
Voila!
As stated already, Element.scrollIntoView() is a good answer. Since the question says "I have a link on a long HTML page..." I want to mention a relevant detail. If this is done through a functional link it may not produce the desired effect of scrolling to the target div. For example:
HTML:
<a id="link1" href="#">Scroll With Link</a>
JavaScript:
const link = document.getElementById("link1");
link.onclick = showBox12;
function showBox12()
{
const box = document.getElementById("box12");
box.scrollIntoView();
console.log("Showing Box:" + box);
}
Clicking on Scroll With Link will show the message on the console, but it would seem to have no effect because the # will bring the page back to the top. Interestingly, if using href="" one might actually see the page scroll to the div and jump back to the top.
One solution is to use the standard JavaScript to properly disable the link:
<a id="link1" href="javascript:void(0);">Scroll With Link</a>
Now it will go to box12 and stay there.
I use a lightweight javascript plugin that I found works across devices, browsers and operating systems: zenscroll
scrollTop (IIRC) is where in the document the top of the page is scrolled to. scrollTo scrolls the page so that the top of the page is where you specify.
What you need here is some Javascript manipulated styles. Say if you wanted the div off-screen and scroll in from the right you would set the left attribute of the div to the width of the page and then decrease it by a set amount every few seconds until it is where you want.
This should point you in the right direction.
Additional: I'm sorry, I thought you wanted a separate div to 'pop out' from somewhere (sort of like this site does sometimes), and not move the entire page to a section. Proper use of anchors would achieve that effect.
I personally found Josh's jQuery-based answer above to be the best I saw, and worked perfectly for my application... of course, I was already using jQuery... I certainly wouldn't have included the whole jQ library just for that one purpose.
Cheers!
EDIT: OK... so mere seconds after posting this, I saw another answer just below mine (not sure if still below me after an edit) that said to use:
document.getElementById('your_element_ID_here').scrollIntoView();
This works perfectly and in so much less code than the jQuery version! I had no idea that there was a built-in function in JS called .scrollIntoView(), but there it is! So, if you want the fancy animation, go jQuery. Quick n' dirty... use this one!
For smooth scroll this code is useful
$('a[href*=#scrollToDivId]').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) +']');
var head_height = $('.header').outerHeight(); // if page has any sticky header get the header height else use 0 here
if (target.length) {
$('html,body').animate({
scrollTop: target.offset().top - head_height
}, 1000);
return false;
}
}
});
Correct me if I'm wrong but I'm reading the question again and again and still think that Angus McCoteup was asking how to set an element to be position: fixed.
Angus McCoteup, check out http://www.cssplay.co.uk/layouts/fixed.html - if you want your DIV to behave like a menu there, have a look at a CSS there