I've been banging my head against the wall really hard for the past couple of hours to figure out a way to achieve the layout I'd like for a webapp. And my head hurts.
Basically what I need is to have a full window layout (full width, full height, no scrolling - ever). 100% of width and height should be covered using two different horizontal boxes (you can see them as rows).
The height of the first box/row can be variable (see it as a header for the page)
The one below should occupy what's left of the space, without ever going further than 100% of the window, hence without ever showing a scrollbar.
Now what's a bit more tricky is that within the second box/row, I want content to be displayed with an inner vertical scrolling. Imagine the second box/row contains a list of items, in case of very few items, the bottom part of the box/row should stop right after the content. In case of many items, the box/row should expand right until it hits 100% of the window height (which is basically 100% of the windows - the height occupied by the first box/row). The rest of the content should be visible through scrolling within the second box/row.
Am I making any sense?
Regarding the code, I'm not going to copy/paste the desastrous thing I've pulled together because I'd rather start from a blank page.
This is what I tried:
<html>
<body>
<div id="wrapper">
<div class="box">Header</div>
<div class="box">Content <ul><li>...</li>(x1000)</ul></div>
</div>
</body>
</html>
The reason why I use a "box" class is because both boxes/rows should show the same appearence in terms of backgrounds, margins, shadows, etc.
html, body {
height: 100%;
}
#wrapper {
position: absolute;
height: 100%;
width: 100%;
left: 15px;
right: 15px;
top: 15px;
bottom: 15px;
}
For the rest, I've just tried (and failed so far) to manipulate the .box elements by adding hazardously overflow: hidden; overflow-y: scroll; height: 100%; max-height: 100%; min-height: 100%; etc.
Thanks in advance for your help!
The problem is because CSS has long been crappy about auto-adjusting height to available space.
The solution is to use a wrapper that's set to position: absolute and tied to the top, left, right, and bottom edges of the viewport. With this, the browser will auto adjust the height of the element, and if you have a content div inside with height: 100% it'll always fill that space.
Setting overflow-y: scroll on the wrapper will allow the content to scroll if it becomes too long:
http://codepen.io/helion3/pen/jwbcx
Site headers are usually not variable in height. If you're defining the site header using percentages, and if you don't need to support IE<8 then you can use percentages safely with box-sizing: border-box to achieve the same.
I believe this should do the trick.
If you adjust the height of .header make it is equal to the top: position of .content
CSS:
html, body {
margin: 0;
}
.header {
height: 150px;
background: #0080ff; // (Unnecessary, this is set to help you see the header div)
}
.content {
position: absolute;
top: 150px;
bottom: 0;
left: 0;
right: 0;
overflow: auto;
background: #ff8000; // (Unnecessary, this is set to help you see the content div)
}
HTML:
<body>
<div id="wrapper">
<div class="box header">Header</div>
<div class="box content">Content</div>
</div>
</body>
Maybe you want something like this? I replaced class="box" with ids, but it should work.
Consider following things:
No need to have the "absolute" positioned div (#wrapper in your example)
Create 2 box div same like you have created in your example (.box)
Second box should have "overflow:auto" style property
Calculate the height of header and full display area's height with javascript
Calculate the remaining height and assign this value as height, min-height and max-height for the second box. That's it.
You can check the solution here:
http://webnflash.com/temp/occupyAvailableHeight.htm
Related
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.
<div id="main" style="overflow:hidden;height:80%;>
<div id="header">
</div>
<div id="content" style="overflow:hidden;">
</div>
</div>
I have two divs in the main div, and I want the content div to fill up the remainder of the main div, but if stuff fills up the content div past its filled up height, I don't want the content div to grow any taller.
I've seen some other stackoverflow questions like this, but none of the answers have worked for me. Tried: Make DIV fill remainder of page vertically?, Get CSS Div to fill available height, and How to make a DIV fill the remaining vertical space of the browser window?
I think the main difference is that I require the content div to fill up, but ALSO not overflow. Is this possible with only css?
Update:
I kept trying out different pieces of code and this is what I want: http://jsfiddle.net/zXnnp/. But for some reason I couldn't replicate it on my localhost. And then I found out it was because I was using http://jamesflorentino.github.io/nanoScrollerJS/ And for some reason class="nano" on the content div messed things up. Still investigating on what's wrong.
Update2:
class="nano" has height:100%; so I just overrode it with height:auto; and things are now fine. Thanks for all the help!
You could do something like this:
/* stretch the body to full height */
body, html {
height: 100%;
}
/* stretching the containers */
#header {
height: 50px; /* just a random number i chose, not sure what you wanted here */
}
#content {
height: 100%;
margin-bottom: -50px; /* same as the header height, but negative */
}
You can see the code in action here: http://jsfiddle.net/mRK24/
The magic lies in first stretching you body to viewport height. The #main will then become 80% of the viewport height. Next you give the header some fixed height, and the content you set to a height of 100%, with a negative margin bottom that is the same as the height of the header.
Note that some of your content will be lost, due to the overflow:hidden;. Strange, cause you can not know how much since you don't know the height of your user's viewport. Perhaps you should consider setting the overflow of the content to scroll, cause I can't imagine you would want part of you content to be invisible.
Have you tried using the CSS property max-height? This is from CSS 2 and should not have any compatability issues.
http://www.w3schools.com/cssref/pr_dim_max-height.asp
If you post some editable code then we could play with it and help you find some ways of making it work.
I'm not exactly sure what you're after, but maybe this will get you close:
http://jsfiddle.net/isherwood/TCVvn/1
#main {
height: 80%;
width: 80%;
position: absolute;
}
#header {
height: 50px;
position: relative;
top: 0;
}
#content {
position: absolute;
top: 70px;
right: 5px;
left: 5px;
bottom: 5px;
overflow: auto;
}
<div id="main">
<div id="header">Header</div>
<div id="content">Content</div>
</div>
Keep overflow:hidden on <div id="#main"> and let the content div take as much height as it wants with no overflow restrictions. #main will cut off #content if it gets too tall to fit inside of #main.
So I've seen this post: Can I scale a div's height proportionally to its width using CSS? and it sort of answers my Question. I can get divs to sclae porpotionally as I need. However, what I also need is to set a minimum height for those divs.
In this fiddle http://jsfiddle.net/FBZuB/1/ I have set up what I am trying to accomplish. The BLUE div is a general wrapper that then defines the height of the RED div based on the width of the BLUE div. However when I try to change the min-height on the RED div, the divs that I want to scale AND have a min-height, unexpected results occur.
I would think once I scale DOWN to the min-height point, the div would stop scaling and only change in width. However, it seems like setting the min-height just sets some sort of base point for the whole calculation and everything scales continually. I hope this makes sense.
The RED divs should scale up and down, but at a certain point, when the RED div hits its minimum height, it should stop scaling in height and only in width. I have accomplished this before with pure javascript, but since I read the post above, I am trying to get a CSS only solution.
Here is the code. You can ignore the content for now... I am focuses mainly on the red blocks. Proportionally scale width/height, until it hits the min-height and then it should stop scaling the height and only the width.
HTML
<div style="background: blue; width: 70%;">
<div id="left">
<div class="content"></div>
</div>
<div id="right">
</div>
</div>
CSS
div {
margin: 5%;
float: left;
background: red;
position: relative;
}
#left {
width: 50%;
padding-bottom: 60%;
min-height: 100px;
}
#right {
width: 30%;
padding-bottom: 60%;
min-height: 100px;
}
.content {
position: absolute;
width: 90%;
margin: 5%;
background: green;
top: 0;
left: 0;
height: 90%;
}
Unfortunately plain CSS is unable to calculate any expressions in all browsers except IE, and as such you will have to use at least some JavaScript to dynamically calculate the width.
I would probably do something like this in your html file.
Since you didn't specify how you are resizing your div, I'll assume that it's just when the window resizes.
<body onresize="
var left = document.getElementById('left');
if (left.clientHeight < left.style.min-height) {
left.style.cheight = left.style.min-height;
}
">
</body>
For example, I want this page to have the footer fill to the bottom of the page, but I want this page to behave how it does now - so the footer cannot be fixed. I'd prefer to not use JS simply because $(window).resize() is expensive and performance is a concern for us.
Our lowest supported browser is IE9, Firefox 13, Chrome 16 and Safari 5 so I'm not concerned about using a more advanced solution, though probably not bleeding-edge.
You can't - you have to either calculate the window height and footer top offset (which involves JS), or fix the position of the element to bottom: 0.
You could make the page background color match the footer color, and instead of using the graphic as the background for the whole page, make it only for the content area.
so put the background on main-content-container
and make the body background color #EBEBEB
Here is a way to do it, but it does bring other problems with it. You will need to set a min-height and make sure your content does not exceed that min-height or it may get cut off and all text must be at the top of the second div.
The css:
body,html
{
width: 100%;
height: 100%;
}
div#wrapper
{
overflow: hidden;
height: 100%;
min-height: 600px;
}
div#one
{
background-color: #0ff;
height: 200px;
}
div#two
{
height: 100%;
background-color: #f00;
}
The html:
<div id="wrapper">
<div id="one"></div>
<div id="two"></div>
</div>
So the content on the bottom, would not be able to exceed 400px in height in this example. But, if it was larger than that it would be filled in by a solid color.
I'm trying to get a simple solution for this layout.
This is the simplified html.
<div class='wrapper'>
<div class='header'></div>
<div class='middle'> TEXT </div>
<div class='footer'></div>
</div>
Header and footer have a fixed height in pixels.
middle can have a variable height, depending on the content.
I want wrapper to have a minimum height of 100%. So if the text inside middle is small, the middle div should expand to fill the browser page. And if it's too long, the whole page should be scrollable.
Is this possible easily? Maybe changing something in the layout?
here's your solution: http://jsfiddle.net/S4akv/1/
You do NOT want to set a hard height for the .middle. If your content is only a few lines then you will end up with scrollbars where none are needed.
With a header and footer, you also don't want height: 100% on your .middle class because it will push your footer down, forcing a scrollbar no matter what. You also don't want a clear-cut height:100% because most browsers will interpret this as 100% of the browser height, so when you resize your browser to be larger, either the height won't change or the footer won't move.
The best solution here is to have your wrapper and any associating backgrounds attached to that. Depending on the content within your .middle div this answer could change, but given the simple parameters this is the most elegant way to do it.
the secret is to make sure that all containing elements have a height set. reason being, any block element with height: 100% will only be 100% of the area containing it. in this case you need to set height for middle, wrapper and body, html
body,html { height: 100%; margin:0; padding:0; }
.wrapper { min-height: 100%; width: 100%; background-color: red; position:relative; padding-bottom: 200px; }
.header { height: 200px; width: 100%; background-color: blue; }
.middle { }
.footer { height: 200px; width: 100%; background-color: green; position:absolute; bottom: 0; }
If you have nested content within .middle that also needs to be 100% height there is a better way, using a combination of height, absolute positioning and negative margins. There are a million ways to skin a cat. Well, a handful at least :)
edited to add padding to .wrapper to make room for footer. The bottom padding of wrapper must be the same height as the footer