CSS layout with header, footer and multiple 100% min-height content columns - html

This is what I want to achieve:
Footer should stay at the bottom of the screen even if the content doesn't fill the viewport vertically.
Content columns have a border that should always be 100% content height. As the number and width of columns will change from page to page, background-image to fake column borders can’t be used.
There should be no scrollbars when all content is visible (Example 1).
Solution should be all HTML/CSS, no JS.
Minimum browser support should be IE9+ and latest desktop versions of Firefox, Chrome, Safari, Opera; with no quirks mode.
Width of the header/footer/content is always fixed (so header and footer don’t need to be placed inside content area). Height of header and footer is also fixed.
I’ve tried techniques from Fluid Width Equal Height Columns and this sticky footer example but haven’t been able to satisfy all the requirements at the same time. Any tips are appreciated.
Edit: So far the farthest I’ve got is by imitating tables which works correctly in webkit browsers but not in IE9 and Opera. See the fiddle here.
HTML:
<div class="table outer">
<div class="row header">
<div class="cell">header</div>
</div>
<div class="row content">
<div class="cell">
<div class="table inner">
<div class="row">
<div class="cell">content 1</div>
<div class="cell">content 2</div>
<div class="cell">content 3</div>
</div>
</div>
</div>
</div>
<div class="row footer">
<div class="cell">footer</div>
</div>
</div>
CSS:
html, body {
height: 100%;
}
.table {
display: table;
min-height: 100%;
height: 100%;
}
.table.outer {
width: 500px;
margin: 0 auto;
}
.row {
display: table-row;
}
.cell {
display: table-cell;
}
.header, .footer {
height: 25px;
background-color: #999;
}
.content {
background-color: #eee;
}
.table.inner {
width: 100%;
min-height: 100%;
height: 100%;
}
.table.inner .cell {
width: 33%;
border-right: 1px dashed #c00;
}

While not a semantically desirable solution, the only way I could find to achieve all stated requirements is to go back to the 90s and use tables for layout.
See the fiddle here.
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<table class="outer">
<tr>
<td class="header" colspan="3">header</td>
</tr>
<tr class="content">
<td>content1</td>
<td>content2</td>
<td>content3</td>
</tr>
<tr>
<td class="footer" colspan="3">footer</td>
</tr>
</table>
</body>
</html>
CSS:
html, body {
height: 100%; margin: 0;
}
.outer {
min-height: 100%;
height: 100%;
width: 500px;
margin: 0 auto;
}
.header, .footer {
height: 25px; background-color: #999;
}
.content td {
width: 33%;
background-color: #eee;
border-right: 1px dashed #c00;
vertical-align: top;
}

Try this :
#footer {
position:fixed;
left:0px;
bottom:0px;
height:30px;
width:100%;
}
/* IE 6 */
* html #footer {
position:absolute;
top:expression((0-(footer.offsetHeight)+(document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight)+(ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop))+'px');
}

In case anyone is interested, I figured out a solution that uses jQuery (instead of tables).
http://benpearson.com.au/web-development/3-column-fluid-layout-with-header-sticky-footer-and-100-percent-height-columns/

Related

Flex-box Footer Element Centered

I'm making a user-resizable GUI window with a header that gains height through new elements, a footer with static height, and a spacer in between that automatically takes up the rest of the height. I attempted using this answer, but the footer ended up vertically-centered. Picture:
If anyone knows why off the top of their head, it would be greatly appreciated. The element is being added to the page with javascript so the code is pretty messy. Thank you for your time.
What about the following:
<body>
<header class="header"></header>
<main class="spacer"></main>
<footer class="footer"></footer>
</body>
.
html {
height: 100%;
}
body {
display: flex;
flex-direction: column;
min-height: 100%;
}
.spacer {
flex: 1;
}
I still don't know what the issue was, but I made a solution using the css calc() function.
HTML:
<div id="myWindow">
<div id="header">
Header
</div>
<div id="footer">
<div id="subHeaderContainer">
<div id="subHeader">
Sub Header
</div>
</div>
<div id="subFooter">
Sub Footer
</div>
</div>
</div>
CSS:
#myWindow {
width: auto;
height: auto;
resize: both;
border: 2px solid black;
overflow:hidden;
}
#header {
height: 20px;
background-color: grey;
}
#footer {
width:100%;
height: calc(100% - 20px);
}
#subHeaderContainer {
width:100%;
height: calc(100% - 30px);
}
#subFooter {
width:100%;
height:30px;
}

Troubleshooting CSS Layout

I have built a template to layout what I intend to accomplish. Everything seems to work well with what I have learned from the stackoverflow community.
However, the Footer which is its own container and has "section7" as another DIV is not displaying as 150 pixels in height. Basically all sections have fixed height except for Section 5 and Section 6 which have to scale in height depending on the browser window size or content that will be placed inside the section. So if content is sparse, I just want the height to be 100% of the remaining browser space so that the website is top to bottom. However if there is content that is lengthy obviously I want the middle section to adapt and continue as required. Hope I am making sense.
The challenge is I don't know where I am wrong and thus do not know how to pose the question in the search function as I imagine it is an easy task for those with experience. Any help is appreciated.
The HTML:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Sample Website</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container">
<div class="header">
<div class="section1">section 1</div>
<div class="section2">section 2</div>
<div class="section3">section 3</div>
<div class="section4">section 4</div>
</div>
<div class="middle">
<div class="section5">section 5</div>
<div class="section6">section 6</div>
</div>
<div class="footer">
<div class="section7">section 7</div>
</div>
</div>
</body>
</html>
The CSS:
#charset "utf-8";
/* CSS Document */
body {
margin-left: 0px;
margin-top: 0px;
margin-right: 0px;
margin-bottom: 0px;
padding: 0px;
background-color:#DBDBDB
}
div.container {
width: 1200px;
background-color:#FFFFFF;
margin-left:auto;
margin-right:auto;
}
div.header {
height: 100px;
}
div.middle {
min-height: 400;
}
div.footer {
height: 150px;
}
div.section1 {
background-color:#FF0004;
height: 100px;
width: 275px;
float:left;
position:relative;
}
div.section2 {
background-color:#FFA600;
height: 100px;
width: 100px;
float:left;
position:relative;
}
div.section3 {
background-color:#00C304;
height: 50px;
}
div.section4 {
background-color:#DFDD00;
height: 50px;
}
div.section5 {
background-color:#0A00FF;
width: 275px;
height: 400px;
float:left;
height: 100vh;
}
div.section6 {
background-color:#CB05B1;
width: 925px;
height: 400px;
float:right;
height: 100vh;
}
div.section7 {
background-color:#9E9E9E;
height: 150px;
}
Floating elements need to be cleared so that elements following align correctly and do not move into the elements you have floated. Section 5 and Section 6.
Add the following class definition to your stylesheet
.clearfix:before, .clearfix:after {
content: " ";
display: table;
}
Change the following tag <div class="middle"> to <div class="middle clearfix">
HTML5 also includes <header> and <footer> elements, as well as <article> tags to make the document language more semantic. So for HTML5 you can use
<header>
<div class="section1">section 1</div>
<div class="section2">section 2</div>
<div class="section3">section 3</div>
<div class="section4">section 4</div>
</header>
And
<footer>
<div class="section7">section 7</div>
</footer>
https://jsfiddle.net/raythcael/s49o4rjz/2/
To make .section7 have a height of 150px add display: inline-block;
div.section7 {
background-color: #9E9E9E;
height: 150px;
display: inline-block;
}
See: https://jsfiddle.net/zvkxj6v8/
The reason why the height isn't working as it should is because the Div's above it is set to "float". Add "clear: both;" to div.section7 to clear the floats.
https://jsfiddle.net/2L55g0f9/1/
because section 5 and 6 are floated, you're not seeing the height of section 7. All i did was clearfix it, and you got your height :)
.clearfix:after {
clear: both;
content: ".";
display: block;
height: 0;
visibility: hidden;
}
.clearfix {
display: inline-block;
}

Table Element Not Taking 100% Of Parent Element

I created a sample of the situation in JSFiddle
I updated JSFiddle Here: http://jsfiddle.net/x11joex11/r5spu85z/8/ (this shows in more detail how the sticky footer works so well, just height issue).
I want the table to take up the remaining height, for some reason the height: 100% is not working?
From my tests it appears to be related to min-height: 100%. I need that to make the sticky footer work.
So a solution for me is another way to do the sticky footer, or a way to still give 100% height to the elements within.
HTML
<div class="wrapper">
<div class="wrapper_content">
<!--Header-->
<div class="header">Header</div>
<div class="content table">
<div class="row">
<div class="l_cell">left</div>
<div class="r_cell">right</div>
</div>
</div>
<div class="push"></div>
</div>
</div>
<!--Footer-->
<div class="footer">Footer</div>
CSS
body, html {
margin: 0;
padding: 0;
height: 100%;
}
.wrapper {
min-height: 100%;
margin: 0 auto -50px;
background-color: black;
}
.container {
}
.table {
display: table;
height: 100%;
width: 100%;
background-color: yellow;
}
.row {
display: table-row;
}
.l_cell {
display: table-cell;
width: 265px;
background-color: orange;
}
.r_cell {
display: table-cell;
background-color: purple;
}
.header {
background-color: red;
width: 100%;
}
.footer {
height: 50px;
background-color: green;
}
.push {
height: 50px;
}
Here is one solution, http://jsfiddle.net/7t4RT/
This question has been asked many times before. I recommend viewing some of the answers already provided here at StackOverflow.
The reason that we're unable to use height: 100% in your example is because no height has defined. The CSS is wondering... well how high is 100%? There are many ways to get our elements to fill their containers in either HTML or CSS. Simply choose one you feel works better for you.
The following is one of many ways to solve this problem.
HTML:
<div class="fill-height">
<p>Filled</p>
</div>
<div class="cant-fill-height">
<p>Not Filled</p>
</div>
CSS:
body {
background-color: #ccc;
}
.fill-height {
background-color: #0ff;
width: 200px;
position: absolute;
top: 0;
bottom: 0;
}
.cant-fill-height {
background-color: #ff0;
width: 200px;
height: 100%;
margin-left: 200px;
}
I found an answer to my problem for now, but it requires the use of display:table which I recall causes other errors down the road, but it does appear to work right now to create the layout I had in mind.
http://jsfiddle.net/x11joex11/r5spu85z/10/
CSS
body,html{margin:0;padding:0;height:100%;}
.wrapper{}
.table{
height:100%;
width:100%;
display:table;
background-color:yellow;
}
.row{display:table-row;}
.cell{display:table-cell;}
.footer{background-color:green;height:50px;}
.header{background-color:red;height:30px;}
.left{background-color:purple;}
.right{background-color:orange;}
HTML
<div class="wrapper table">
<div class="header row">
Header<br/>
Header2
</div>
<div class="content table">
<div class="row">
<div class="cell left">leftt<br/>left2</div>
<div class="cell right">right<br/>right2</div>
</div>
</div>
<div class="footer row">
Footer
<br/>
Footer2
</div>
</div>
An answer not requiring the use of display:table or table tags is preferred.
Notice the sticky footer effect remains.

Set div to remaining height using CSS with unknown height divs above and below

Is it possible to make the wrapper fill the window height (no scrolling) and the center div scrollable without messing around with pixels and javascript?
<div id="wrapper">
<h1>Header</h1>
<div id="center">
<div style="height:1000px">high content</div>
</div>
<div id="footer">Footer</div>
</div>
Basically I want the header to be visible at the top and the footer to be always visible at the bottom and have a scrollable content in the center which occupies the remaning height.
The header, footer and center divs' heights are all unknown (no set px or %, i.e. variable font-size or padding). Is it possible with pure CSS?
2014 UPDATE: The modern way to solve this layout problem is to use the flexbox CSS model. It's supported by all major browsers and IE11+.
2012: The correct way to do this with CSS alone is to use display: table and display: table-row. These are supported by all major browsers, starting with IE8. This is not using tables for display. You'll use divs:
html, body {
height: 100%;
margin: 0;
}
.wrapper {
display: table;
height: 100%;
width: 100%;
background: yellow; /* just to make sure nothing bleeds */
}
.header {
display: table-row;
background: gray;
}
.content {
display: table-row; /* height is dynamic, and will expand... */
height: 100%; /* ...as content is added (won't scroll) */
background: turquoise;
}
.footer {
display: table-row;
background: lightgray;
}
<div class="wrapper">
<div class="header">
<h1>Header</h1>
<p>Header of variable height</p>
</div>
<div class="content">
<h2>Content that expands in height dynamically to adjust for new content</h2>
Content height will initially be the remaining
height in its container (<code>.wrapper</code>).
<!-- p style="font-size: 4000%">Tall content</p -->
</div>
<div class="footer">
<h3>Sticky footer</h3>
<p>Footer of variable height</p>
</div>
</div>
That's it. The divs are wrapped as you'd expect.
A cross-browser solution derived from Dan Dascalescu answer:
http://jsfiddle.net/Uc9E2
html, body {
margin: 0;
padding: 0;
height: 100%;
}
.l-fit-height {
display: table;
height: 100%;
}
.l-fit-height-row {
display: table-row;
height: 1px;
}
.l-fit-height-row-content {
/* Firefox requires this */
display: table-cell;
}
.l-fit-height-row-expanded {
height: 100%;
display: table-row;
}
.l-fit-height-row-expanded > .l-fit-height-row-content {
height: 100%;
width: 100%;
}
#-moz-document url-prefix() {
.l-scroll {
/* Firefox requires this to do the absolute positioning correctly */
display: inline-block;
}
}
.l-scroll {
overflow-y: auto;
position: relative;
height: 1000px;
}
.l-scroll-content {
position: absolute;
top: 0;
bottom: 0;
height: 1000px;
min-height:100px;
}
<div class="l-fit-height">
<section class="l-fit-height-row">
<div class="l-fit-height-row-content">
<p>Header</p>
</div>
</section>
<section class="l-fit-height-row-expanded">
<div class="l-fit-height-row-content l-scroll">
<div class="l-scroll-content">
<p>Foo</p>
</div>
</div>
</section>
<section class="l-fit-height-row">
<div class="l-fit-height-row-content">
<p>Footer</p>
</div>
</section>
</div>
Using overflow:auto will let you do this.
demo
So what you are talking about is a sticky footer. I went and did some more research and here is what I have for you.
<div id="wrapper" style="height:100%">
<div id="header" style="float:none;"><h1>Header</h1></div>
<div style="overflow:scroll;float:none;height:auto;">high content</div>
<div id="footer" style="clear:both;position:fixed;bottom:0px;"><h1>Footer</h1></div>
</div>
This will give you a sticky footer. The key is position:fixed and bottom:0px;
Unfortunately this means it also hovers above any content in the scrollview. So far there seems to be only Javascript to figure this out but I will keep looking.

How can I convert this table based layout to CSS?

I have a table based layout which is 100% height/width with no scrollbars. The header (red) automatically expands to fit the content and I don't know how many pixels it will be. The fluid table below gives exactly what I what.
<html>
<body height=100%>
<table height=100% width=100% padding=0>
<tr height=1><td colspan=2 bgcolor=red>Fit<br/>to<br/>content<br/>height</td></tr>
<tr><td bgcolor=blue width=66% valign=top>How can I do this with CSS?</td><td bgcolor=green valign=top>
<div style="height:100%; width:100%; overflow:auto;">
This area can have content that overflows - needs an independent scrollbar.<br/>
0<br/>1<br/>2<br/>3<br/>4<br/>5<br/>6<br/>7<br/>8<br/>9<br/>
0<br/>1<br/>2<br/>3<br/>4<br/>5<br/>6<br/>7<br/>8<br/>9<br/>
0<br/>1<br/>2<br/>3<br/>4<br/>5<br/>6<br/>7<br/>8<br/>9<br/>
0<br/>1<br/>2<br/>3<br/>4<br/>5<br/>6<br/>7<br/>8<br/>9<br/>
</div>
</td></tr>
</table>
</body>
</html>
How can I do the same layout in CSS and have it work on commonly used browsers?
The header shouldn't be too difficult, for the two columns, I think you'll need to use faux columns to make the colours stretch all the way to the bottom.
For the header I think you'll just want:
HTML:
<div id="header">Fit<br/>to<br/>content<br/>height</div>
CSS:
#header {
background-color: red;
width: 100%;
}
p.s. You just made my eyes bleed ;)
<html>
<head>
<style type="text/css">
#wrapper
{
height: 100%;
width: 100%;
padding: 0;
}
#header
{
float: left;
width: 100%;
background-color: red;
}
#main
{
height: 100%;
width: 100%;
float: left;
}
#main-left
{
height: 100%;
float: left;
width: 66%;
background-color: blue;
}
#main-right
{
height: 100%;
float: left;
width: 34%;
background-color: green;
}
</style>
</head>
<body>
<div id="wrapper">
<div id="header">
Fit<br />to<br />content<br />height
</div>
<div id="main">
<div id="main-left">
How can I do this with CSS?
</div>
<div id="main-right">
Tested in Chrome 2 and IE8
</div>
</div>
</div>
</body>
</html>