Flexible vertical html layout - html

I need solve some task in vanilla html+css - bootstrap code for desktop browser-based application. So, I can't use libraries such as jQuery or Ext.
There are container 'wrapper' with three boxes - 'header', 'pane', 'content'. I need the following - wrapper and all three boxes always fit into single screen and take 100% of height/width
Header is going to be a toolbar and pane is a fixed height box. Content takes the rest of the screen.
I'm unable to make content fit into the rest of page. Can anybody help me ?
Another problem - I need to have testarea in the pane and content. Of course, there are lot's of such contols but I can't use them because this is bootstrap code.
I've created sample page: http://jsfiddle.net/madhollander/6r4nu/
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>filterIt</title>
<style>
#wrapper
{
position:absolute;
top:0px;
left:0px;
right:0;
bottom:0px;
-webkit-box-orient: vertical;
-webkit-box-flex: 1;
}
#header
{
display: -webkit-box;
width:100%;
background-color:blue;
-webkit-box-orient:vertical;
}
#pane
{
display: -webkit-box;
width:100%;
height:100px;
background-color:black;
-webkit-box-flex: 1;
-webkit-box-orient:vertical;
}
#content
{
display: -webkit-box;
width:100%;
background-color:green;
overflow-x: scroll;
overflow-y: scroll;
-webkit-box-flex: 1;
-webkit-box-orient:vertical;
}
.textbox{
width:100%;
display:block;
-webkit-box-sizing: border-box;
box-sizing: border-box;
resize:none;
overflow-x: scroll;
overflow-y: scroll;
}
</style>
</head>
<body onload='onload();run();'>
<div id='wrapper'>
<div id='header'>
<button type="button">Apply</button>
</div>
<div id='pane'>
<textarea class="textbox" id="command" wrap="off">command sample</textarea>
</div>
<div id='content'>
<textarea class="textbox" wrap="off" id='log'>log sample</textarea>
</div>
</div>
</body>
</html>

You're simply using the Flexbox module incorrectly. Some properties only apply to flex containers, others only apply to flex items. Also never use the old Flexbox properties unless you're also using the modern properties.
http://codepen.io/cimmanon/pen/DcesF
#wrapper {
position: absolute;
top: 0px;
left: 0px;
right: 0;
bottom: 0px;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-webkit-box-direction: normal;
-moz-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
#header {
width: 100%;
background-color: blue;
}
#pane {
width: 100%;
height: 100px;
background-color: black;
-webkit-box-flex: 1;
-moz-box-flex: 1;
-webkit-flex: 1 1;
-ms-flex: 1 1;
flex: 1 1;
}
#content {
width: 100%;
background-color: green;
overflow-x: scroll;
overflow-y: scroll;
-webkit-box-flex: 1;
-moz-box-flex: 1;
-webkit-flex: 1 1;
-ms-flex: 1 1;
flex: 1 1;
}
.textbox {
width: 100%;
display: block;
-webkit-box-sizing: border-box;
box-sizing: border-box;
resize: none;
overflow-x: scroll;
overflow-y: scroll;
}

What you could do to make this 'fluid' layout is to set the #wrapper to height: 100%;
This stretches it to the body's height (which you should also set to 100% - as some browsers handle this different from others)
Furthermore, you could set a percentage for each element in height which you can always change to your liking, ofcourse you should set min-height rather than height, otherwise your elements will overflow and cause layout glitches.
Your page will then look like this:
http://jsfiddle.net/6r4nu/1/

Not sure I understand your question correctly, but here you go anyway:
If you need the three div's to fill the page vertically, you just need to give your wrapper (and further parent elements) a height of 100%. Then to fill the page, each div gets a height of 33.3%.
like this:
#wrapper{
height:100%;
}
#header, #content, #pane{
height:33.3%
}
If they shouldn't be equally heigh, just re-calculate the percentage so they add up to 100%.

Related

Div to fill the rest of page

I'm trying to fill the rest of my content, before my footer. I've found many pages here with solutions that seem logical but don't seem to work within my page. I cant change my position status of my footer to fixed or absolute.
I currently have a div with the id of "bottomfix". I tried the fixed & zerod solution but that didn't work either.
I invite you view my biopage, the css that I'm working on is the last sheet titled style.css.
A way to do this, which I think would work for your layout, is using flexbox. I actually did this for one of my own projects (example). This is the best solution, since your footer and other content can have dynamic height.
General HTML structure:
<body>
<main>
Header and page content go here...
</main>
<footer>
Footer...
</footer>
</body>
It's important to include many different prefixes and fallbacks to make it work in all browsers (I tested it in multiple versions of Chrome, FF, IE and Safari).
CSS:
body {
display: box;
display: -webkit-box;
display: -moz-flex;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
min-height: 100vh;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
box-orient: vertical;
}
main {
-webkit-box-flex: 1 1 auto;
-moz-box-flex: 1 1 auto;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
}
footer {
margin-top: 32px; // Whatever space you want between content and footer.
-webkit-box-flex: 0 1 auto;
-moz-box-flex: 0 1 auto;
-webkit-flex: 0 1 auto;
-ms-flex: 0 1 auto;
flex: 0 1 auto;
}
If you want to control the size of your .bottomfix div, you can add more flexboxes into the main element.
Add to your #footer class position: fixed;
then add position bottom: 0px; and it will be at the bottom
#footer {
border-width: 5px;
bottom: 0;
padding: 6px 0 7px;
position: fixed;
width: 100%;
}
if you want footer to bi fixed to the bottom of the page only if your page doesn't have enough content to fill in page then add this script before <body> closing tag
<script type="text/javascript">
if(jQuery('header:first').height()+
jQuery('main:first').height()+ jQuery('footer:first').height() > jQuery(window).height()){
$('#footer').css({position: 'fixed', bottom: '0px'});
}
</script>
and this scrip will on load check if your page needs fixed footer :)
or you can add it in
$(document).ready(function(){
//code
});
#footer {
border-top: 1px solid #000;
background: #222;
color: #7B7B7B;
font-size: 13px;
position: absolute;
z-index: 100;
clear: both;
padding: 10px 0;
bottom: 0;
}
This worked for me I set the position to absolute and set bottom:0; to force the div to the bottom of the browser
You can try using the the CSS3 calc function. Like this:
main{
min-height: 100%; /*fallback if browser doesn't support calc*/
min-height: ~"calc(100% - 330px)"; /*330px comes from 270px <header> plus 60px <footer>*/
}
You would just have to replace the <header> and <footer> height value calculation to yours.
Also make sure you have something like this:
html, body{
height:100%;
}
Just try this. 66px is footer + header height
html, body, #page, #bottomfix, main > div {
height: 100%;
}
main {
height: calc(100% - 66px);
}

CSS Table Styles - Get table row to fill entire content area

I'm trying to use the CSS table display to layout my page and I'm having trouble getting my main content area to take up the entire area (vertically) between the header and the footer. The main div contains some floated elements that don't necessarily extend the length of the screen. Basically, no matter what I do, the area of my main content is decided by the vertical height of these elements. Is there anything I can do about this? Thanks!
Html:
<div id="all-container">
<div id="header">
...
</div>
<div id="table-container">
<div id="content">
<div id="side-bar">
...
</div>
<div id="main">
... some content that's floated ...
</div>
</div>
</div>
<div id="footer"></div>
</div>
CSS:
#all-container {
margin:0px;
position:relative;
min-height:100%;
background-color:#E6DCD8;
}
#header {
height:60px;
padding-left:20px;
padding-right:20px;
background-color:#685642;
}
#table-container {
display:table;
height:100%;
}
#content {
display:table-row;
height:100%;
}
#side-bar {
display:table-cell;
vertical-align:top;
padding-right:100px;
height:100%;
padding-bottom:60px;
}
#main {
display:table-cell;
vertical-align:top;
border-left-style:solid;
border-left-width:normal;
border-left-color:#685642;
padding-bottom:60px;
height:100%;
}
#footer {
position:absolute;
width:100%;
height:50px;
bottom:0px;
background-color:#685642;
}
I'm going to take a shot in the dark at trying to answer. These are my suggestions, not necessarily the canonical correct answer you're looking for.
Not answering exactly to the question on table layout per say, but I'm offering other ways to achieve the same desired result.
This is your original code in the fiddle http://jsfiddle.net/CRzfS/
I think you have at least two design objectives here you want to achieve:
make a full screen height layout
make a 2-column layout
I'll have to put it forward first, that there are many ways to achieve the objective, but all has their limitations due to browser support. I also advise against table layouts unless it is necessary.
For me, display: table is only used for one reason mostly: Making vertical-align work in a fixed-height container, especially vertical-align: middle. There are also relevant uses for the auto calculation of table-cell widths from a fixed-width table, but it all depends on how you want to present data or information.
We'll face the issues one by one.
Full Height
First is the layout's height issue. Height flexibility has always been a sore point in web design layouts.
To fill screen height only, you can look at this sticker footer implementation:
http://www.cssstickyfooter.com/
Here's an example fiddle with full screen height, not taking footer implementation into account: http://jsfiddle.net/CRzfS/3/
CSS:
html, body {
height: 100%;
min-height: 100%;
}
For liquid height layout you can look at this: http://www.mightymeta.co.uk/superstretch-a-vertically-fluid-layout-using-css/
For a proper flexible height, you'll have to use CSS Flexbox.
http://caniuse.com/#feat=flexbox
You can try it out here http://flexiejs.com/playground/
Your example implemented using CSS Flexbox: http://jsfiddle.net/CRzfS/4/
CSS:
html, body {
height: 100%;
min-height: 100%;
margin: 0;
padding: 0;
}
#all-container {
display: -webkit-box;
display: -moz-box;
display: box;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
box-orient: vertical;
margin:0px;
position:relative;
min-height:100%;
height: 100%;
background-color:#E6DCD8;
}
#header {
height:60px;
padding-left:20px;
padding-right:20px;
background-color:#685642;
}
#table-container {
display: -webkit-box;
display: -moz-box;
display: box;
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
box-orient: vertical;
}
#content {
display: -webkit-box;
display: -moz-box;
display: box;
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
overflow: hidden;
}
#side-bar {
vertical-align:top;
min-width: 150px;
}
#main {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
vertical-align:top;
border-left-style:solid;
border-left-width:normal;
border-left-color:#685642;
}
#footer {
width:100%;
height:50px;
background-color:#685642;
}
Two-column Layout
There are many ways to achieve this. Considerations have to be made for the differing screen sizes you're supporting(which is a major headache). Each has their own drawbacks. And also it depends on your width requirements i.e. fixed width, flexible width.
semantic way by absolute positioning the sidebar and setting margin for main content
common method used by layout frameworks via floating sidebar and container so they are side by side
using display: inline-block to the same effect as #2.
The first method here, sets your #side-bar after the #main in the HTML. Then using CSS absolute positioning to set #side-bar to the left side, and setting margin-right for your #main. http://jsfiddle.net/CRzfS/2/
HTML:
<div id="table-container">
<div id="content">
<div id="main">
... some content that's floated ...
</div>
<div id="side-bar">
...
</div>
</div>
</div>
CSS:
#table-container {
position: relative;
}
#content {
height: 200px;
}
#side-bar {
width: 200px;
position: absolute;
left: 0;
top: 0;
background-color: rgba(255,255,255,0.5);
height: 100%;
}
#main {
margin-left: 200px;
height: 100%;
overflow: hidden; // for floated elements within
}
The second method here, using the original HTML, you'll only need to set the CSS. http://jsfiddle.net/CRzfS/5/
#table-container {
overflow: hidden;
}
#content {
width: 100%;
}
#side-bar {
width: 33%;
float:left;
}
#main {
width: 66%;
float: left;
vertical-align:top;
border-left-style:solid;
border-left-width:normal;
border-left-color:#685642;
padding-bottom:60px;
min-height: 100px;
overflow: hidden; // for floated elemnts
}
How to combine these 2 layout requirements together will be difficult if I'm not sure of what you exactly require for the vertical height part.
I'll need more information before I can give a relevant answer tailored to your question.
Resources
If you're open to layout grid systems framework, I'll suggest you take a look at: http://twitter.github.com/bootstrap/scaffolding.html#gridSystem
Even if you don't want to use it, just looking at the CSS implementation will yield you interesting insights.
I'll be adding other jsfiddle examples as more information on the question comes.
Edit: More information and explanations added.

CSS Box Flex Fixed Height Container with Resizable Top and Scrollable Bottom

I am trying to layout a header that will resize vertically to fit the content, and a footer that will resize vertically the remaining then scroll any overflow given a fixed size container. Using CSS box-flex I have an example that works in Chrome but not Firefox (http://jsfiddle.net/V4Uc2/). What CSS styles do I need to add to ensure that Firefox doesn't allow any overflow from the container and acts like Chrome? Here is inlined code:
<style>
.container
{
background: #fee;
height: 400px;
width: 400px;
display: -webkit-box;
display: -moz-box;
display: box;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
box-orient: vertical;
}
.header
{
background: #fee;
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
}
.footer
{
background: #eef;
overflow: auto;
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
}
</style>
<div class="container">
<div class="header">...</div>
<div class="footer">...</div>
</div>
Add
width: 100%;
in your footer css description.
That prevents an overflow horizontally, firefox keeps your 400px then as a fixed width.

HTML5 flexible box model height calculation

after researching the flexible box model for a whole day, I must say I really like it. It implements the functionality I implement in JavaScript in a fast and clean way. One thing however bugs me:
I can't expand a div to take the full size calculated by the flexible box model!!!
To illustrate it I'll proved an example. In it the two flexible places take the exact with and height, but the div inside it only takes the height of the "<p>...</p>" element. For this example it doesn't matter but what I originally was trying was placing a "flexible box model" inside another "flexible box model" and this must be possible in my opinion
html, body {
font-family: Helvetica, Arial, sans-serif;
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
}
#box-1 {
background-color: #E8B15B;
}
#box-2 {
background-color: #C1D652;
}
#main {
width: 100%;
height: 100%;
overflow-x: auto;
overflow-y: hidden;
}
.flexbox {
display:-moz-box;
display:-webkit-box;
display: box;
text-align: left;
overflow: auto;
}
H1 {
width: auto;
}
#box-1 {
height: auto;
-moz-box-orient: vertical;
-webkit-box-orient: vertical;
box-orient: vertical;
-moz-box-flex: 3;
-webkit-box-flex: 3;
box-flex: 3;
}
#box-2 {
height: auto;
min-width: 50px;
-moz-box-orient: vertical;
-webkit-box-orient: vertical;
box-orient: vertical;
-moz-box-flex: 1;
-webkit-box-flex: 1;
box-flex: 1;
}
#fullsize{
background-color: red;
height: 100%;
}
<div id="main" class="flexbox">
<div id="box-1" class="flexbox">
<div id="fullsize">
<p>Hallo welt</p>
</div>
</div>
<div id="box-2" class="flexbox">
</div>
</div>
I've been wrestling with this myself, but have finally managed to come up with a solution.
See this jsFiddle, although I have only added webkit prefixes so open in Chrome.
You basically have 2 issues which I will deal with separately.
Getting the child of a flex-item to fill height 100%
Set position:relative; on the parent of the child.
Set position:absolute; on the child.
You can then set width/height as required (100% in my sample).
Fixing the resize scrolling "quirk" in Chrome
Put overflow-y:auto; on the scrollable div.
The scrollable div must have an explicit height specified. My sample already has height 100% but if none is already applied you can specify height:0;
See this answer for more information on the scrolling issue.
You must also make the div you want to expand a flex-box as well and add a flex value.
This fixes the problem.
#fullsize{
background-color: red;
display: -webkit-box;
display: box;
display: -moz-box;
box-flex:1;
-webkit-box-flex:1;
-moz-box-flex:1;
}

Tableless layout with two liquid columns (liquid - fixed - liquid)

So, this web application I'm working in haves three vertical columns expanding for the entire window height, and a footer div expanding for the entire width. The layout looks like this:
+|+
---
where + means a liquid column, | means a fixed column, and - the footer.
I've done the element positioning using absolute and relative positioning with some tweaks using jQuery. But I want to know if there is a way of doing this with CSS3 only.
Thanks!
This neglects all browser not supporting the box-orient and box-flex properties (like IE).
Demo: http://jsfiddle.net/p8vBC/11/
CSS:
html, body {
height: 100%;
padding: 0px;
margin: 0px;
}
body > #main {
display: -webkit-box;
-webkit-box-orient: horizontal;
display: -moz-box;
-moz-box-orient: horizontal;
display: box;
box-orient: horizontal;
height: 100%;
margin-bottom: -100px;
}
footer {
height: 100px;
box-flex: 1;
-webkit-box-flex: 1;
-moz-box-flex: 1;
}
aside {
box-flex: 1;
-webkit-box-flex: 1;
-moz-box-flex: 1;
}
#content {
width: 400px;
}
HTML:
<div id="main">
<aside id="left"></aside>
<div id="content"></div>
<aside id="right"></aside>
</div>
<footer></footer>