Assume, that I have three boxes (divs) on website (see image below):
header with logo
content with some text
footer with contact info
Each box have unique color (in order: yellow, orange and blue) and black border.
I would like to website always fills the entire screen, the logo was on the top and the footer was at the bottom. So if there is not enough text in content, content should be extended, so that the footer was on the bottom. And if will be a lot of text in content, slider should appear on the right.
How do this in CSS? Important is that boxes have backgrounds. I found many solutions, but none doesn't work properly with backgrounds.
Solution Explained
The black box in your diagram gets min-height 100%, is the scrolling container, and is position relative, to allow child positions to be respective to it.
The red box in your diagram is actually composed of 2 boxes:
one for your dynamically-sized content; this has sufficient top and bottom padding to make room for your header and footer, and force the scrolling container to expand
one for the background; this is position absolute, with top and bottom position specified relative to the black box, its parent.
The yellow and blue boxes in your diagram can be position: absolute, top: 0 and bottom: 0, respectively... or however you choose to position them.
Here's a fiddle of it: http://jsfiddle.net/syndicatedshannon/F5c6T/
And here is another version with explicit viewport elements just to clarify, matching colors, and borders added to replicate the OP graphics (although per the OP the black border is actually the window).
Sample HTML
<html>
<body>
<div class="background"></div>
<div class="content"></div>
<div class="header"></div>
<div class="footer"></div>
</body>
</html>
Sample CSS
html { position: absolute; height: 100%; left: 10px; right: 10px; overflow: auto; margin: 0; padding: 0; }
body { position: relative; width: 100%; min-height: 100%; margin: 0; padding: 0; }
.background { position: absolute; top: 120px; bottom: 120px; background-color: red; width: 100%; }
.content { position: relative; padding: 120px 0; }
.header { position: absolute; top: 10px; height: 100px; width: 100%; background-color: yellow; }
.footer { position: absolute; bottom: 10px; height: 100px; width: 100%; background-color: cyan; }
Also note that this assumes you cannot rely on CSS3 yet.
If you're only targeting modern browsers, you can use calc()
body, html {
height: 100%;
padding: 0;
margin: 0;
}
.header {
height: 50px;
margin-bottom: 10px;
}
.footer {
height: 100px;
margin-top: 20px;
}
.content {
min-height: calc(100% - 50px - 10px - 100px - 20px);
}
The drawback is that you need to know the header and footer sizes and they need to be fixed. I don't know any way around this without using Javascript. For slightly less modern browsers, you can use border-box to get the same effect as above.
body, html {
height: 100%;
padding: 0;
margin: 0;
}
.header {
height: 50px;
margin-bottom: 10px;
z-index: 5;
position: relative;
}
.footer {
height: 100px;
margin-top: -100px;
z-index: 5;
position: relative;
}
.content {
box-sizing: border-box;
padding: 60px 0 120px 0;
margin-top: -60px;
min-height: 100%;
z-index: 1;
position: relative;
}
Lastly, here is the JS solution:
$(function(){
$('.content').css('min-height',
$(window).height()
- $('.header').outerHeight()
- $('.footer').outerHeight() - $('.content').marginTop()
- $('.content').marginBottom());
});
EDIT: My JS solution assumed border-box and no border. This solution should be more robust:
function setContentSize() {
$('.content').css('min-height',
$(window).height()
- $('.header').outerHeight()
- $('.footer').outerHeight()
- ($('.content').outerHeight()
- $('.content').innerHeight()));
}
$(setContentSize);
$(window).on('resize', setContentSize);
Related
I have a content div with a ragged border (using a border-image) and I place another div each below the content div left and right to hold an image. This image is supposed to have a link. While the image shows nicely through the border the link area gets hidden by it. Given that my ragged border is rather wide (almost 100px), this feels quite confusing. Therefore I would like to "float" the image below the border and the actual link area above so that the link is clickable as well were the image is under the border or visible through the border.
Despite not having the background-image uploaded the effect becomes visible since the border is wide black. The structure includes a minimal header, which is not vital to the problem but is part of the root structure.
Another problem is that the link area expands to more than the wrapped image in height, however this is a minor issue.
http://jsfiddle.net/hc3jrkku/
Basestructure:
<header>
<nav>
<a href='?p=faq#faq' id='faq'>
FAQ
</a>
</nav>
</header>
<div class='leftSide'>
<a href="#anchor" class="bgImage"><img src="img/some.png" style="
position: relative;
z-index: -1;
opacity: .99;
border: 1px solid red;
width: 150px;
height: 200px;
background-color: red,
"></a>
</div>
<div class='rightSide'>{$right}</div>
<main>
<div class='container'>
{$content}
</div>
</main>
</body>
CSS:
* {
box-sizing: border-box
}
body {
margin: 0;
}
.leftSide{
position: fixed;
z-index: 0;
top: 20px;
right: 50%;
transform: translateX(-50%);
width: 808px;
height: 100%;
display: flex;
justify-content: flex-end;
margin-right:-93px;
padding: 15px 93px 90px 0;
}
.rightSide{
position: fixed;
z-index: 0;
top: 20px;
left: 50%;
transform: translateX(50%);
width: 808px;
height: 100%;
margin-left:-93px;
padding: 15px 0 90px 93px;
}
a.bgImage {
z-index:900;
opacity:.99;
border:2px dashed blue
}
.rightSide .bgImage {
margin-left: -93px;
}
.leftSide .bgImage {
margin-right: -93px;
}
main {
width: 808px;
min-height: 400px;
margin: 20px auto 0;
position: relative;
z-index: 50;
border-style: solid;
border-width: 0px 93px 127px 93px;
border-image: url(img/paperedge.png) 0 93 127 93 fill round;
padding-top:10px;
}
header {
height: 20px;
background: #ffffff url(img/header_bg.png) repeat-x bottom;
border-bottom: 1px solid #000000;
position: fixed;
width: 100%;
top: 0;
z-index: 100
}
nav {
display: flex;
justify-content: center;
}
Having read http://philipwalton.com/articles/what-no-one-told-you-about-z-index/, I tried creating new context(s) as well, and stripping the divs containing left/right background image of the z-index, However my current code depends on the transform/position thus creating a new context for the parent element either way. Is the sandwich stacking (some children above other parts of the page/others below) possible anyways?
If you want the image to be behind the border (or your content div), you can add this to the CSS of your div in the front:
main {
pointer-events: none;
}
This will kill the events on your div and make the behind events visible in the front: DEMO
You can also search more and find these similar topics:
HTML "overlay" which allows clicks to fall through to elements behind it
HTML/CSS: Make a div "invisible" to clicks?
I'm trying to display 2 divs side by side in css.
The first div has a variable width (in fonction of the image it contains).
The second one has to take all the remaining width.
The second div contains 3 sections: "top", "middle" and "bottom" whose added height is 100%.
Both divs have a 100% height.
I successfully placed the divs side by side thanks to this question and everything works great when the body has fixed dimensions.
But since I will embed this page in an iframe, I want the divs to occupy all the available space. I would like to avoid setting the body dimensions with javascript...
I decided to add this code to the body:
body {
margin: 0;
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
}
This does the trick on Chrome and Safari: the image has a 100% height which defines its width and the second div stretches until it occupies all the available space. (The caption is displayed over the image)
But when I use Firefox, the first pane is larger than expected (see the red rectangle).
I created a fiddle with the code: http://jsfiddle.net/0w0s6z5n/1/
I can't understand why the behavior is different and what I did wrong on this page. Can someone explain to me why the behavior is different and point me in the right direction to succeed in displaying everything like it currently is on Chrome/Safari.
Thanks in advance for your help.
add
width: 100%;
height: 100%;
to body (yeah, its that simple)!! :)
Problem : container always takes dimension of parent elements, so you have to declare them if you intend to use them in %
css :
body {
margin: 0;
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
background-color: orange;
width: 100%; /* added */
height: 100%; /* added */
}
Fiddle here
I am not sure this is exactly what you wanted, but from what i understood you need to have the first div with a variable width and the rest should fall in place.
I edited your code: Fiddle here
CSS :
body {
margin: 0;
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
background-color: orange;
}
.container {
width: 100%;
height: 100%;
background-color: pink;
}
.first {
position: relative;
float: left;
height: 100%;
background-color: red;
}
.second {
height: 100%;
background-color: yellow;
}
.media {
height: 100%;
}
.caption {
position: absolute;
width: 100%;
height: 15%;
right: 0;
bottom: 0;
left: 0;
background-color: grey;
}
.top {
height: 40%;
background-color: blue;
}
.middle {
height: 30%;
background-color: purple;
}
.bottom {
height: 30%;
background-color: green;
}
With this if you change the width of .media , the rest of them fall in place and also works with firefox (Tested).
Examining this HTML:
<div class="wrapper">
<div class="content">
</div>
</div>
<div class="footer">
<hr />
<p>some text</p>
</div>
and CSS:
.footer {
position: absolute;
height: 100px;
width: 100%;
bottom: 0;
background-color: black;
}
.wrapper {
padding-bottom: 100px;
background-color: blue;
height: 100%;
}
.content {
width: 200px;
height: 100px;
margin: auto;
background-color: green;
}
html, body {
width: 100%;
height: 100%;
}
You can see that footer have position absolute and stay at the bottom of the page. wrapper will cover the remaining space and contain a content inside it. I want to vertical-align content without breaking the current layout. Do you have any suggestion?
Here is JSFiddle link. (Note: jsfiddle doesn't work as expected, there always a space beneath footer, this behavior doesn't occur when run the HTML file in browser).
Note: I don't want to use fixed height for wrapper, I want it covers all the remaining space, so please don't suggest me to use line-height
I tried the example here but it doesn't seem to work
NOTE I want the layout easy to modify (like add a header or content at the top) without breaking it therefore I want to avoid using absolute position on wrapper and content
NOTE 2 Sorry for not to clarify, actually, content doesn't have fixed size, its size depend on the content inside it, so the solution using negative margin doesn't work as I mentioned above
Here is one approach using the following CSS:
.footer {
position: absolute;
height: 100px;
width: 100%;
bottom: 0;
background-color: black;
}
.wrapper {
background-color: blue;
position: absolute;
top: 0;
bottom: 100px;
left: 0;
right: 0;
}
.content {
width: 200px;
height: 100px;
background-color: green;
position: absolute;
top: 50%;
left: 50%;
margin-top: -50px;
margin-left: -100px;
}
html, body {
width: 100%;
height: 100%;
margin: 0;
}
Use absolute positioning and then negative margins, since your content has well-defined
dimensions, this is relatively straightforward.
See demo at: http://jsfiddle.net/audetwebdesign/DgUV2/
For .wrapper, use the top, bottom, left and right offsets to stretch the div to the
full width and height, taking into account the 100px for the footer.
For .content, set top and left to 50%, the center point of the .wrapper and then adjust
for the center of the .content div using negative margins.
Remember to zero out the margin for the body or else you might see 10px whitespace
depending on your browser.
Add this to your .content
position: relative;
top: 50%;
transform: translateY(-50%);
Just 3 lines of code to vertical align
I was able to get it to work using Method 1 from the example you linked
I added the following:
.content {
width: 200px;
height: 100px;
margin: auto;
background-color: green;
/* THE BELOW WAS ADDED */
position: absolute;
top: 50%;
left: 50%;
margin: -100px 0 0 -100px;
}
html, body {
width: 100%;
height: 100%;
/* BELOW ADDED TO REMOVE EXTRA SPACE AROUND EDGES */
margin: 0;
}
jsFiddle of working example
SO,
I've created a four-column fluid-width layout for a site, and I'm working on placing a fluid square DIV within one of my columns. There are a few techniques I've found to achieve this - namely, setting padding-bottom to the same percentage as the width - but none of these seem to work when the DIV contains content.
Is there a way to maintain a 1:1 (square) ratio on a fluid DIV when that DIV contains content?
Here's my HTML:
<div id="leftmostcolumn">
<div id="logo"></div>
</div>
<div id="leftcolumn"></div>
<div id="rightcolumn"></div>
<div id="rightmostcolumn"></div>
And my CSS:
body {
width: 100%;
height: 100%;
background-color: red;
}
#leftmostcolumn {
position: absolute;
top: 0;
left: 0;
width: 25%;
height: 100%;
background-color: blue;
}
#leftcolumn {
position: absolute;
top: 0;
left: 25%;
width: 25%;
height: 100%;
background-color: green;
}
#rightcolumn {
position: absolute;
top: 0;
left: 50%;
width: 25%;
height: 100%;
background-color: yellow;
}
#rightmostcolumn {
position: absolute;
top: 0;
left: 75%;
width: 25%;
height: 100%;
background-color: gray;
}
#logo {
width:100%;
padding-bottom:100%;
background-color: #aa2d2d;
color: white;
}
And here's a JsFiddle.
The DIV "logo" is the one I'm trying to maintain as a square. Right now, I've used the padding-bottom approach but that doesn't do the trick when there's content in the DIV. Any input is greatly appreciated!
Marca
EDIT:
Getting there...I'm adapting a script I found to find the width of the DIV and then apply that value to the height to keep it a square. However, as it stands now the script doesn't constantly resize the DIV, and it won't allow it to shrink below a certain size. Any thoughts on how to correct either of these issues?
HTML:
<div id="box"></div>
CSS:
#box { width: 75%; height: 50px; background-color: black; }
JQUERY:
$("#box").css("height", function() {
return $(this).width();
});
JsFiddle is here.
This is something I've actually been messing around with for a while, and have come up with a quasi (but not entirely) hacky, CSS-only solution that seems to work on most browsers in the past decade. The trick is to use images, and positioning in a tricky fashion. Consider the following (simplification) of your code.
Markup:
<div class="sqr_box">
your content goes here!
</div>
CSS:
.sqr_box
{
width: 50%; /* or 100px, or 20em, or whatever you want */
border: solid 2px pink;
background-color: grey;
color: white;
}
Now, we can't set the height in terms of percent, so we won't; instead, first we'll go into Photoshop, and make an image that is 2x2 px, transparent, or background-colored. Next we'll add the following to your markup:
<div class="sqr_box">
<img src="images/sizers/2x2.png" class="sizer">
<div class="content">your content goes here!</div>
</div>
and THIS to your CSS:
.sqr_box
{
width: 50%; /* or 100px, or 20em, or whatever you want */
position: relative; /* static positioning is less than ideal for this scenario */
}
.sqr_box > img.sizer
{
display: block; /* images default to an inline-block like thing */
width: 100%;
height: auto; /* CLUTCH!!! this ensures that the image's height changes to maintain proportions with it's width */
visibility: hidden;
}
.sqr_box > .content
{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%; /* Our parent element now has a dynamically assigned height, this will work */
border: solid 2px pink;
background-color: grey;
color: white;
}
Best of all, this will work for any sized ratio of box you'd want! Just change the proportions of the image!
Hope this is all still relevant to you, 3 months later.
-Sandy
Put all four columns in one div. set that div to 100% width and set the font size to 100em
Have each of your four columns have a width of 25em instead of 25%
Have your logo width and height set to 25em each
I have a div which needs to fill out the height of the browser's viewport,but still says in the same position when the user scrolls the web page up and down. position: fixed; does this, but I am unable to use it as it's making the overflow scroll bar of the div jerky and slow. Is there an position or method that I can use so for example I currently have:
div.panel {
position: absolute;
top: 36px;
right: 0;
overflow: auto;
background: #636362;
padding: 0 0 20px 0px;
width: 290px;
height: 100%;
}
I'm not sure what you mean with "jerky and slow", because all scrollbars act the same. This is how I would resolve your issue:
HTML:
<div class="fixed">I'm fixed!</div>
<p>Rest of page</p>
CSS:
html, body {
/* make sure the page is at least height of viewport */
height: 100%;
}
body {
/* because the fixed div is no part of the flow,
make sure it is not overlapping the webpage */
padding: 0 0 0 100px;
}
.fixed {
height: 100%;
width: 100px;
left: 0;
position: fixed;
background: #e0e0e0;
/* only vertical-scrolling, but can be changed of course */
overflow-y: scroll;
}
JSfiddled Live example
Works in at least IE7, IE8 and Firefox.