How to create a fixed / sticky sidebar in CSS / JS? - javascript

I'm trying to create a website with main content area and a sidebar, something like here on Stack Overflow. The goal is that when you scroll down, the sidebar stays visible.
I have seen two approaches to this:
position:fixed;
JavaScript manipulation with the DOM
Approach no. 1, as far as I know, will have a problem when the viewport is smaller than the sidebar contents so I guess that can't be used reliably and JavaScript scripts that I have seen are usually animated or generally "slow" (you can see that there is redrawing going on after each scroll).
Can someone point out a JavScript library / CSS approach that would not suffer from the aforementioned issues?
Edit: an example would be this page but with the sidebar sticking to the top without an animation and correctly handling the situation when the sidebar is higher than content / viewport.

I don't like heavy JS solutions, so important thing to ask is - preferred compatibility. In IE8+ it is possible instead of
var $window = $(window),
$sidebar = $(sidebar);
$window.on('resize', function(){
$sidebar.height($window.innerHeight());
});
$window.resize();
do something like this (pure CSS solution):
#sidebar {
position: fixed;
left: 0; /* or right */
top: 0;
bottom: 0;
overflow: auto;
}
When you have top&bottom / left&right value at the same time, box will be stretched. (JSFiddle demo)

Got it. It is Javascript based, but I'm sure that's nothing heavy and even IE8 should solve it pretty fine.
var top = $('#sidebar').offset().top;
var height = $('#sidebar').height();
var winHeight = $(window).height();
var gap = 10;
$(window).scroll(function(event) {
var scrollTop = $(this).scrollTop();
// sidebar reached the (end - viewport height)
if (scrollTop + winHeight >= top + height + gap) {
// if so, fix the sidebar and make sure that offset().top will not give us results which would cancel the fixation
$('#sidebar').addClass('fixed').css('top', winHeight - height - gap + 'px');
} else {
// otherwise remove it
$('#sidebar').removeClass('fixed').css('top', '0px');
}
});​
demo

You could catch client window's height and giving it to your sidebar like this :
var sidebarHeight = $(window).innerHeight();
$('#sidebar')​​​​​​​​​​​.css('height',sidebarHeight);​​​​​​​​​​​​​
With the proper CSS for the sidebar :
#sidebar {
position: fixed;
right: 0;
top: 0;
width: 200px;
overflow: hidden;
}
Here is a working JSFiddle.
You could also watch for window resizing to avoid a mess on resize :) Here is the way to go with jQuery
Good luck

Not sure if you have this figured out but I have created a contained sticky sidebar jQuery plugin. It's really simple and allows you to invoke with just one line of jQuery. Take a look here: http://mojotech.github.com/stickymojo/
It starts by position: fixed; then uses javascript to handle any resizes, scrolls and even allows you to specify a footer element that it should not intersect. By combining these approaches you will get a smooth looking fixed element. Plus, we made it easy for you.

Code and demo here: http://closure-library.googlecode.com/svn/docs/class_goog_ui_ScrollFloater.html

Related

How to make scrollbar to see full content in below case?

see demo url of the framework i'm using: http://alvarotrigo.com/fullPage/examples/navigationH.html#secondPage
However,using almost same kind of code from above,
when I try to achieve below effect in which title text is excluded from slider. (title text to be static, and content is sliding)
jsfiddle url: http://jsfiddle.net/097wvnot/8/
I can't scroll to see all the content; what's the best code to achieve this effect?
if i want to use the top framework, must i do a lot of hack into its core functions?
if not hacking the top animation framework , what are other recommendations to this effect
Use an absolute positioned element for your title. Fullpage.js calculates the height of your content inside the slide elements. (as they are suppose to be full height...).
If you place anything outside any slide, it would have to be absoluted positioned.
Take a look at the solution I propose: http://jsfiddle.net/097wvnot/11/
I added the following style to your title:
#demo{
position:absolute;
top:50px;
margin: 0;
left:0;
right:0;
text-align:center;
}
It looks like the plugin is calculating the height of the fp-scrollable incorrectly. At least for your use case. I was able to get it looking good by just manually adjusting the fp-scrollable's height attribute to a smaller amount (obviously that is not a long term fix, just something I was doing for testing). I'm not sure if the calculating takes into account your font size, and things like that, so that might effect it.
If you want to hack on the plugin, generally the place you need to make your changes is fairly restricted, and wouldn't be too bad. From the github page. https://github.com/alvarotrigo/fullPage.js/blob/master/jquery.fullPage.js
All you need to do is fix the value being placed into the scrollHeight variable. I'm not sure exactly what it's not accounting for in the scroll height calculation (the scrollHeight needs to be smaller in your case, it's too big), but I think that's an exercise you can try your hand at first :) I've got to get to bed z.z
You also may need to mess with the calculation for the contentHeight, since ostensibly you'll be shrinking the scrollHeight, and the script only puts the scroll bar on there if the content is bigger than the scroll.
function createSlimScrolling(element){
//needed to make `scrollHeight` work under Opera 12
element.css('overflow', 'hidden');
//in case element is a slide
var section = element.closest('.fp-section');
var scrollable = element.find('.fp-scrollable');
//if there was scroll, the contentHeight will be the one in the scrollable section
if(scrollable.length){
var contentHeight = scrollable.get(0).scrollHeight;
}else{
var contentHeight = element.get(0).scrollHeight;
if(options.verticalCentered){
contentHeight = element.find('.fp-tableCell').get(0).scrollHeight;
}
}
var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
//needs scroll?
if ( contentHeight > scrollHeight) {
//was there already an scroll ? Updating it
if(scrollable.length){
scrollable.css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
}
//creating the scrolling
else{
if(options.verticalCentered){
element.find('.fp-tableCell').wrapInner('<div class="fp-scrollable" />');
}else{
element.wrapInner('<div class="fp-scrollable" />');
}
element.find('.fp-scrollable').slimScroll({
allowPageScroll: true,
height: scrollHeight + 'px',
size: '10px',
alwaysVisible: true
});
}
}
//removing the scrolling when it is not necessary anymore
else{
removeSlimScroll(element);
}
//undo
element.css('overflow', '');
}

Fixed sidebar too tall for browser (bottom is getting cut off)

Let's say I have a fixed sidebar that is XXpx tall (Refer to http://www.getskeleton.com/ if you want a visual of what I mean). The sidebar looks exactly the way I want, as long as the height of the browser is bigger than the sidebar. However, when the browser height shrinks below the height of the sidebar, the bottom contents get cut off.
Initially, the sidebar has position: fixed, but if the browser gets too small to contain the entire sidebar, I want to change it to position: aboslute. Essentially, I'd like to make it so on both page load and any time the user resizes finishes resizing the page it will check to make sure that the bottom content isn't being cut off, then assign the appropriate position attribute.
You could use a vertical media query for this, like so (let's say the sidebar is 700px tall.)
#sidebar {
position: absolute;
}
media screen and (min-height:700px) {
#sidebar { position: fixed; }
}
By declaring the absolute position first, you make sure that browsers that don't support media queries will get the absolutely positioned sidebar, which will still be functional.
Do something like this:
var $sidebar = $('#idOfSidebar')
,$w = $(window);
$w.resize(function () {
var pos = $w.height() < $sidebar.height()? 'absolute': 'fixed';
$sidebar.css({position: pos});
});
An option is to use overflow: auto for fixed blocks that can be potentially taller than browser`s client height. This can be used as default pure-CSS solution that can work in conjunction with JavaScript methods.

Vertical scrolling columns with different speeds

I would like to create an interface with 3 columns, each having mixed content (text, image, and video), and would like to have them scroll vertically with different speeds at the same time. Is there a relatively simple way of accomplishing this with html, css, and/or javascript?
PS. I know about the parallax scrolling, but the implementations I came across seem to be mostly about using images as background to create a dimensional illusion.
Something like: http://jsfiddle.net/KVWuS/.
$.fn.makeScroll = function(speed) {
var elem = this,
i = 0;
setInterval(function() {
elem.scrollTop(i++); // increment scroll top
}, speed); // run every 'speed' ms (so lower is faster)
};
You can enable it like:
$('div:eq(0)').makeScroll(75); // moderate speed
You want to actually scroll the content?
$('.column').animate({
scrollTop: $('.column').height() - $(window).height()
}, 1000);
This will scroll your column down in 1 second. Adjust the speed per column.
EDIT:
I was assuming your columns were the height of the window. If not, you'll have to adjust the scrollTop.
I think a simple workaround would be to create 3 div Elements with the following Attributes:
overflow: hidden;
width: x px (fixed width)
height: x px (fixed height)
top: 0px;
left: x px;
Then you have to capture the onscroll event and set the top-Attribute.
E.g.
div1: top: -100px
div2: top: -300px
div3: top: -500px
I hope my description is clear.. :)
That should work

how to center a relative div horizontally using jquery on window resize?

i am initially centering div horizontally using jquery but when the window is resized it looks bad so what i want to do is keep it centered using jquery after the window is resized
is there a way to help?
EDIT
guys i have successfully made other elements centered but i am having another issue now :(
please check this
http://hrmanagementbradford.com/gallery/
and resize the window, you will see that the content doesn't get positioned correctly, i am trying to fix this for hours but can't find the solution please help with that
EDIT
solved! it was complex and my code is very specific so posting it here won't help :)
and
although i used jquery to center it but if we use the css thing then FutureKode's answer is best suited for me :)
Why are you using jquery to center horizontally when css can do it one line and it will stay in the center when the browser is resized:
div {
margin:0 auto;
width:800px
}
You can make it dead-centered like this:
$('#elementID').css({
position:'absolute',
top:'50%',
left:'50%',
width:'600px', // adjust width
height:'300px', // adjust height
zIndex:1000,
marginTop:'-150px' // half of height
marginLeft:'-300px' // half of width
});
Note that element will appear at the center but with scrolling it won't move. If you want to make it appear at center, you need to set position to fixed instead. However, this won't work in IE6. So decision is yours :)
You can also create quick simple jQuery plugin:
(function($){
$.fn.centerIt = function(settings){
var opts = $.extend({}, $.fn.centerIt.defaults, settings);
return this.each(function(settings){
var options = $.extend({}, opts, $(this).data());
var $this = $(this);
$this.css({
position:options.position,
top:'50%',
left:'50%',
width:options.width, // adjust width
height:options.height, // adjust height
zIndex:1000,
marginTop:parseInt((options.height / 2), 10) + 'px' // half of height
marginLeft:parseInt((options.width / 2), 10) + 'px' // half of height
});
});
}
// plugin defaults - added as a property on our plugin function
$.fn.centerIt.defaults = {
width: '600px',
height: '600px',
position:'absolute'
}
})(jQuery);
And later use it like:
$('#elementId').centerIt({width:'400px', height:'200px'});
To center it when window is resized, you would use resize event just in case it does not center like this:
$(window).resize(function(){
$('#elementId').centerIt({width:'400px', height:'200px'});
});
You can use
margin: 0 auto;
to centre a block element horizontally in CSS.
Like so:
div
{
width: 400px;
margin: 0 auto;
}
do this:
$(window).resize(function(){
// reposition div again here
})

using a simple jquery script to have a div follow the page on scroll

I'm trying to use this script here: http://css-tricks.com/scrollfollow-sidebar/ to make a simple div that follows the window as the user scrolls. I changed it from 0 to topPadding and changed topPadding to topPadding*2 to get the right top offset.
Unfortunately this has the side effect of the object making the page a little longer and allowing the user to scroll infinitely. This bug is also actually in the original code without my larger toppadding changes if you make the window small enough.
I also tried another plugin for jquery, but it didn't work at all and this gives me what I need, so how can I fix it?
Why not just use CSS.
#theNonMovingDiv {position:absolute; position: fixed; top: Npx; right:Mpx}
position:fixed; doesn't work in ie6, but including the position:absolute; will give you a rough approximation.
I've knocked together this quick amendment, which limits based on the document height. I'm not certain that jQuery is giving an accurate height, hence a safety barrier of 100px. Even if the height isn't quite right, any extra scrolling will be limited and certainly not infinite.
<script type="text/javascript">
var documentHeight = 0;
var topPadding = 15;
$(function() {
var offset = $("#sidebar").offset();
documentHeight = $(document).height();
$(window).scroll(function() {
var sideBarHeight = $("#sidebar").height();
if ($(window).scrollTop() > offset.top) {
var newPosition = ($(window).scrollTop() - offset.top) + topPadding;
var maxPosition = documentHeight - (sideBarHeight + 100);
if (newPosition > maxPosition) {
newPosition = maxPosition;
}
$("#sidebar").stop().animate({
marginTop: newPosition
});
} else {
$("#sidebar").stop().animate({
marginTop: 0
});
};
});
});
</script>
I can duplicate your bug in my browser (Firefox 3.5).
The problem is that the code doesn't look to see if the bottom of the sidebar falls off the end of the document.
Your best bet is to use the .height() method to check. You can get the height of the sidebar (as presented in the example) as $("#sidebar").height(), and the height of the whole document as $(document).height().
What exactly the behavior should be -- up to you. It involves an extra if, to make sure all your pixels line up right, but design questions, like how the sidebar should align against the bottom, are going to be a matter of personal taste.

Categories

Resources