I'm putting together a Tumblr layout and I'm running into a snag. I got everything working fine, but as soon as I added my sidebar, the container stopped expanding the height of the page. It stops right under the end of the sidebar and I'm not sure why when previously it expanded the width of the content section.
URL: http://nellyswritingroom.tumblr.com/
Structural CSS:
#container {
margin: 0 auto;
padding: 30px 60px 30px 60px;
width: 900px;
}
#main {
margin-top: 50px;
}
#content {
width: 620px;
float: left;
margin: 0;
}
aside {
width: 220px;
float: left;
margin-left: 60px;
}
header#top {
text-align: center;
height: 293px;
margin-bottom: 8px;
}
header#top h1{
position:relative;
width:500px;
height:285px;
overflow:hidden;
float:left;
}
header#top h2 {
position:relative;
width:400px;
height:285px;
overflow:hidden;
float:left;
}
HTML skeleton:
<div id="container">
<header id="top>
<h1>
content
</h1>
<h2>
content
</h2>
</header>
<nav>Nav Goes here</nav>
<section id="content">
Content on the left
</section>
<aside>
Sidebar Content
</aside>
</div>
Any help would be greatly appreciated!
You need to add a clear: both; after the aside element closes.
So, after:
<aside>
Testing
</aside>
Add:
<div style="clear: both;"></div>
And you will see the issue should be resolved.
Of course, it would be better to make a .clear CSS class and call that, rather than using inline CSS.
Because #content is floated it is no longer part of the layout, thus the parent is only sized to contain the sidebar.
You should remove the float:left from the content section, and apply float:right to the aside. This does assume the content is always longer than the sidebar - if this isn't the case you can either employ a clearing element below both elements, or float the container as well, or look into display:block or relative positioning to position them next to eachother.
Related
In order to understand what does a block formatting context do, I'm trying to find out what's going on when a BFC is not created.
I took the following demo from Everything you Know about Clearfix is Wrong:
.wrapper {
width: 740px;
background: #cccccc;
}
.leftSidebar {
float: left;
width: 200px;
}
.rightSidebar {
float: right;
width: 200px;
}
.mainContent {
padding-right: 200px;
padding-left: 200px;
}
.floatMe {
float: left;
background: teal;
color: #fff;
}
<div class="wrapper">
<div class="leftSidebar">
<h2>Heading</h2>
<pre>.leftSidebar {
float:left;
width:200px;
}</pre>
</div>
<div class="rightSidebar">
<h2>Heading</h2>
<pre>.rightSidebar {
float:right;
width:200px;
}</pre>
</div>
<div class="mainContent">
<h2>Heading</h2>
<pre>.mainContent {
padding-right:200px;
padding-left:200px;
}</pre>
<div class="floatMe">
<pre>.floatMe {
float:left;
background:teal;
color:#fff;
}</pre>
</div>
</div>
</div>
According to that article(emphasis mine):
In modern browsers:
All elements belong to the same block formatting context so adjacent
margins collapse. The heading’s margin “sticks out” of the wrapper to
butt against the p. Unlike in IE, it is that margin (not the one on
the black box) that creates the gap above the wrapper.
I cannot understand what does "the same block formatting context" refers to. I want to know why such a weird layout is produced without a block formatting context.
I've tried to figure out the exact layout by adding * {border: 1px solid blue;} to CSS, but the overall layout changed greatly after this change: now it behaves as if wrapper is a block formatting context!
.wrapper {
width: 740px;
background: #cccccc;
}
.leftSidebar {
float: left;
width: 200px;
}
.rightSidebar {
float: right;
width: 200px;
}
.mainContent {
padding-right: 200px;
padding-left: 200px;
}
.floatMe {
float: left;
background: teal;
color: #fff;
}
* {
border: 1px solid blue;
}
<div class="wrapper">
<div class="leftSidebar">
<h2>Heading</h2>
<pre>.leftSidebar {
float:left;
width:200px;
}</pre>
</div>
<div class="rightSidebar">
<h2>Heading</h2>
<pre>.rightSidebar {
float:right;
width:200px;
}</pre>
</div>
<div class="mainContent">
<h2>Heading</h2>
<pre>.mainContent {
padding-right:200px;
padding-left:200px;
}</pre>
<div class="floatMe">
<pre>.floatMe {
float:left;
background:teal;
color:#fff;
}</pre>
</div>
</div>
</div>
Please tell me what's going on.
Good question, got me thinking a lot!
There are lot of concepts at play here, so I'll get to them one by one:
Buggy IE:
Whatever is mentioned in this old article about IE can be easily ignored if you do not have to design for IE7 or IE8 compatibility mode. This behavior is due to hasLayout property used internally by IE7.
See this MSDN doc for IE7:
What is "HasLayout" and why is it important?
There are several bugs in
Internet Explorer that can be worked around by forcing "a layout" (an
IE internal data structure) on an element.
Clearly this is a non-standard workaround and along with brings up a lot of inconsistencies. Read about this here too.
Block Formatting Context (BFC):
Excerpts from this MDN doc:
A block formatting context is a part of a visual CSS rendering of a
Web page. It is the region in which the layout of block boxes occurs
and in which floats interact with each other.
BFCs are very important for positioning and clearing of floated elements- floated elements affects only within the same BFCs. When you float an element, it is taken out of the flow and reinserted by "floating".
See the examples below:
The inside of wrapper is a BFC where you float one div to left and another to the right.
The floated elements are reinserted into the BFC while rendering around the element that is not floated.
As you have not cleared the floating in the BFC, the wrapper height will extend to the size of the element that is not floated.
body{
margin: 0;
}
*{
box-sizing: border-box;
}
.wrapper{
border: 1px solid;
}
.wrapper > * {
display: inline-block;
border: 1px solid red;
width: 33.33%;
height: 100px;
}
.left{
float: left;
}
.right{
float: right;
}
.center{
height: 50px;
}
<div class="wrapper">
<div class="left">Left</div>
<div class="center">Center</div>
<div class="right">Right</div>
</div>
See what happens when you clear the floating in the BFC- now the heights will behave normally in the wrapper BFC.
body{
margin: 0;
}
*{
box-sizing: border-box;
}
.wrapper{
border: 1px solid;
}
.wrapper > * {
display: inline-block;
border: 1px solid red;
width: 33.33%;
height: 100px;
}
.left{
float: left;
}
.right{
float: right;
}
.center{
height: 50px;
}
.wrapper:after{
content: '';
display: block;
clear: both;
}
<div class="wrapper">
<div class="left">Left</div>
<div class="center">Center</div>
<div class="right">Right</div>
</div>
Collapsing Margins:
Top and bottom margins of blocks are sometimes combined (collapsed)
into a single margin whose size is the largest of the margins combined
into it, a behavior known as margin collapsing.
Margins collapse for adjacent blocks, parent and first/last child and empty blocks. See more about margin collapsing in this MDN doc.
Also note that:
Margins of floating and absolutely positioned elements never collapse.
So what really happens here?
So now you will have understood about BFCs and also how floating containers work in first case (when you have no borders specified) - that's why floatMe stays out of its immediate mainContent wrapper and exactly why the height of wrapper and mainContent is as it looks there.
Layout and IE referred to are only in IE7 and is non-standard.
Everything else that happens is because of margin collapsing:
a. h2 and pre margins collapse (adjacent siblings)
b. mainContent shifts a little bit to the top to collapse with the margin on the body (Parent and first/last child)
c. As wrapper takes the height of mainContent, the wrapper height is also shifted upwards.
d. What happens when you apply borders is that the margin collapsing in (b) above is nullified! (see MDN doc above as to why)
Hope things are looking better now. Cheers!
I have a wrapper div in my css that covers most of my viewport. I have a background color and inside that div, I have two more divs floated right and left respectively.
When I'm with Chrome, I can see the background code perfectly, but when I'm with Firefox, the background color is not seen. Here are some screenshots:
On Chrome:
On Firefox
And here's the code.
My HTML:
<div id="wrapper">
<div id="asd"></div>
<div id="perejavi">
<p id="pere">Pere</p>
<p id="and">&</p>
<p id="javi">Javi</p>
</div>
<div id="web">
<p id="programmer">Programación</p>
<p id="programmer2">diseño web</p>
</div>
My CSS:
#wrapper {
background-color: #00CE6B;
height: auto;
min-height: 93%;
width: 85%;
color: #ffffff;
margin: 0 auto;
}
#perejavi {
margin: 0;
font-size: 9.1em;
float: left;
padding-bottom: 0;
height: 60%;
width: 50%;
}
#web {
margin: 0;
width: 50%;
height: 60%;
float: right;
}
Why is this happening? Hope you can help!;)
Floats remove the HTML element from the normal document flow and can cause issues like this. There are a couple ways to handle floats but i'll just give you the way I prefer to do it:
in your css:
.clearfix:after {
visibility:hidden;
display:block;
font-size:0;
content:" ";
clear:both;
height:0;
}
Then in your HTML:
<div id="wrapper" class="clearfix>
This creates a pseudo element as the last child of your .clearfix div which clears the floated elements contained within the .clearfix div
note: Also, you seem to be missing your closing </div> for your wrapper div. Make sure you add that in
Further reading on floats and the strangeness they bring with them:
http://css-tricks.com/all-about-floats/
I structured my site like this:
<body>
<div class="main">
<div class="header">
content
</div>
<div class="section">
content
</div>
<div class="sidebar">
content
</div>
<div class="clearing"></div>
<div class="footer">
content
</div>
</div>
</body>
and the css
.main {
position:relative;
width:908px;
margin-top:0px;
border:solid 0px;
margin:0 auto;
}
.header {
position:relative;
height:200px;
margin: auto;
}
div.section {
float:left;
position:absolute;
width: 584px;
height:500px;
margin-top: 0px;
margin-left: auto;
margin-right: auto;
text-align:left;
}
div.sidebar{
float:right;
position:relative;
width: 324px;
height:500px;
margin-top: 0px;
margin-left: auto;
margin-right: auto;
text-align:left;
}
.clearing {
clear:both;
}
.footer {
position:relative;
left:0px;
top:0px;
width:908px;
height:300px;
}
When I add content to the div section, I goes all over the footer. The footer is fixed at that point, and as content is added, the page grows and the footer remains still.
What I have to do everytime I add content is to increase in the css file either the height of the section or the height of the sidebar - either one would work - but I increase both heights (section and sidebar) to the same value, because it seems the right thing to do. The footer then is pushed down as the height of the section and the sidebar grows.
However, if I atribute a height to the content that I add to the section, it does not have any effect on the position of the footer, perhaps because it has nothing to do with the height of the section itself.
Is there a way to make the footer respond to the space the content being added will occupy, and just automatically move along, remaining at the bottom of the page ?
You have position:absolute set on your .section div, which will only ever use its CSS height value for the amount of space it takes up, regardless of its actual content. Removing that absolute position should solve your problems. There's (almost) always a way around absolute positioning. In your example, it seems completely unnecessary.
Here's a helpful site for CSS positioning:
http://www.barelyfitz.com/screencast/html-training/css/positioning/
Hope it helps!
Try this:
.footer {
position:relative;
left:0;
bottom:0;
width:908px;
height:300px;
}
Also when putting 0, there is no need to add the px.
I am checking the CSS code and have spotted position in every div. Try to balance it because it affects other divs
Also try
.footer{
clear: both
}
I am trying to get a centered in the space that is left empty by a sidebar. This is how I'd like it to look like:
I actually managed to make this work OK for most browsers using margin: auto for the div in question, while setting overflow: hidden:
Fiddle here
CSS
#header {
height: 50px;
background: #224444;
color: #fff;
}
#container div {
padding: 1em;
}
#content {
max-width: 400px;
margin: auto;
background: #ddd;
height: 300px;
overflow: hidden;
}
#sidebar {
float: right;
width: 200px;
background: #aaa;
height: 300px;
}
HTML
<div id="container">
<div id="header">
PAGE HEADER
</div>
<div id="sidebar">
Sidebar
</div>
<div id="content">
Centered Content
(Works everywhere but on IE9)
</div>
</div>
However, it does not work with IE9. It is strange as IE8 works OK!
I am running out of ideas, so I thought that maybe someone knows what is going on? The trick seems to work perfectly everywhere else.
NOTE: Please note that the content div should be flexible as it is in the demo. As the available space decreases, it should change size and squeeze in.
Isolate the centering from the floating
This affects IE9/10.
It works fine if the floated element is removed, or if width is used instead of max-width. The presence of floated content, combined with the use of margin:auto and max-width instead of width, appears to be confusing IE9+.
To fix this, put the centered content in a wrapper div, so that the centering of the content can be separated from the floating of the sidebar. In other words, too much is happening layout-wise in a single div, more than IE9+ can handle. So split up the #content div into two separate divs.
#header {
height: 50px;
padding: 1em;
background: #224444;
color: #fff;
}
#content-wrapper {
overflow: hidden;
}
#content {
max-width: 400px;
margin: auto;
padding: 1em;
background: #ddd;
height: 300px;
}
#sidebar {
float: right;
width: 200px;
padding: 1em;
background: #aaa;
height: 300px;
}
<div id="container">
<div id="header">
PAGE HEADER
</div>
<div id="sidebar">
Sidebar
</div>
<div id="content-wrapper">
<div id="content">
Centered Content
</div>
</div>
</div>
This tested fine in IE7/8/9/10. On a side note, because a wrapper div was added, the padding: 1em; now has to be added to each element individually.
IE is notorious for not working without proper doctypes.
Try adding the HTML5 one
<!DOCTYPE html>
Floats are a tricky business. Strictly speaking, they're only supposed to affect the inline content that flows around them, so margins acts like the floats aren't even there.
Try this instead:
#container {text-align:center}
#content {display:inline-block;text-align:left}
This should make the content box act like an inline element, and therefore appear centered in the space.
As far as I remeber I've always problems with margin:0 auto because I didn't specify width property.
So everytime you want use margin:auto you propably should write this:
#content {
max-width: 400px;
margin: auto;
background: #ddd;
height: 300px;
overflow: hidden;
width:500px;
}
or in percentage:
#content {
max-width: 400px;
margin: auto;
background: #ddd;
height: 300px;
overflow: hidden;
width:30%;
}
EDIT
If you want to create flexible layout please take a look to bootstrap and fluid grids.
I have a page that has a header, content, and footer. The header and footer are of fixed height, and I'd like the content to adjust its height so that it fits dynamically between the header and footer. I am planning to put a background-image in my content, so it is critical that it actually fills the rest of the unoccupied vertical space.
I used the Sticky Footer approach to ensure that the footer remains on the bottom of the page. This however does not make the content span the entire height of the remaining space.
I have tried several solutions which involved me adding height:100%, height:auto; position:relative but it did not work.
html,
body {
height: 100%;
background-color: yellow;
}
header {
width: 100%;
height: 150px;
background-color: blue;
}
header nav ul li {
display: inline;
padding: 0 30px 0 0;
float: left;
}
#wrapper {
min-height: 100%;
height: auto !important;
height: 100%;
margin: 0 0 -30px 0;
/* the bottom margin is the negative value of the footer's height */
position: relative;
}
#wrapper #content {
background-color: pink;
width: 400px;
height: 100%;
margin: 0 0 -30px 100px;
padding: 25px 30px 25px 30px;
}
footer {
margin: -30px 0 0 0;
width: 100%;
height: 30px;
background-color: green;
}
<div id="wrapper">
<header>
<div id="logo"></div>
<nav>
<ul>
<li>About</li>
<li>Menu</li>
<li>Specials</li>
</ul>
</nav>
</header>
<div id="content">
content
<br>goes
<br>here
</div>
</div>
<footer>footer</footer>
The trick about height:100% is that it requires all of the parent containers to be have their heights set as well. Here's an html example
<html>
<body>
<div id="container">
</div>
</body>
</html>
in order for the container div with a height set to 100% to expand dynamically to the height of the window you need to make sure that the body and html elements have their heights set to 100% as well. so...
html
{
height: 100%;
}
body
{
height: 100%;
}
#container
{
height: 100%;
}
would give you a container that expands to fit your window. then if you need to have footer or header that floats above this window you can do so with z indexing. This is the only solution I've found that fills the vertical height dynamically.
I'm providing a slightly more general solution so it is more useful for others reading this answer and wondering how to apply it to their site.
Assuming you have three divs:
<div id='header'></div>
<div id='contents'></div>
<div id='footer'></div>
where #header is fixed and may have variable height, #contents should consume all remaining vertical space and #footer is fixed and may have variable height you can do:
/* Note you could add a container div instead of using the body */
body {
display: flex;
flex-direction: column;
}
#header {
flex: none;
}
#contents {
flex: 1;
height: 100%;
overflow-y: scroll;
}
#footer {
flex: none;
}
Note that this will allow the contents to scroll vertically to show it's whole contents.
You can read more about display:flex here.
Try changing your css to this:
html,
body {
height: 100%;
background-color: yellow;
}
header {
width: 100%;
height: 150px;
background-color: blue;
}
header nav ul li {
display: inline;
padding: 0 30px 0 0;
float: left;
}
#wrapper {
min-height: 100%;
height: auto !important;
height: 100%;
margin: 0 0 -30px 0;
/* the bottom margin is the negative value of the footer's height */
position: relative;
}
#content {
background-color: pink;
width: 400px;
padding: 25px 30px 25px 30px;
position: absolute;
bottom: 30px;
top: 150px;
margin-left: 100px;
}
footer {
margin: -30px 0 0 0;
width: 100%;
height: 30px;
background-color: green;
}
<div id="wrapper">
<header>
<div id="logo"></div>
<nav>
<ul>
<li>About</li>
<li>Menu</li>
<li>Specials</li>
</ul>
</nav>
</header>
<div id="content">
content
<br>goes
<br>here
</div>
</div>
<footer>footer</footer>
You probably don't want to be setting the width, padding, margins, ect. of the wrapper. Also, with absolute positioning you can pull the bottom and top of the content to where you want them.
Here's what you are after, I think.
I spend several hours trying to figure this out too and finally have a robust solution without hacks. However, it requires CSS3, which requires a modern browser to support it. So, if this constraint works for you, then I have a real solution for you that works.
http://jsfiddle.net/u9xh4z74/
Copy this code into your own file if you need proof, as the JSFiddle will not actually render the flexbox correctly as embedded code.
Basically, you need to
- set the target container to 100% height, which you seem to already know
- the parent container you set display: flex and flex-direction: vertical (you'll see in the JSFiddle I've also included the alternate styles that do the same thing but are needed for cross browser support)
- you can let the header and footer be their natural heights and dont need to specify anything in that regard
- in the container you want to fill up the remaining space, set flex: 1. You're set! You'll see it works exactly as you semantically have intended. Also in the JSFiddle, I included overflow: auto to demonstrate that if you have even more text than the screen can handle, scrolling works as you would want it to.
<div style="display:flex; flex-direction:vertical;">
...header(s)...
<div style="flex: 1; overflow: auto;">
As much content as you want.
</div>
...footer(s)...
</div>
As a side note, I pursued the option of trying to do this same thing using display: table. It works just fine as well, except that overflowed content does not work as you would expect, instead overflowed content simply expands the container to the size of the content, which I'm pretty sure is not what you want. Enjoy!
Use display:table and display:table-row
Set height:0 for normal divs and height:auto for div that should fill vertical space. Insert a div with {height:100%; overflow-y:auto} into the vertical filler to if the containers height shouldn't expand beyond its preset height.
Behold the power of display:table!
<div style="height:300px;">
<div style="display:table; height:100%; width:100%;border: 1px solid blue;">
<div style="display: table-row; height:0; padding:2px; background-color:yellow;">
Hello
</div>
<div style="display: table-row; height:auto; padding:2px; background-color:green;">
<div style="height:100%; overflow: auto;">
<div style="height: 500px"></div>
</div>
</div>
<div style="display: table-row; height:0; padding:2px; background-color:yellow;">
Gbai
</div>
</div>
</div>
There is no 100% height from 100% continer height exactly. You can't solve it this way. Likewise while using mix of height + margin + padding. This is way straight to hell. I suggest you to take a look for tutorials which are sloving this page layout.