I have similar problem which can be found here. But i couldn't make it work or i didnt understand it fully.
My problem which im trying to resolve is - I want my content background to reach footer even if there isnt enough content to be displayed. I created a simple fiddle which can be found here. As you can see there isnt enough content to reach footer and there is this "blue" space between content and footer. I would like to make that space grey.
HTML :
<div class=blue>header here</div>
<p>LOGO here</p>
<div class="blue">navigation bar here</div>
<div class="content">
No content.
</div>
<div class="footer">footer is here</div>
CSS:
.blue {
color: #ffffff;
background-color: #294a70;
display: block;
float: none;
width: 400px;
margin: 0 auto;
text-align: center;
}
p {
text-align: center;
color: #ffffff;
}
.content {
background-color: #e6e6e6;
display: block;
float: none;
margin: 0 auto;
overflow:hidden;
width:400px;
margin-bottom:30px;
}
.footer {
color: #ffffff;
background-color: #294a70;
display: block;
float: none;
width: 400px;
margin: 0 auto;
text-align: center;
position: absolute;
bottom: 0;
left: 0;
right: 0;
height:30px;
}
body {
margin:0;
padding:0;
font-family: 'Open Sans', sans-serif;
line-height: 1.5;
font-size: 14px;
overflow-x:hidden;
background-image:url('http://www.planwallpaper.com/static/images/Alien_Ink_2560X1600_Abstract_Background_1.jpg');
min-height: 100%;
}
html {
position:relative;
min-height: 100%;
}
All help will be appreciated!
Use CSS3 calc() function
the trick is, if you know the height of header & footer, you can use this function with vh units, 100vh gives you screen height, just substract the height of hearder & footer from it.
E.g.
If header is 80px & Footer is 40px, i.e. total 120px, then use
.content{
min-height: calc(100vh - 120px);
}
The purpose of using min-height is if content is not present then atleast this height is applied, but if there is more content than screen then div is expanded to fit accordingly.
Updated JSFiddle:
https://jsfiddle.net/vj07e8g1/5/
You could try a flexbox layout instead:
HTML
<body>
<header></header>
<main class="content"></main>
<footer></footer>
</body>
CSS
body {
display: flex;
min-height: 100vh;
flex-direction: column;
}
main.content {
flex: 1;
}
Check out this codepen example: http://codepen.io/StefanBobrowski/pen/zZXXWy
You can add this to your content style:
min-height:400px;
It'll push the footer a little, but it'll do the work.
Hope this is what you're looking for.
The easiest contemporary way, depending on your browser-support requirements, would be to use CSS grids, which allows you to define rows and columns and assign certain content to be in specific places (placed by grid-row and grid-column), like follows:
html,
body {
height: 100%;
}
/* to force all elements to be sized including
their padding and border-widths */
body,
::before,
::after {
box-sizing: border-content;
}
body {
/* To use CSS grid, forcing the child elements of
the <body> element to adopt 'display: grid-item': */
display: grid;
/* defining the three columns of the grid, the first and
third being equal fractions of the space left over after
the second (middle) column's width of 400px is calculated */
grid-template-columns: 1fr 400px 1fr;
/* reducing the first three rows to the minimum height needed
to fully display their content, setting the fourth row
to take up the remaining unoccupied space once the other
heights are calcuated and setting the final row's height to
30px: */
grid-template-rows: min-content min-content min-content 1fr 30px;
height: 100vh;
background-image: url(https://i.stack.imgur.com/2oC8H.jpg);
}
body>* {
/* setting all the child elements of the <body> to be placed
in grid-column 2 (the central 400px-wide column): */
grid-column: 2;
}
/* Setting the default shared styles of the .blue elements: */
.blue {
color: #ffffff;
background-color: #294a70;
}
.blue.header {
/* positioning this element in the first (one-based counting)
row: */
grid-row: 1
}
body>p {
grid-row: 2;
}
.blue.navigation {
grid-row: 3;
}
div.content {
grid-row: 4;
/* background-color purely to show that the space of the
div.content element occupies the full space available: */
background-color: #ffa;
}
div.footer {
grid-row: 5;
}
<div class="header blue">header here</div>
<p>LOGO here</p>
<div class="blue navigation">navigation bar here</div>
<div class="content">
No content.
</div>
<div class="footer">footer is here</div>
JS Fiddle.
Please note that I did add a class-name to both the .blue elements in order to more-easily distinguish them according to their roles in the document, and from each other when placing them in the document.
Related
This question already has answers here:
Percentage Height HTML 5/CSS
(7 answers)
Closed 2 years ago.
I am pretty new to Web development and I am trying to learn CSS grids. While learning the CSS grid I tried to make one simple layout. It has one header section, one menu section, one sidebar section, and one footer section.
I used auto while defining grid template rows for the 2nd row, and gave conatiner height as 100%, so that 2nd row will stretch fully in the remaining space left by row 1 and 2.
But it didn't work that way, i am trying to figure out why 2nd row is not stretching vertically in the remaning space left.
Here is the conatiner css in which i defined the 2nd row as auto and conatiner height as 100%.
.container {
height: 100%;
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 40px auto 40px;
}
fiddle link:
https://jsfiddle.net/791vtd4z/
That is because you did not give body a fixed height, yet you have .container a relative height: therefore, when the child .container simply stretches to its content height and not any further, since there's nothing absolute to compare against by using 100% (ask yourself: "100% of what?").
A solution will be to set .container { min-height: 100vh; } to fix that, which tells the element to at least be as tall as the viewport, and allow it to grow should the content inside menu or sidebar grow beyond what the viewport can contain.
* {
margin: 0;
top: 0;
bottom: 0;
font-family: sans-serif;
font-size: 1.2em;
}
title {
display: none;
}
.container {
min-height: 100vh;
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 40px auto 40px;
}
.Header {
background-color: beige;
grid-column: 1/-1;
}
.Menu {
background-color: red;
}
.Sidebar {
background-color: burlywood;
grid-column: 2/-1;
}
.Footer {
background-color: aquamarine;
grid-column: 1/-1;
}
<div class="container">
<div class="Header">Header</div>
<div class="Menu">Menu</div>
<div class="Sidebar">Sidebar</div>
<div class="Footer">Footer</div>
</div>
To build on Terry's answer, you can achieve your desired result by giving body a height of 100vh, you could change the height of .container to 100vh, or you could give html and body a height of 100% (and keep the 100% height of .container).
This is because 100vh gives an element the full height of the viewport regardless of the height of its parents, while setting an element's full height using a percentage (i.e. 100%) means the element takes the full height of its parent, whatever that is. So an element with a height of 100% could still be zero, if its parent has no height.
To put this another way, when setting an element's height to 100% all of its parents need to be 100% as well for that element to take up the full viewport.
html, body{
height: 100%;
}
* {
margin: 0;
top: 0;
bottom: 0;
font-family: sans-serif;
font-size: 1.2em;
}
title {
display: none;
}
.container {
height: 100%;
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 40px auto 40px;
}
.Header {
background-color: beige;
grid-column: 1/-1;
}
.Menu {
background-color: red;
}
.Sidebar {
background-color: burlywood;
grid-column: 2/-1;
}
.Footer {
background-color: aquamarine;
grid-column: 1/-1;
}
<div class="container">
<div class="Header">Header</div>
<div class="Menu">Menu</div>
<div class="Sidebar">Sidebar</div>
<div class="Footer">Footer</div>
</div>
When a number of rows on the last page is small it leaves space below the table. On a "full" page, there is no space.
Also,
Pics (the html background set to green just for demonstration)
No extra space
I played with min-height/max-height/height. Couldn't get close to what I would like to see.
body {
background: #fafafa;
color: #333333;
margin-top: 5rem;
}
html {
/* min-height: 100%; */
/* min-height: 200px; */
background-color: green;
}
Also been logging height for body and html in my .js.
console.log(`BODY: ${$('body').height()}`);
console.log(`HTML: ${$('html').height()}`);
And there is probably something that I don't understand, because it shows that height of html = height of body - margin-top for every page of the table. I thought html height will be bigger, and then I will be able to set the height via JQuery. Also if I set really small(like 200px) max-height for html it doesn't seem to have any effect, but I definitely can see the difference if I set a big min-height for html, like 1600px or something. Is there some global min-size that couldn't be less than some value?
I don't think the table styling or some Tablesorter options have anything to do with it. Let me know if some additional info will be useful.
EDIT.
demo
example of the desired behavior.
Try this,Its works:
body {
background: #fafafa;
color: #333333;
margin:0;
min-height:100%;
}
html {
background-color: green;
height:100%;
}
Try this implementation of footer:
CSS:
#supports (display: grid) {
body {
display: grid;
grid-template-rows: 3.5rem auto fit-content(8rem);
grid-template-areas: "header"
"main"
"footer";
padding-top: 0;
height: 100%;
}
}
main {
grid-area: main;
}
.main-footer {
background: black;
padding: 2rem;
grid-area: footer;
}
.main-header {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
background-color: lightgreen;
}
HTML:
<body>
<header>
<div class="main-header">
This is a header!
</div>
</header>
<main>
<div class="main">
This is a main!
</div>
</main>
<footer class="main-footer">
<nav>
<span>This is a your footer!</span>
</nav>
</footer>
</body>
I'm struggling with a problem which seems simple:
My code:
* {
font-family: tahoma;
}
body {
background: #333;
}
.wrapper {
padding: 10px;
background: white;
width: 100%;
}
.box {
margin-top: 40px;
width: 1100px;
height: 400px;
background: #aaa;
}
<div class="wrapper">
<div class="box">
box
</div>
</div>
The box contained in the wrapper has a fixed size, which might overflow the wrapper on small screens. Why doesn't the wrapper wrap around the box? How would I do that?
You can also check out the issue in this jsFiddle.
In order to make this work:
Remove width: 100% and add to the wrapper display: inline-block.
Doing so, will enable the wrapper to have as much width as needed to wrap around the box. Putting width: 100% restricts your wrapper to the width of the screen and in case of the box having a bigger with than that of the screen, it won't work.
If you do not want to have a horizontal scrollbar, especially on narrower screens use: box-sizing: border-box on the wrapper.
CSS:
.wrapper {
display: inline-block; /* Ensures that the box stays wrapped */
padding: 10px;
background: white;
box-sizing: border-box; /* Ensures that there won't be a horizontal scrollbar */
}
Here is a working version of your jsFiddle, with both the wrapping issue mended and the horizontal scrollbar abolished.
* {
font-family: tahoma;
}
body {
background: #333;
}
.wrapper {
box-sizing: border-box display: inline-block;
padding: 10px;
background: white;
}
.box {
position: relative;
margin-top: 40px;
height: 400px;
background: #aaa;
}
<div class="wrapper">
<div class="box">
box
</div>
</div>
For reference:
display: inline-block;
box-sizing: border-box;
Use display:inline-block on the wrapper to resize the container based on the content inside.
The div element by default has display:block; so you need to change its display.
You should remove width:100%; from .wrapper class, then you can make it display:inline-block; or display:table;
*{
font-family:tahoma;
}
body{
background:#333;
}
.wrapper
{
padding:10px;
background:white;
display:inline-block;
}
.box
{
margin-top:40px;
width:1100px;
height:400px;
background:#aaa;
}
<div class="wrapper">
<div class="box">
box
</div>
</div>
Your problem occurs, because HTML documents, by default, display all elements as display: block.
There are two ways to do it as our friends have mentioned before.
First one is to use inline-block value for the display property:
body{
display: inline-block;
}
The second way is to use max-width:
div.wrapper{
max-width: 100%;
/*we have set height property to auto to have coefficient between width & height*/
height: auto;
}
For more information visit these webpages:
inline-block
max-width
You can solve the problem by using the following css:
* {
font-family: tahoma;
}
body {
background: #333;
}
.wrapper {
padding: 10px;
background: white;
display: inline-block;
}
.box {
margin-top: 40px;
width: 1100px;
height: 400px;
background: #aaa;
}
<div class="wrapper">
<div class="box">
box
</div>
</div>
The only change is I have added display: inline-block to .wrapper element.
Why wrapper doesn't wrap around the child div
The problem is all html element has some default CSS styling which gets applied by the browser.
In this case div gets a default property of display: block; It is the same property that makes a default unstyled div to take up full available width of it's parent element.
As you can see with this: snapshot of chrome dev tools
*The css style highlighted in red rectangle is the default styling applied by the browser.
*The red underlined text tells us about the width of the element. The fading out signifies that value of that property is computed by the browser.
** While we are at it I want to point you to a different problem that you might have faced with the previous code and if the goal was to make the wrapper to wrap box at all times.
If the .box div would have width far less than that of the width of the browser then another problem may arise which I have shown in the code snippet bellow.
* {
font-family: tahoma;
}
body {
background: #333;
}
.wrapper {
padding: 10px;
background: white;
}
.box {
margin-top: 40px;
width: 100px;
height: 400px;
background: #aaa;
}
<div class="wrapper">
<div class="box">
box
</div>
</div>
As you can see the box tries to cling to a side of wrapper.
You can read more about display css property here: CSS display property || CSS-Tricks
I asked a question today about good and bad practises in CSS/HTML/jQuery and when it is appropriate to use jQuery to set container dimensions. I got some good answers
So, understanding that jQuery is not the best option, I decided to ask maybe some of you can give some input about this "problem"
So, I have a page put together with php. I have one header for all of my pages and content is being changed with php (I am saying this only to let you guys know that wrapping header and div in one container is not an option):
include ("header.php");
include ("$lang/$section.php");
include ("footer.php");
I have a header with fixed hight (100px + 100px margin-bottom) and after that I have a div which on screens smaller than 768px(height) I want to be no longer than the remaining space. If the screen is larger, I want my div to be
max-height: 420px;
with
padding: 100px 0;
Inside of this div I have 3 floated columns. I need them to fill the space in the parent div.
What I would usually do is- use jQuery and calculate screen height and subtract header height and all the margins and paddings. But as I've learned today, that is not a good practise.
So, to wrap it up: I NEED THE DIV TO FILL THE SPACE BETWEEN HEADER AND BOTTOM OF THE SCREEN FOR VIEWPORT HEIGHT SMALLER THAN 768px. MAX-HEIGHT FOR THIS DIV IS 420px. With jQuery it is super easy but I can't figure out the clean css way.
Maybe some of you have an idea?
Here is my fiddle, so you guys don't have to type out all of the code.
Thank you in advance!
You can use calc() and vh (viewport height).
calc() browser support: http://caniuse.com/#search=calc
vh browser support: http://caniuse.com/#search=vh
So we use calc(100vh - 200px) being 100vh the height of the viewport and 200px the height of the header.
Also, we add a media query so that when the screen is bigger than 768px height we limit the height to 420px.
Try this:
header { height: 100px; background: #ccc; margin-bottom: 100px; box-sizing: border-box; }
section { width: 100%; height: calc(100vh - 200px); padding: 50px 0; background: yellow; box-sizing: border-box; }
.col1, .col2, .col3 { float: left; width: 33%; }
.colPadding { padding: 25px; background: blue; }
.cb { width: 100%; height: 1px; clear: both; }
body {
margin: 0;
}
#media screen and (min-height: 768px) {
section {
max-height: 420px;
}
}
<header>
This is my header with 100px bottom margin
</header>
<section>
<div class="col1">
<div class="colPadding">
section with padding: 50px 0; and max-height: 420px;
</div>
</div>
<div class="col2">
<div class="colPadding">
Column 2
</div>
</div>
<div class="col3">
<div class="colPadding">
Column 3
</div>
</div>
<div class="cb"></div>
</section>
Gave it a shot with CSS3 flex-box model and screen media queries. Here is my fiddle.
I used 300px instead of 764px for the fiddle. (you can change it if you want, I just used 300px so that it's easier to test)
Applied CSS
* { box-sizing: border-box; } /* force sizing based on border */
body {
display: flex; /* flex for body since wrapping header and section is not allowed */
flex-flow: column wrap;
}
header {
height: 100px;
background: #ccc;
margin-bottom: 100px;
flex: 0 0 auto; /* make header size fixed */
}
section {
width: 100%;
max-height: 420px;
padding: 50px 0;
background: yellow;
/* to occupy remaining space */
flex: 1 1 auto;
/* for columns inside to occupy full width */
display: flex;
flex-flow: row wrap;
/* for immediate children to stretch to max height possible */
align-items: stretch;
}
.col1, .col2, .col3 {
float: left;
/* to occupy remaining width */
flex: 1 0 auto;
}
.colPadding {
padding: 25px;
background: blue;
}
.cb {
width: 100%;
height: 1px;
clear: both;
}
/* Custom CSS */
/* style to apply when the screen is less than or equal to 300px (you can change this to 768px) */
#media screen and ( max-height: 300px ){
body {
height: 100vh; /* for body to have a size of the full screen */
}
header {
margin: 0px; /* remove margin bottom */
}
section {
padding: 0px; /* remove margin bottom and top/bottom padding */
margin: 0px;
}
}
More on CSS3 flex-box here.
How can I achieve the following structure without using tables or JavaScript? The white borders represent edges of divs and aren't relevant to the question.
The size of the area in the middle is going to vary, but it will have exact pixel values and the whole structure should scale according to those values. To simplify it, I'd need a way to set "100% - n px" width to the top-middle and bottom-middle divs.
I'd appreciate a clean cross-browser solution, but in case it's not possible, CSS hacks will do.
Here's a bonus. Another structure I've been struggling with and end up using tables or JavaScript. It's slightly different, but introduces new problems. I've been mainly using it in jQuery-based windowing system, but I'd like to keep the layout out of the script and only control the size of one element (the middle one).
New way I've just stumbled upon: css calc():
.calculated-width {
width: -webkit-calc(100% - 100px);
width: -moz-calc(100% - 100px);
width: calc(100% - 100px);
}
Source: css width 100% minus 100px
You can use nested elements and padding to get a left and right edge on the toolbar. The default width of a div element is auto, which means that it uses the available width. You can then add padding to the element and it still keeps within the available width.
Here is an example that you can use for putting images as left and right rounded corners, and a center image that repeats between them.
The HTML:
<div class="Header">
<div>
<div>This is the dynamic center area</div>
</div>
</div>
The CSS:
.Header {
background: url(left.gif) no-repeat;
padding-left: 30px;
}
.Header div {
background: url(right.gif) top right no-repeat;
padding-right: 30px;
}
.Header div div {
background: url(center.gif) repeat-x;
padding: 0;
height: 30px;
}
While Guffa's answer works in many situations, in some cases you may not want the left and/or right pieces of padding to be the parent of the center div. In these cases, you can use a block formatting context on the center and float the padding divs left and right. Here's the code
The HTML:
<div class="container">
<div class="left"></div>
<div class="right"></div>
<div class="center"></div>
</div>
The CSS:
.container {
width: 100px;
height: 20px;
}
.left, .right {
width: 20px;
height: 100%;
float: left;
background: black;
}
.right {
float: right;
}
.center {
overflow: auto;
height: 100%;
background: blue;
}
I feel that this element hierarchy is more natural when compared to nested nested divs, and better represents what's on the page. Because of this, borders, padding, and margin can be applied normally to all elements (ie: this 'naturality' goes beyond style and has ramifications).
Note that this only works on divs and other elements that share its 'fill 100% of the width by default' property. Inputs, tables, and possibly others will require you to wrap them in a container div and add a little more css to restore this quality. If you're unlucky enough to be in that situation, contact me and I'll dig up the css.
jsfiddle here: jsfiddle.net/RgdeQ
Enjoy!
You can make use of Flexbox layout. You need to set flex: 1 on the element that needs to have dynamic width or height for flex-direction: row and column respectively.
Dynamic width:
HTML
<div class="container">
<div class="fixed-width">
1
</div>
<div class="flexible-width">
2
</div>
<div class="fixed-width">
3
</div>
</div>
CSS
.container {
display: flex;
}
.fixed-width {
width: 200px; /* Fixed width or flex-basis: 200px */
}
.flexible-width {
flex: 1; /* Stretch to occupy remaining width i.e. flex-grow: 1 and flex-shrink: 1*/
}
Output:
.container {
display: flex;
width: 100%;
color: #fff;
font-family: Roboto;
}
.fixed-width {
background: #9BCB3C;
width: 200px; /* Fixed width */
text-align: center;
}
.flexible-width {
background: #88BEF5;
flex: 1; /* Stretch to occupy remaining width */
text-align: center;
}
<div class="container">
<div class="fixed-width">
1
</div>
<div class="flexible-width">
2
</div>
<div class="fixed-width">
3
</div>
</div>
Dynamic height:
HTML
<div class="container">
<div class="fixed-height">
1
</div>
<div class="flexible-height">
2
</div>
<div class="fixed-height">
3
</div>
</div>
CSS
.container {
display: flex;
}
.fixed-height {
height: 200px; /* Fixed height or flex-basis: 200px */
}
.flexible-height {
flex: 1; /* Stretch to occupy remaining height i.e. flex-grow: 1 and flex-shrink: 1*/
}
Output:
.container {
display: flex;
flex-direction: column;
height: 100vh;
color: #fff;
font-family: Roboto;
}
.fixed-height {
background: #9BCB3C;
height: 50px; /* Fixed height or flex-basis: 100px */
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
}
.flexible-height {
background: #88BEF5;
flex: 1; /* Stretch to occupy remaining width */
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
}
<div class="container">
<div class="fixed-height">
1
</div>
<div class="flexible-height">
2
</div>
<div class="fixed-height">
3
</div>
</div>
The usual way to do it is as outlined by Guffa, nested elements. It's a bit sad having to add extra markup to get the hooks you need for this, but in practice a wrapper div here or there isn't going to hurt anyone.
If you must do it without extra elements (eg. when you don't have control of the page markup), you can use box-sizing, which has pretty decent but not complete or simple browser support. Likely more fun than having to rely on scripting though.
Maybe I'm being dumb, but isn't table the obvious solution here?
<div class="parent">
<div class="fixed">
<div class="stretchToFit">
</div>
.parent{ display: table; width 100%; }
.fixed { display: table-cell; width: 150px; }
.stretchToFit{ display: table-cell; vertical-align: top}
Another way that I've figured out in chrome is even simpler, but man is it a hack!
.fixed{
float: left
}
.stretchToFit{
display: table-cell;
width: 1%;
}
This alone should fill the rest of the line horizontally, as table-cells do. However, you get some strange issues with it going over 100% of its parent, setting the width to a percent value fixes it though.
We can achieve this using flex-box very easily.
If we have three elements like Header, MiddleContainer and Footer. And we want to give some fixed height to Header and Footer. then we can write like this:
For React/RN(defaults are 'display' as flex and 'flexDirection' as column), in web css we'll have to specify the body container or container containing these as display: 'flex', flex-direction: 'column' like below:
container-containing-these-elements: {
display: flex,
flex-direction: column
}
header: {
height: 40,
},
middle-container: {
flex: 1, // this will take the rest of the space available.
},
footer: {
height: 100,
}
what if your wrapping div was 100% and you used padding for a pixel amount, then if the padding # needs to be dynamic, you can easily use jQuery to modify your padding amount when your events fire.
I had a similar issue where I wanted a banner across the top of the screen that had one image on the left and a repeating image on the right to the edge of the screen. I ended up resolving it like so:
CSS:
.banner_left {
position: absolute;
top: 0px;
left: 0px;
width: 131px;
height: 150px;
background-image: url("left_image.jpg");
background-repeat: no-repeat;
}
.banner_right {
position: absolute;
top: 0px;
left: 131px;
right: 0px;
height: 150px;
background-image: url("right_repeating_image.jpg");
background-repeat: repeat-x;
background-position: top left;
}
The key was the right tag. I'm basically specifying that I want it to repeat from 131px in from the left to 0px from the right.
In some contexts, you can leverage margin settings to effectively specify "100% width minus N pixels". See the accepted answer to this question.