I'm trying to make this template have a fixed navbar: here
I'm a beginner at CSS, so sorry about the silly question. When I try to make .masthead have position:fixed, the "Home About Contact" part disappears.
Thanks in advance!
The problem:
When you set position:fixed, the width of the masthead becomes the size of the elements inside by default. Usually you would be able to declare width:100% on the masthead so it stretches the entire width of the parent div, but in this case, setting percentage width on the fixed element makes it calculate based on the width of the viewport: see here for more details:
Percentage width for fixed elements?
Since the rest of the content has a max-width of 700px, we can set the width of the masthead to also be 700px but the issue is when you shrink the viewport, the rest of the page will shrink but the masthead won't. Setting max-width on the masthead doesn't work because its original width is less than 700px.
.masthead {
position: fixed;
width: 700px;
top: 0;
background-color: white;
border-bottom: 2px solid rgb(220,220,220);
}
Note that we set the background to white otherwise the bar will by default have a transparent background and the elements underneath will just intersect -- very ugly. We set the top property to 0 so it is now attached to the top of the page and doesn't leave a gap when we scroll.
(The border I added was just for looks, you can remove that if you'd like.)
Since we set the masthead to fixed positioning, it is now removed from the page flow, so everything else in the page acts like the masthead wasn't there. That leads to an issue: everything in the page shifts up, and one of the <hr />s on the top becomes hidden. To solve this, we add a margin-top: 50px; to the top <hr />, and everything is shifted downwards.
Due to the default margin styling (margin-bottom: 20px;
margin-left: 0;) on .navs in bootstrap the "Home About Contact" section ends up looking a bit awkward. We fix this by setting the margins to something more appropriate: margin: 14px 0;
Quick Note: I applied all these styles as inline in the chrome web inspector, so that they would override any other properties
Edit: Actually, it works nicely too if you just delete the HR from the document with the web inspector
First, you need to add some CSS to the header so it can be used as a fixed header. It needs a background color, and a given width:
.masthead {
width: 700px;
background: white;
}
Then, because the header is not aligned with the top of the page, you'll need some javascript to make it stick to the top:
<script>
$(document).ready(function() {
var div = $('.masthead');
var start = $(div).offset().top;
$.event.add(window, "scroll", function() {
var p = $(window).scrollTop();
$(div).css('position',((p)>start) ? 'fixed' : 'static');
$(div).css('top',((p)>start) ? '0px' : '');
});
});
</script>
Look at the boostrap navbar docs
Here is an example of a fixed navbar using bootstrap:
<div class="navbar navbar-fixed-top" style="position: absolute;">
<div class="navbar-inner">
<div class="container" style="width: auto; padding: 0 20px;">
<a class="brand" href="#">Title</a>
<ul class="nav">
<li class="active">Home</li>
<li>Link</li>
<li>Link</li>
</ul>
</div>
</div>
</div>
This is a navbar that works with position: fixed:
<div class='container'>
<div class='navbar'>
<div align='right'> <a class='menu1 menu-item'>Home</a>
<a class='menu2 menu-item'>About</a>
<a class='menu3 menu-item'>Contact</a>
</div>
</div>
</div>
http://jsfiddle.net/H9mMk/3/
Related
I've a sidebar which is positioned sticky but in some cases larger than the height of the screen.
If the sidebar is in fact larger as the screen height, I don't want it to stick on the top. It should scroll down with the content of the page.
I'm using Bootstraps sticky-top class for that.
It has the following attributes:
.sticky-top {
position: sticky;
top: 0;
z-index: 1020;
}
I changed the top: 0 to top: 50px in my case because I need the space above.
Here's some example code: https://codepen.io/cray_code/pen/ZEaOXwo
<div class="container">
<div class="row">
<div class="col-lg-3">
<div class="toc sticky-top">
<nav class="list-group">
Links (see example)
</nav>
</div>
</div>
<div class="col-lg-9">
Content (see example)
</div>
</div>
</div>
I tried the solution from here and added the following code to my class:
.toc {
overflow-y: auto;
max-height: 100vh;
}
But that doesn't help.
Is there a pure CSS solution for that or do I need to use JavaScript?
Not sure if this is what you want, but maybe using the calc() in your css could help you.
.toc{
overflow-y: auto;
max-height: calc(100vh - 50px);
}
Hope this pen helps
Some explanations:
in js we use .offsetHeight&.clientHeight to get height we check weather this height(493px) + 50px offset is more than screen height or not.
When screen size is small we set position to static
Also we set margin-top: 50px instead of top: 50px
because top works only for sticky and margin-top works for static
For aside blocks that higher then window height you can use smartSticky script
Just add "data-smartsticky" atribute to your aside block
https://www.npmjs.com/package/smartsticker
Parent block of sticky block must be height 100%, or for flex - flex-grow:1
I have the following HTML,
header {
background: #f6f6f6;
width: 100%;
min-height: 120px;
position: fixed;
z-index: 100;
top: 0;
padding: 5px 0;
}
<header>
<div class="container">
<div class="row">
<a href="index.html">
<img src="images/logo.png" class="img-responsive" alt="">
</a>
</div>
</div>
</header>
As you can see it is a fixed header and I've given it a min-height of 120px. This makes the header overlap the content below and I've prevented that by giving the div that wraps the content a margin-top of 90px.
This works fine on larger layouts but when the layout gets smaller and the image starts re-sizing(due to the .img-responsive class) its height reduces and it results in an empty space below it. I could write a media query and reduce the margin-top but I was wondering if there is some other way to prevent this from happening.
You can use JS to update the margin based on the header size on page load.
$(function() {
var headHeight = $('header').outerHeight();
$('.welcome-home').css({'margin-top': headHeight });
});
This will get the total height of the header element and then apply that size as margin-top to .welcome-home.
Here's a fiddle: https://jsfiddle.net/13n7mpbk/
If you try adding to the header, it will automatically increase the margin as needed when the page is loaded.
This problem arises when you are using a position:fixed top nav bar: Since the nav bar is out of the document flow, the initial content that you put after it will be hidden by the nav bar itself. This fiddle shows my solution which uses an extra spacer div and padding-top:
http://jsfiddle.net/MFwJT/
html
<div class="fixednav">some nav stuff</div>
<div class="navspacer"></div>
main content which should not be covered by nav
css
.fixednav { position:fixed; width: 100%; height: 30px; background: #999 }
.navspacer { padding-top: 30px; } /* This works */
2 questions
Is there a better solution?
If you change padding-top to margin-top, the nav bar behaves as if the spacer came before it rather than after it. I'd like to know why this happens.
To clarify question 2, margin-top produces this:
whereas padding-top produces this (the correct behavior):
Is there a better solution
IMHO, better solution would be to avoid a fake spacer div navspacer and instead, go with the span as you can easily achieve your target with a single div, using line-height and without a fake div
Example Fiddle
CSS
.fixednav {
width: 100%;
height: 30px;
background: #999;
line-height:90px; /*this is the key here*/
}
.fixednav > span {
position:fixed;
display:block;
width:100%;
line-height:30px;/*this is the key here*/
}
HTML
<div class="fixednav">
<span>some nav stuff</span>
main content which should not be covered by nav
</div>
Question 2
If you change padding-top to margin-top, the nav bar behaves as if the spacer came before it rather than after it. I'd like to know why this happens.
when you give the padding-top: 30px;, it is applied to the inside of the content area, making the whole div height (30px + if anything is in content), check this demo to see it
when you give margin-top: 30px;, it is applied to the outside of the content, demo and the contents overlap as FIXED position divs do not follow the document flow but the viewport flow!!
The problem here is that you fixed the position of the fixednav but not the navspacer. When you do this, the fixednav and navspacer are on the same line since one is fixed and not the other. When you add padding to the navspacer, it pushes away the fixednav from it. When you add margin-top:30px; it moves the fixednav and navspacer together. To fix this, add a fixed position to the navspacer and add the content to the fixed navspacer:
/*html*/
<div class="fixednav">some nav stuff</div>
<div class="navspacer">main content which should not be covered by nav</div>
/*css*/
.fixednav { position:fixed; width: 100%; height: 30px; background: #999 }
.navspacer { position:fixed; margin-top: 30px; }
This will give you the correct behavior you are looking for.
Here is a link: http://jsfiddle.net/4vAgZ/
Also, this picture should help you with the padding vs. margin thing.
http://s3.amazonaws.com/codecademy-blog/assets/ae09140c.png
Hope this helps.
You can use a div for spacing like youtube does.
Here i made an example wich uses javascript to listen on window resizes and adjusts the spacer if necessary.
But you can also use this jQuery plugin for every single div.
//initial adjustment
$(function () { $('#topSpacer').height($('#fixedtop').height()); });
//adjustment on every resize event
$(window).resize(function () {
$('#topSpacer').height($('#fixedtop').height());
console.log("<div>" +$('#topSpacer').height() + "</div>");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<div id="topSpacer"></div>
<div>
Does anyone overlay me?
</div>
<div id="fixedtop" style="position:fixed; top: 0px;">
Top navbar elements Page0000000000000 Page11111111111111 Page2222222222222
</div>
<div>
Another relative element
</div>
I've successfully used the beautiful Susy grid system to create a responsive layout similiar to the one of WebDesignerWall.com:
What i failed to implement is a position:fixed sidebar.
Such a sidebar would not scroll when the page is scrolled and stays on the same place. That's fantastically convenient (anyway, you actually can't put more content into the sidebar, because it would clutter the top of page in a narrow window).
My layout goes crazy whenever i apply position:fixed to a column:
The colored blocks are declared three-column wide, but stretch further when position:fixed is applied to the sidebar..
I think the problem is that the width of the sidebar is relative, i. e. set in percentage. Due to position:fixed, the width is measured against the width of the browser window, not its container (though i set the container to position:relative).
The question is: how do i make a column fixed to the window while measuring its width against its container, not the viewport?
Maybe it's possible to fix the position of an element with JS?
PS I've tried the width: inherit solution, but it wasn't of any help to my situation.
The way to do it is with a second container. I don't know your exact code, but here's an example. Let's assume your structure is something like this:
<div class="page">
<header class="banner">
<h1>header</h1>
</header>
<nav class="navigation">
<ul class="nav-inner">
<li>navigation link</li>
</ul>
</nav>
<article class="main">
<h2>main content</h2>
</article>
<footer class="contentinfo">
<p>footer</p>
</footer>
</div>
The only important assumption I made there was ensuring an extra wrapper around my navigation sidebar. I have both the <nav> tag and the <ul> tag to work with. You can use any tags you want, as long as the sidebar has two that can be used for structure - the outer for a fixed container, and the inner for the sidebar itself. The CSS looks like this:
// one container for everything in the standard document flow.
.page {
#include container;
#include susy-grid-background;
}
// a position-fixed container for the sidebar.
.navigation {
#include container;
#include susy-grid-background;
position: fixed;
left: 0;
right: 0;
// the sidebar itself only spans 3 columns.
.nav-inner { #include span-columns(3); }
}
// the main content just needs to leave that space open.
.main { #include pre(3); }
// styles to help you see what is happening.
header, article, .nav-inner, footer {
padding: 6em 0;
outline: 1px solid red;
}
Cheers.
You can't, fixed-position elements are detached from their containers, position: relative or no position: relative. Just set its width to an absolute value - it looks like your content is always 760 pixels wide, right?
Maybe it's possible to fix the position of an element with JS?
Yes, but it will be tedious and isn't the ideal solution .
Instead, calculate the appropriate width using JavaScript and assign it, instead of using the percentage directly in CSS. Here's a basic outline:
function updateSize() {
var outer = document.getElementById("outercontainer"); //get the container that contains your sidebar
var navcol = document.getElementById("navcol"); //get the sidebar (which is supposed to have position: fixed;)
navcol.style.width = Math.floor(outer.offsetWidth * 45/100) + "px"; //or whatever your percentage is
}
updateSize();
window.onresize = updateSize; /*make sure to update width when the window is resized*/
Note: the IDs used above are just placeholders -- you will need to modify them to fit your actual page.
Why don't you just use math? =)
Example html:
<div class="container">
<div class="col">
<div class="fixed">This is fixed</div>
</div>
</div>
CSS
.container {
width: 80%;
margin: 0 auto;
}
.col {
float: left;
width: 33.3333333333%;
}
.fixed {
position: fixed;
width: 26.666666666%; /* .container width x .col width*/
}
position:fixed works like position:absolute so it isn't positioned in relation of its container. It simply floats into your document.
A quick fix would be something like this:
<div id="fixed-element" style="width:30%"> /* 30% of the document width*/
lorem ipsum dolor sit amet
</div>
<div id="faux-sidebar" style="width:30%; display:block"> /* 30% of the document, leave it empty, so it acts like a placeholder for the fixed element*/
</div>
<div id="the-rest" style="width:70%"> /* the rest of the website goes here */
more lorem ipsum than ever before
</div>
Here is a preview of what I have so far:
The red area is part of the design and should always scroll down with the design. So when the content expands, the footer, and that red bar go with it. This should be at the very bottom of the window.
I tried positioning it absolute and it worked perfectly, except when I re-sized my browser and made it smaller, it would stay at the very bottom but would only work when the browser is in full screen.
What I am doing right now is just positioning it relative with top:-120px; and then as you can see, it gives me the extra whitespace that I want to get rid of.
footer { height:185px; background:url(../images/footer_bg.png) repeat-x; position:relative; z-index: 0; top:-115px; width:100%; }
Not sure what else code to paste, I think that's all everyone needs. The rest is self explanatory. Does anyone have any suggestions on how to approach this?
My goal is to get it just like the image above except without the whitespace, pushed down at the bottom at all times, even when the browser is re-sized.
we use a sticky footer as well - here's the basics:
<div id="container">
<div id="header">Header</div>
<div id="nav">
<ul>
<li>Home</li>
<li>Page 1</li>
<li>Page 2</li>
</ul>
</div>
<div id="content">Content Here.</div>
<div class="clearfooter"></div>
</div>
<div id="footer">Footer Here.</div>
Note the clearfooter before the end of the container. Then with CSS you need something like this:
html, body {
height: 100%;
}
#container {
min-height: 100%;
margin-bottom: -330px;
position: relative;
}
.clearfooter {
height: 330px;
clear: both;
}
#footer {
height: 330px;
position: relative;
}
The only downside is that this is a fixed height footer. Don't forget, too if you add any padding to your footer that increases the height and your height on the footer, clearfooter and negative margin on the container need to be adjusted accordingly.
If you happen to need it to work in IE6 you'll need to target the container however you'd like and use:
#container {
height: 100%;
}
Hope that helps!
Sticky footers can be tricky and adding an over lapping background can be even more tircky. What you might want to try is creating a Sticky footer and applying the background image to the body or container background repeating-x and position bottom.
Are you able to create a jsfiddle and I can show you the technique I mean.
When you are offsetting something with position: relative, the element still "reserves" the space it would have occupied otherwise - in your case, the bottom area where you get the whitespace. Set margin-bottom: -115px on your footer to tell it not to do that.