How do I force my column to always stretch to the bottom of the page? - css

I need my content column to expand to the bottom of the page when it's content is shorter than the viewport, but still expand when the content is longer. The column has to come down a little ways from the top of the page.
Here is the HTML for what I described:
<html>
<body>
<div id="content">
<p> asdf ghjkl </p>
</div>
</body>
</html>
Here is the CSS
#content {
min-height: 100%;
margin: 100px 0 0;
}
The issue with this method though is that min-height: 100%; does not take padding into account so the page is always bigger than what I want.
This is the behavior I am seeking:
Is there any way to accomplish this without using Javascript?

Absolute positioning can do this for you:
First remove your min-height and margin then apply this rule to your CSS.
#content {
position: absolute;
top: 100px;
bottom: 0;
}

In CSS3, you can use box-sizing
By setting it to border-box, you can force the browser to instead render the box with the specified width and height, and add the border and padding inside the box.

Ok blokes and birds, here's what I ended up doing. Instead of solving the problem directly, I added a few fixer divs.
First off, here are a few observations:
We know that when #column is longer than the viewport, the length of #column needs to specify the height of <body>.
If #column is shorter than the viewport, the height of the viewport needs to specify the height of <body>.
The column needs stretch to the bottom of the page under all circumstances, regardless of how long it's content is.
For the first criteria we need to make sure that height: auto is set on <body>. Height defaluts to this if it's not set. We also need to make sure that #column has height: auto; and overflow: hidden; so that it expands to the size of it's content.
For the second criteria we need to set position: absolute; and min-height: 100%; on <body>. Now the length of <body> will expand when #column is longer than it, but won't go shorter than the viewport. This next part is where the fix comes in.
For the third criteria, the trick is to add some extra divs and give them some special css. In my HTML I added two divs right outside of #column.
<div id="colhack-outer">
<div id="colhack-inner">
</div>
</div>
<div id="column">
...
</div>
For the outside div you postiion it absolutely and set it's height to 100%, force it to use an alternative box model and shift it's content area using padding. You apply all your column styling (background color, border radius, shadow, etc.) to the inner div. Here is the CSS I applied to them:
#colhack-outer {
height: 100%;
padding: <where you want to shift the column to>;
position: absolute;
width: 50%;
}
#colhack-inner {
height: 100%;
width: 100%;
background-color: #303030;
}
You also have to make your actual content container use that special box model and shift it with padding too:
#contentbox {
position: relative;
padding: <where you want to shift the column to>;
width: 50%;
color: #EEEEEC;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
Live example here: http://nerdhow.net/
post a comment if you have questions or if something wasn't clear.

You can achieve it by using Absolute positioning and adding extra block (if you need a solid background under you column).
So, when you'll have a little content, you'll get http://jsfiddle.net/kizu/7de7m/
And if you'll have a lot of content, you'll get http://jsfiddle.net/kizu/7de7m/3/

Try this jsFiddle: http://jsfiddle.net/8R4yN/. It seems to work the way you want. I took some tips from: http://www.tutwow.com/htmlcss/quick-tip-css-100-height/. It looks like the overflow is causing the hiding, and the #content inside there is also not helping out :).

Related

html - how to make a scroll with the width on auto?

I have a div with lots of content in it, and trying to set a width to be 100% of the parent element. This div also uses a padding, so I thought I should be setting the width to auto.
But for some reason it always expands past the parent width. I even have overflow set to scroll.
What I want is the div to have a scroll bar (only horizontal), and its width to fit the parent width.
Does anyone know how I can fix this?
100% width of its parent, with padding:
Given that the padding you mention is applied to the 100% wide element, the problem is within the box model that browsers use. If you apply 100% width and some padding, the element will get width + padding as its complete width, thus causing it to become too large. There are a few ways to solve this:
CSS3 introduces a new property called box-sizing, by setting it to border-box, the padding will be added within the given width of the element, instead of adding to the width causing the element to become "to big". (Notice the lack of support by older browsers).
I believe it would be possible to use left: 0; right: 0; instead of using width: 100%;. In that case you can add padding, without the element becoming to wide.
The second option in practice:
<!-- The markup -->
<div class="parent">
<div class="child">Child</div>
</div>​
/* The CSS */
.parent {
width: 200px;
height: 200px;
position: relative;
background-color: #666;
}
.child {
position: absolute;
left: 0;
right: 0;
padding: 10px;
background-color: #888;
}
​
Here is a working example of the second option: http://jsfiddle.net/mGLRD/
Horizontal scroll-bar:
To get a horizontal scroll-bar, you will have to look in to the overflow-x CSS-property. By setting it to scroll, you will see a disabled scrollbar when there is no content to scroll, so the scrollbar is always visible. Your other option is to set it to auto, where the scrollbar will become visible if needed (may vary between different browsers).
Try:
div#content {
width:auto;
padding:20px;
overflow-x:auto;
}
See my demo: http://jsfiddle.net/HRRsU/3/
box-sizing: border-box;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
http://www.w3schools.com/cssref/css3_pr_box-sizing.asp

CSS: layer two elements centered

How can I do this:
an image
a simple small DIV on top of the image, centered vert/horiz, which doesn't appear until the image is rolled-over
Try this:
<div style="position:relative;top:0;left:0;">
<img src="path/2/img.png" style="z-index:1;"
onmouseover="document.getElementById('hidden').style.display='block';">
<div id="hidden" style="display:none;position:absolute;z-index:10;"></div>
</div>
If it works for you, clean it up before you deploy it! :)
NOTE: div#hidden is not yet centered over the image. If you know the width and height of it in advance, you can use this method:
#hidden {
top:50%;
left:50%;
margin-top: -(heightOfHiddenDiv/2)px
margin-left: -(widthOfHiddenDiv/2)px
}
Otherwise you will need to get the computed values of width and height in JavaScript.
If you can have a fixed width and height for the <div>, then I’d suggest this:
HTML
<div class="hover_image">
<img width="250" height="300" src="http://pauldwaite.me.uk/images/professional.jpg" />
<div class="overlay">Hello!</div>
</div>
CSS
.hover_image {
position: relative;
float: left;
}
.hover_image .overlay {
visibility: hidden;
position: absolute;
top: 50%;
left: 50%;
width: 100px;
height: 3em;
margin: -2em 0 0 -55px;
padding: .5em 5px;
background: #006;
color: #fff;
}
.hover_image:hover .overlay {
visibility: visible;
}
http://jsfiddle.net/ZKXgw/
You may need to add some JavaScript to make .hover_image:hover work in earlier versions of IE, which didn’t support :hover on anything except links.
If you can’t have a fixed width/height, it’ll be a lot tricker to achieve.
Things aren't really clear to me, any way you can play with the CSS/style of the element to work around on this.
To center an element you can set the top and left by 50% where its position is set to absolute. Then set the margin-top the half size of its height in negative, and the margin-left the half size of its width in negative.
To place the div in top of the image, its z-index must be higher than the image. But first the image must have the higher z-index until its not rolled-over.
To show the div on top of the image change the z-index of the image lower then the div. Using hover or onMouseOver event. There other ways of doing this, base on your needs.
See jsfiddle in action
You can use z-index property with absolute positioning to place the div on top of the image. Since you want this to be hidden, set the "display" property in css to "none".
The second part of your question can be accomplished by using a javascript function that you can call onmouseover [ http://www.w3schools.com/jsref/event_onmouseover.asp ]. All the function would have to do is change the "display" property of the element from "none" to "block".

CSS: div expanding to window height, with margin-bottom fixed

I've been trying to do something extremely simple, yet I can't make it work!
Here's what I'm trying:
---margin top: 15 px
---VARIABLE HEIGHT DIV (imagine a box-like element)
---margin bottom: 15px
I basically want the box to resize based on the browser window height.
Here's what I've been trying:
CSS
body {
background-color: #D0CDC5;
height:100%
}
#info_box {
background-color: rgba(40,40,40,0.5);
border: rgba(34,34,34,0.9) 1px solid;
width: 350px;
height: 100%;
margin: 15px 0px 15px 20px;
}
#info_box p {
color: red;
}
HTML
<body>
<div id="info_box">
<p>Sample Content</p>
</div>
</body>
By the way, why is that the text appears 15px from the top of the div? Why isn't it flush?
Thanks a lot guys,
**EDIT
See this link, very good answer for all browser but IE6 and 7. another HTML/CSS layout challenge
Thanks to #Hristo!
UPDATE
Check out the fiddle...
Edit, Full Screen
Check out the fiddle... http://jsfiddle.net/UnsungHero97/uUEwg/1/
I hope this helps.
Hristo
if you don't need to support IE6, and this is not part of a bigger layout, there is an easy way:
#info_box {
position: fixed;
left: 0px;
top: 15px;
right: 0px;
bottom: 15px;
}
alternatively, you could make #info_box stretch the full height, and put a position: absolute div into it with the same data as above.
I'm not entirely sure whether there's a way to do this without absolute or fixed positioning, because no matter whether you use padding or margin, you'll always end up adding 30 pixels to what is already 100% of the height. I'm happy to be proven wrong though.
Elements get their height based on the content inside them. So you already have an element that is centered and that will have margin top and bottom of 15px from the top and bottom of you site's body.
But if you want an element that will always be centered middle of screen, filling all but 15px top and 15px bottom, it is not achievable with "conventional" means. It will either have to be an image or a re-sizable box that will have a scroll-bar if the content is bigger than screen size.
Anyways, if that is what you want, give it a fixed size and height, and use position:fixed.
If you always use a consistent browser resolution, then it is doable. But if your screen size changes, depending on the device you use (tablet, mobile etc.), then this cannot be accomplished though CSS alone.
I have done this dynamically using jQuery.

Getting a horizontal scroll bar within a 100% div

I'm trying to build a quick overview that shows the upcoming calendar week. I want it arranged horizontally so it can turn out to be quite wide if we show a full calendar week.
I've got it set up right now with an inner div with a fixed width (so that the floated "day" divs don't return below) and an outer div that's set to width: 100%. I'd LIKE for the outer div to scroll horizontally if the page is resized so that the inner div no longer fits in it, but instead the outer div is fixed larger at the width of the inner div and the page itself scrolls.
Gah I'm not good at explaining these things... Here's a bit of code that might clear it up..
The CSS:
.cal_scroller {
padding: 0;
overflow: auto;
width: 100%;
}
.cal_container {
width: 935px;
}
.day {
border: 1px solid #999;
width: 175px;
height: 200px;
margin: 10px;
float: left;
}
and the (simplified) structure:
<div class="cal_scroller">
<div class="cal_container">
<div class="day">Monday</div>
<div class="day">Tuesday</div>
<div class="day">Wednesday</div>
<div class="day">Thursday</div>
<div class="day">Friday</div>
</div>
</div>
So to try again - I'd like the cal_scroller div always be the page width, but if the browser is resized so that the cal_container doesn't fit anymore I want it to scroll WITHIN the container. I can make it all work if I set a fixed width on cal_scroller but that's obviously not the behavior I'm going for. I'd rather not use any javascript cheats to adjust the width of the div if I don't have to.
Your cal_scroller class is 100% + 20px (padding) wide. Use a margin on cal_container instead, like so:
.cal_scroller {
padding: 10px 0;
overflow: auto;
width: 100%;
}
.cal_container {
margin: 0 10px;
width: 935px;
}
See here for a description of how the box model works (in short, the everything is outside the width/height of an element).
Also, block elements (like <div>s) are 100% width by default, making your 100% width declaration redundant.
One problem I see is your width: 100% rule. div.cal_scroller is already a block-level element, so it'll default to filling the entire page width. (Not to mention that padding is added on top of width, so you end up with that div being bigger than the page.)
Just get rid of that width rule, and you should be golden. (I just tried myself, and it worked like a charm.)
I didn't read your question very carefully, but when you have width: 100% and padding, that's generally not what you want.
100% + 20px > 100% - that might be the problem.
I struggled with this a lot but the simplest solution I found was adding:
.cal_container { white-space: nowrap; }
This way you don't have to give it a width at al. It just makes sure everything stays in one line.

CSS 100% height with padding/margin

With HTML/CSS, how can I make an element that has a width and/or height that is 100% of it's parent element and still has proper padding or margins?
By "proper" I mean that if my parent element is 200px tall and I specify height = 100% with padding = 5px I would expect that I should get a 190px high element with border = 5px on all sides, nicely centered in the parent element.
Now, I know that that's not how the standard box model specifies it should work (although I'd like to know why, exactly...), so the obvious answer doesn't work:
#myDiv {
width: 100%
height: 100%;
padding: 5px;
}
But it would seem to me that there must be SOME way of reliably producing this effect for a parent of arbitrary size. Does anyone know of a way of accomplishing this (seemingly simple) task?
Oh, and for the record I'm not terribly interested in IE compatibility so that should (hopefully) make things a bit easier.
EDIT: Since an example was asked for, here's the simplest one I can think of:
<html style="height: 100%">
<body style="height: 100%">
<div style="background-color: black; height: 100%; padding: 25px"></div>
</body>
</html>
The challenge is then to get the black box to show up with a 25 pixel padding on all edges without the page growing big enough to require scrollbars.
I learned how to do these sort of things reading "PRO HTML and CSS Design Patterns". The display:block is the default display value for the div, but I like to make it explicit. The container has to be the right type; position attribute is fixed, relative, or absolute.
.stretchedToMargin {
display: block;
position:absolute;
height:auto;
bottom:0;
top:0;
left:0;
right:0;
margin-top:20px;
margin-bottom:20px;
margin-right:80px;
margin-left:80px;
background-color: green;
}
<div class="stretchedToMargin">
Hello, world
</div>
Fiddle by Nooshu's comment
There is a new property in CSS3 that you can use to change the way the box model calculates width/height, it's called box-sizing.
By setting this property with the value "border-box" it makes whichever element you apply it to not stretch when you add a padding or border. If you define something with 100px width, and 10px padding, it will still be 100px wide.
box-sizing: border-box;
See here for browser support. It does not work for IE7 and lower, however, I believe that Dean Edward's IE7.js adds support for it. Enjoy :)
The solution is to NOT use height and width at all! Attach the inner box using top, left, right, bottom and then add margin.
.box {margin:8px; position:absolute; top:0; left:0; right:0; bottom:0}
<div class="box" style="background:black">
<div class="box" style="background:green">
<div class="box" style="background:lightblue">
This will show three nested boxes. Try resizing browser to see they remain nested properly.
</div>
</div>
</div>
The better way is with the calc() property. So, your case would look like:
#myDiv {
width: calc(100% - 10px);
height: calc(100% - 10px);
padding: 5px;
}
Simple, clean, no workarounds. Just make sure you don't forget the space between the values and the operator (eg (100%-5px) that will break the syntax. Enjoy!
According the w3c spec height refers to the height of the viewable area e.g. on a 1280x1024 pixel resolution monitor 100% height = 1024 pixels.
min-height refers to the total height of the page including content so on a page where the content is bigger than 1024px min-height:100% will stretch to include all of the content.
The other problem then is that padding and border are added to the height and width in most modern browsers except ie6(ie6 is actually quite logical but does not conform to the spec). This is called the box model. So if you specify
min-height: 100%;
padding: 5px;
It will actually give you 100% + 5px + 5px for the height. To get around this you need a wrapper container.
<style>
.FullHeight {
height: auto !important; /* ie 6 will ignore this */
height: 100%; /* ie 6 will use this instead of min-height */
min-height: 100%; /* ie 6 will ignore this */
}
.Padded {
padding: 5px;
}
</style>
<div class="FullHeight">
<div class="Padded">
Hello i am padded.
</div
</div>
1. Full height with padding
body {
margin: 0;
}
.container {
min-height: 100vh;
padding: 50px;
box-sizing: border-box;
background: silver;
}
<div class="container">Hello world.</div>
2. Full height with margin
body {
margin: 0;
}
.container {
min-height: calc(100vh - 100px);
margin: 50px;
background: silver;
}
<div class="container">Hello world.</div>
3. Full height with border
body {
margin: 0;
}
.container {
min-height: 100vh;
border: 50px solid pink;
box-sizing: border-box;
background: silver;
}
<div class="container">Hello world.</div>
This is one of the outright idiocies of CSS - I have yet to understand the reasoning (if someone knows, pls. explain).
100% means 100% of the container height - to which any margins, borders and padding are added. So it is effectively impossible to get a container which fills it's parent and which has a margin, border, or padding.
Note also, setting height is notoriously inconsistent between browsers, too.
Another thing I've learned since I posted this is that the percentage is relative the container's length, that is, it's width, making a percentage even more worthless for height.
Nowadays, the vh and vw viewport units are more useful, but still not especially useful for anything other than the top-level containers.
Another solution is to use display:table which has a different box model behaviour.
You can set a height and width to the parent and add padding without expanding it. The child has 100% height and width minus the paddings.
JSBIN
Another option would be to use box-sizing propperty. Only problem with both would be they dont work in IE7.
Another solution: You can use percentage units for margins as well as sizes. For example:
.fullWidthPlusMargin {
width: 98%;
margin: 1%;
}
The main issue here is that the margins will increase/decrease slightly with the size of the parent element. Presumably the functionality you would prefer is for the margins to stay constant and the child element to grow/shrink to fill changes in spacing. So, depending on how tight you need your display to be, that could be problematic. (I'd also go for a smaller margin, like 0.3%).
A solution with flexbox (working on IE11): (or view on jsfiddle)
<html>
<style>
html, body {
height: 100%; /* fix for IE11, not needed for chrome/ff */
margin: 0; /* CSS-reset for chrome */
}
</style>
<body style="display: flex;">
<div style="background-color: black; flex: 1; margin: 25px;"></div>
</body>
</html>
(The CSS-reset is not necessarily important for the actual problem.)
The important part is flex: 1 (In combination with display: flex at the parent). Funnily enough, the most plausible explanation I know for how the Flex property works comes from a react-native documentation, so I refer to it anyway:
(...) flex: 1, which tells a component to fill all available space, shared evenly amongst other components with the same parent
To add -webkit and -moz would be more appropriate
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
Frank's example confused me a bit - it didn't work in my case because I didn't understand positioning well enough yet. It's important to note that the parent container element needs to have a non-static position (he mentioned this but I overlooked it, and it wasn't in his example).
Here's an example where the child - given padding and a border - uses absolute positioning to fill the parent 100%. The parent uses relative positioning in order to provide a point of reference for the child's position while remaining in the normal flow - the next element "more-content" is not affected:
#box {
position: relative;
height: 300px;
width: 600px;
}
#box p {
position: absolute;
border-style: dashed;
padding: 1em;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
<div id="box">
<p>100% height and width!</p>
</div>
<div id="more-content">
</div>
A useful link for quickly learning CSS positioning
This is the default behavior of display: block The fastest way that you can fix it in 2020 is to set display: 'flex' of parent element and padding e.g. 20px then all its children will have 100% height relative to its height.
Border around div, rather than page body margin
Another solution - I just wanted a simple border around the edge of my page, and I wanted 100% height when the content was smaller than that.
Border-box didn't work, and the fixed positioning seemed wrong for such a simple need.
I ended up adding a border to my container, instead of relying on the margin of the body of the page - it looks like this :
body, html {
height: 100%;
margin: 0;
}
.container {
width: 100%;
min-height: 100%;
border: 8px solid #564333;
}
<style type="text/css">
.stretchedToMargin {
position:absolute;
width:100%;
height:100%;
}
</style>

Resources