I'm creating a div as a footer as such:
<div class="content">blah blah blah</div>
<div class="content">more content</div>
<div class="content">even more content</div>
<div id="footer">blah blah blah</div>
The CSS for the footer is as follows:
#footer{
height: 50px;
display: block;
position: absolute;
right: 0;
left: 0;
bottom: 0;
}
So how do I leave a 50px space between content and footer? I've tried adding a spacer div between the two but yielded no success. The spacer div needs to be more than the height of content for it to have any effect. I've tried margin-top to #footer, which didn't work, but I do not want a margin-bottom for content because the content containers are multiple. Setting a bottom margin for the content would ruin how they render. Thanks for any help.
P.S. this is not a duplicate to Set position absolute and margin.
Okay, let give this a spin.
Maybe this helps you a bit on your way:
http://codepen.io/bbredewold/pen/avgZmj
It would help if you describe the behaviour you want to achieve, including how the page should respond at different sizes. Maybe you can fork (copy) the pen, and make some additions to help us understand your problem.
Good luck!
.outside {
position: absolute;
overflow: scroll;
background: #ccc;
bottom: 100px;
left: 0;
right: 0;
top: 0;
}
.content {
outline: 1px solid blue;
}
#footer {
outline: 1px solid red;
background: #ccc;
height: 50px;
display: block;
position: absolute;
right: 0;
left: 0;
bottom: 0;
}
<div class="outside">
<div class="content">blah blah blah</div>
<div class="content">more content</div>
<div class="content">even more content</div>
</div>
<div id="footer">blah blah blah</div>
Ya, it won't work like that. Because you've given #footer an absolute position, its position bears no relation to the position of the other elements in the document.
No amount of margin or padding will show between 2 things that aren't in relation to each other.
EDIT: From your comments below, what you are looking for is a static footer
#footer{
height: 50px;
display: block;
margin-top: 50px;
}
I'm such a SO noob I can't comment for more info :| . I assume you may be trying to achieve a fixed / sticky footer where the footer always appears at the bottom of the page? If you could provide an example of the effect you are trying to achieve I would be happy to edit my answer with more specific information.
Anyway because you are using absolute positioning the element is taken out of the document flow and it wont affect any other elements on the page. This means margins wont work. The same is true for fixed positioning, which is what you actually want if you are making a basic sticky footer.
If you want margin to have any effect on an element you need to set the elements display property to be a block level element (block, table, inline-block etc etc) and its positioning to either static (default) or relative.
The cleanest method for robust sticky footers is using flex box. Note the use of semantic html tags and classes instead of id's
<style>
/**
* 1. Avoid the IE 10-11 `min-height` bug.
* 2. Set `flex-shrink` to `0` to prevent Chrome, Opera, and Safari from
* letting these items shrink to smaller than their content's default
* minimum size.
*/
.site {
display: flex;
flex-direction: column;
height: 100vh; /* 1 */
}
.header,
.footer {
margin-top: 50px;
flex-shrink: 0; /* 2 */
}
.content {
flex: 1 0 auto; /* 2 */
}
</style>
<body class="site">
<header class="header">…</header>
<main class="content">…</main>
<footer class="footer">…</footer>
</body>
Courtesy of Phillip Walton http://philipwalton.com/articles/normalizing-cross-browser-flexbox-bugs/
Note that this only works for newer browsers so if you are supporting old versions of IE you will need to use a fixed positioning based sticky footer, or forget sticky footers all together.
Related
I am currently encountering a tricky issue with hashed anchor links.
Here is a simple representation of my HTML code :
<div class="main-wrap">
<header></header>
<aside>
<nav>
<ul>
<li>Article1</li>
<li>Article2</li>
<li>Article3</li>
</ul>
</nav>
</aside>
<section>
<article id="article1">Content Here</article>
<article id="article2">Content Here</article>
<article id="article3">Content Here</article>
</section>
<footer></footer>
and the CSS :
body{overflow: scroll;}
.main-wrap{
overflow: hidden;
position: relative;
}
header{
position: relative;
z-index: 3;
height: 10vh;
}
aside{
position: fixed;
width: 22%;
height: 84vh; /* Equal to 100vh - (header + footer)vh */
top: 10vh;
left: 0;
bottom: 6vh;
}
section{
position: relative;
min-height: 84vh; /* Equal to 100vh - (header + footer)vh */
width: 78%;
left: 22%; /* Equal to aside width*/
}
footer{
position: relative;
z-index: 3;
height: 6vh;
}
I've created a sidebar menu with hashed links to have a scrolled navigation, wich as far as I've been is working. But when I'm clicking on the hashed anchors, all the elements are moving a little further top, including header and footer and are hidden by the overflow:hidden; property of the .main-wrap element. In addition when I go back to the non-hashed page, the issue is still running unless I reload it.
I can't find any clue of how I can fix it. Any ideas ?
Edited : I also use a reset.css that is setting the body and html padding and margin to 0.
Edited 2 :
I think I know what's going on. By clicking on an anchor-link the body is forced to scroll the .main-wrap div and that's why everything looks like it has moved top. In fact the overflow:hidden; property of .main-wrap has just moved a little further down and is hiding the wrong parts.
Default Browser Behavior:
When you click on a named or hashed link, the browser will try to scroll to have the target named link at the top of the view.
This is what is happening with your code too.
Another browser default:
Most browsers have default margins and padding greater than 0 for the HTML elements, including the html and body elements.
Your calculation of height: 84vh; /* Equal to 100vh - (header + footer)vh */ will cause the content height to be more than the viewport height if the html and the body tags have margins or paddings greater than 0 (and make it scrollable since you have body {overflow: scroll;}).
Solution:
Use a css reset, or in your case simply add this to your css
html,
body {
margin:0;
padding:0;
}
Demo https://jsfiddle.net/vkrhnf75/1/
I'm running into a minor issue with one of the elements on my page. I have a sidebar which I am attempting to have span the height of the page by using the following CSS:
#sidebar {
width: 180px;
padding: 10px;
position: absolute;
top: 50px;
bottom: 0;
float: left;
background: #eee;
color: #666;
}
The corresponding CSS is pretty much what you'd expect:
<div id="header">
The header which takes up 50px in height
</div>
<div id="main-container">
<div id="sidebar">
The sidebar in question
</div>
<div id="main-content">
The rest of my page
</div>
</div>
The code works as expected for the most part. When the page renders it spans 100% of the height (minus the 50px from the top). The problem is that it essentially assigns the box to the exact height of the window so as I scroll down the box scrolls away instead of staying locked to the bottom of the window. Any ideas how to resolve this?
You have to use position:fixed if you want for the sidebar to be fixed on some position:
#sidebar {
width: 180px;
padding: 10px;
position: fixed;
top: 50px;
bottom: 0;
background: #eee;
color: #666;
}
JSFiddle
Another way would be to give to the parent container position:relative, and on his child position:absolute - but then the parent must have some height so the child element takes its height.
html,body{
position:relative;
height:100%; /* some height */
}
#sidebar{
width: 180px;
padding: 10px;
position: absolute;
top: 50px;
bottom: 0;
background: #eee;
color: #666;
}
JSFiddle
Check learnlayout to read more about positioning.
use css position:fixed to make the sidebar fixed.
in order to lock the height according to screen height i would use javascript/jquery:
$(function(){
// assign to resize
$(window).resize(set_height);
});
function set_height() {
$('#sidebar_id').height($(window).height());
}
hope that helps
First of all, I don't understand how it's spanning 100% of the height when no height has been defined.
Secondly use position: fixed instead of absolute.
On a second note, I'd like to recommend what seems a more proper way of going about positioning this. At the end of the main-container div, before it's closing tag, put this
<div style="clear: both;"></div>
and make the main container also float left, or float right if that doesnt give you what you want. It's suprising how such a common layout can feel tricky to do properly. (at least for newbies like us). I might be wrong, this might not be a better way, but it's the way I'd do it. The extra div you add is so that floated divs take up space, apart from that if it doesn't work, give the sidebar a height of 100%, or if you think it will overflow, tell me I'll add to my answer.
I've trying to get a layout where a a fixed-height table with two rows, the first scaling to the its content, and the second being the remaining height, and keeping its contents inside it. The height of the bottom part needs to be 'real' (not clipped by a parent or anything), such that it could have overflow: scroll, or children of height: 100%, etc.
This is what it should look like:
I got it working in Chrome, using an absolutely positioned div inside a relative table-cell:
http://jsfiddle.net/9FPqx/
The core of it:
html:
<div class="row">
<div class="cell">
<div class="absolute-fill">
Stuff
</div>
</div>
</div>
css:
.row
{
display: table-row;
}
.cell
{
display: table-cell;
position: relative;
}
.absolute-fill
{
position: absolute
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
overflow: hidden;
}
With another intermediary relative div between the table-cell and the content (rather than setting relative on the table-cell itself), it works in Firefox:
http://jsfiddle.net/sXHry/
It does not work in IE. I need IE >= 9.
It seems like IE thinks the relative element with absolute child has no content height, and so gives it 0 height.
I feel like I'm so close but so far. Is there a way of solving this with just html and css? Am I on the wrong track using display: table? Or should I give up and just throw some javascript at it?
Why does it need to be a table? Can't you just let the container hide the overflow?
html
<div class="container">
<div class="top">
Top, green area
</div>
<div class="bottom">
Bottom, blue area
</div>
</div>
css
.container {
width: 250px;
height: 162px;
overflow: hidden;
background: lightblue;
}
.top {
background: lightgreen;
}
http://jsfiddle.net/sXHry/1/ and http://jsfiddle.net/sXHry/2/ (less content)
I suspect i might be missing something, looking forward to being enlightened ;)
Update - I've decided against the JavaScript solution. The only way to make sure it always works is to put it in setInterval() going every few seconds. Don't want to do that. I know this CSS is possible, I've seen it work. I'll re-open the bounty for more like 150 if it ends.
I have a modal popup made up of two sections: left and right. Within both sections are a label above and the content below. The label is fixed at a certain number of pixels, but the bottom area needs to be able to fill the remaining space, so I'm using display:table on the left and right sides and display: table-cell on the inner sections to achieve the "fill remaining space" effect. It works great in Chrome and Safari.
Here's the CSS:
#tagBoxLeft,#tagBoxRight {
display: table;
height: 100%;
width: 50%;
position: absolute;
right: 0;
opacity: 0;
}
#tagBoxLeft { left: 0 }
#tagBoxDescription {
display: table-row;
-webkit-border-top-left-radius: 20px;
width: 100%;
word-break: break-all;
word-wrap: break-word;
-webkit-box-shadow: 0 1px 0 #FFF;
-moz-box-shadow: 0 1px 0 #FFF;
box-shadow: 0 1px 0 #FFF;
}
.nano {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
display: table-cell;
}
#taglabel {
display: table-row;
z-index: 10000;
border-top: 1px solid #FFF;
width: 100%;
height: 39px;
}
And it just makes a bunch of divs into a table so they can have heights that are relative to each other. Also notice that the left and right sides are relative to the browser window, so that's why I can't just use percentages.
However, in Firefox and Opera, the #tagBoxLeft and #tagBoxRight sides sections refuse to accept height:100%; while they have display:table;. So it won't force the bottom sections up responsively.I know Firefox & Opera support this normally (see http://jsfiddle.net/Qxswa/). But why does all my content overflow in Firefox and Opera?
Here's a screenshot of the issue:
Is there a reason why you can't simply use JavaScript to calculate the correct height and apply it inline? It's not as nice and simple, but it would be trivial for what you are describing.
var boxHeight = $('#tagBox').height();
var leftLabelHeight = $('#tagBoxDescription').height();
$('#tagBoxPopular').css('height', boxHeight - leftLabelHeight + 'px');
var rightLabelHeight = $('#taglabel').height();
$('#tagBoxStream').css('height', boxHeight - rightLabelHeight + 'px');
Here's an alternative to using display:table and friends, which uses the oft-neglected ability of absolutely positioned elements to have both their top and bottom (and left and right) values set. It essentially 'sticks' the top and bottom edge, giving you a height relative to a container, but without explicitly setting a height.
UDPATED: As Jackson mentioned, the CSS-only version of this code doesn't provide an auto-height, fixed panel in the column. A simple bit of JS will fix that - you'd just need to set a sensible default height for users without JS. The JS only needs to run when you load the modal, not at intervals.
Here's the updated fiddle: http://jsfiddle.net/cxY7D/5
and here's the simplified HTML:
<div id="modal">
<div class="left">
<div class="description">
<h1>#tag_name</h1>
<dl>
<dt>Tags</dt> <dd>27</dd>
</dl>
</div>
<div class="contents">
<div class="header">
<h2>Featured</h2>
</div>
<ol>
<li>Something Something</li>
<li>...</li>
</ol>
</div>
</div>
<div class="right">
<div class="contents">
<div class="header">
<h2>Recent</h2>
</div>
<ol>
<li>Something Something</li>
<li>...</li>
</ol>
</div>
</div>
</div>
and CSS:
body {
background:#444;
}
#modal {
background:#FFF;
position: absolute;
top: 4em;
bottom: 4em;
left: 6em;
right: 6em;
}
#modal .left,
#modal .right {
position:absolute;
top: 0;
bottom: 0;
}
#modal .left {
background:#ACF9E4;
left: 0;
right:50%;
}
#modal .right {
background:#FCFFCD;
right: 0;
left:50%;
}
#modal .contents {
position:absolute;
top: 0;
bottom: 0;
width: 100%;
overflow-y:auto;
}
#modal .description {
height: 8em;
}
#modal .description + .contents {
top: 10em;
}
#modal .header,
#modal .description,
.contents li {
border-bottom:1px solid #CCC;
padding: 1em;
}
#modal .description dt {
float: left;
padding-right: 1em;
}
It's a really useful and robust technique. A lot of people get the shudders when you mention 'absolute positions', but used like this, it's really liberating!
The JS (assuming jQuery)
$(function(){
$('#modal').on('display', function(){
//Calculate the height of the top left panel, and provide the remaining space to the bottom left
var leftColumn = $(this).find('.left'),
descriptionHeight = leftColumn.find('.description').height('auto').outerHeight(); //Set the height to auto, then read it
leftColumn.find('.contents').css('top', descriptionHeight)//Apply the height to the scrolling contents pane
});
$('#modal').trigger('display');
});
The JS resets the top-left pane to auto-height, then reads the height and applies it as the top co-ordinate of the bottom-left panel. It's applied as a custom event, so you can trigger it as part of your modal display code.
Here's an answer I gave, using a similar technique, and more explanations of the hows and whys: The Impossible Layout?. Check the A list apart article for more discussion, and some simple fixes that make it work in IE6 (if you care about that).
I open your site on firefox and the hashtag links i see with chrome are gone. Are you doing some fix-attempts right now? If you put the links back in for the ff version I can help you debug this.
UPDATE:
What I see is a highly overcomplicated mix of display:table's and display:table-cells's with absolute and static positionings combined with percentual heights and many other highly cross-browser volatile mixes.
Doing lots of patching and fixing I was able to get this:
There's obviously many errors still present but at least you get some scrollbars.
Basically, the problem is that you're relying upon percentual heights and shady table-displays that are seemingly not very evenly rendered by different browsers.
We have two options here:
1.- Keep your original css/html approach and troubleshoot the JS scrollbar.
2.- Go for a much much much simpler css/html variant
Cheers
G
You may want to look at how you're using <section>. It is not the same as a <div>.
W3C - Using HTML5 section elements , and header elements.
<header> appears the same. They're both flow elements, and not designed as content containers, but as semantic structuring elements for content containers.
I used Firebug and changed both <header> and <section> to display:block on a hunch. Things started to shape up; however I could not get the scroll effect to fire after those changes. I then changed <header> in safari to display:inline. Sure enough - both my browser windows looked like this:
You need to have the #tagboxleft and #tagboxright's overflow hidden. This can be done by setting #tagbox to overflow:hidden, however that will hide part of the close button. so you need another div wrapped around the left and right but not the x with overflow:hidden.
Like so:
<div id="tagbox">
<div id="tagboxX"></div>
<div id="tagboxleftright" style="overflow:hidden"> <!-- This is the wrapper div around tagbox left & right. Of course, move overflow:hidden to the style sheet -->
<div id="tagboxLeft"></div>
<div id="tagboxRight"></div>
</div>
</div>
This worked in Firefox and it should work in Internet Explorer.
I'm designing a website which has fixed elements on the outer edges of a fixed-width layout. A div in the center is reserved for the content.
When the user scrolls, I want all of the content (besides said fixed outer navigation elements) to stay within the borders of that center element.
Here's a quick mockup of what I mean:
I could very easily set the overflow property of the center element to auto, and have everything remain inside. However, it's very important that a scroll bar not be present on the edge of that element.
Basically, I'm wondering how to either:
Restrict content to that area
(perhaps I could change the size and
positioning of the body element -- is
that allowed? -- and then position
the fixed elements outside of the
body.
Hide the scroll bar that appears
inside the div when using
overflow:auto
Any help would be greatly appreciated!
If possible, you should break your fixed position elements up into 4 separate sections (top, left, right and bottom). Then just make sure you pad you centre content area by their respective widths and heights so the content doesn't get overlapped:
HTML
<!-- 4 fixed position elements that will overlap your content -->
<div id="top"></div>
<div id="left"></div>
<div id="right"></div>
<div id="bottom"></div>
<div id="content">
<!-- Your content -->
</div>
CSS
html, body {
height: 100%;
}
#top, #left, #right, #bottom {
position: fixed;
left: 0;
top: 0;
z-index: 2;
background: red;
}
#top, #bottom {
width: 100%;
height: 20px;
}
#bottom {
top: auto;
bottom: 0;
}
#left, #right {
height: 100%;
width: 20px;
}
#right {
left: auto;
right: 0;
}
#content {
position: relative;
z-index: 1;
padding: 25px; /* prevent content from being overlapped */
}
You can see it in action here.
Also note the position: relative on the content area. This is so z-index works correctly and the content is displayed below the fixed sections.
If you care about IE6/7 support, you'll need to add a CSS expression fix to get fixed position working properly in those awesome browsers.