I have the following layout to build:
Basically, I need three divs of varying height with varying header heights to be positioned 100% from the top of their parent, minus the height of the header. I could do this with jQuery, but this is a responsive site, so I'd like to keep it as CSS-based as possible (otherwise I'll have to deal with $(window).resize(), which in my experience can be unreliable).
Is this possible, maybe using the CSS3 calc feature?
Thanks.
So you can try add content (orange container) stick to the bottom off the blue container (depends of your html structure you can use position: absolute , or margin-top in orange container).
Than you can put header (green) container inside orange container and put it position absolute top -100% (orange position has to be absolute or relatve).
If you will add your html than it will be easy to find more precise solution.
JSFIDDLE with an example
CSS:
.box{
background: #f00;
height: 150px;
width: 100%;
position: relative;
padding: 20px;
padding-bottom: 0;
}
.column{
background: #0f0;
width: 30%;
position: relative;
top: 100%
}
.header{
position: absolute;
bottom: 100%;
width: 100%;
background: #00f;
}
HTML:
<div class="box">
<div class="column">
<div class="header">
header
</div>
aaaaaaa<br/>
aaaaaa
</div>
</div>
I have this solution (works for any number of columns as long as they fit):
Use inline blocks to center align the results
Use relative positioning to align the blocks with the bottom of blue box (requires top vertical align)
Move the green blocks out of the flow by making them absolute position (this leaves orange box in the flow which aligns with the bottom of blue box)
body {
font: medium monospace;
}
.blue {
background: #AAF;
height: 12em;
text-align: center;
}
.helper {
display: inline-block;
width: 10em;
vertical-align: top;
position: relative;
top: 100%;
}
.green {
background: #CFC;
position: absolute;
bottom: 100%;
left: 0;
right: 0;
}
.orange {
background: #FCA;
}
<div class="blue">
<div class="helper">
<div class="green">
1<br/>2
</div>
<div class="orange">
1<br/>2<br/>3
</div>
</div>
<div class="helper">
<div class="green">
1<br/>2<br/>3
</div>
<div class="orange">
1<br/>2<br/>3<br/>4<br/>5
</div>
</div>
<div class="helper">
<div class="green">
1
</div>
<div class="orange">
1<br/>2<br/>3<br/>4
</div>
</div>
</div>
Try the following CSS rule: height: calc(100% - header_height);
Related
I'm trying to understand what css "sticky" does.
I can get it to stick to the 'top' of its parent,
but not to the 'bottom'
My test code is:
.block {
background: pink;
width: 50%;
height: 200px;
}
.move {
position: sticky;
bottom: 0;
}
1111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>
<div class="block">
AAAA
<div class="move">
BBBB
</div>
</div>
222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>
When I have "move" set to 'top:0' it sticks to the top of the pink block, but when set to 'bottom:0' it seems no longer fixed/sticky.
It's working fine but you will see nothing. Let's have a look at the definition:
A stickily positioned element is an element whose computed position value is sticky. It's treated as relatively positioned until its containing block crosses a specified threshold (such as setting top to value other than auto) within its flow root (or the container it scrolls within), at which point it is treated as "stuck" until meeting the opposite edge of its containing blockref
Give a big margin to the block element to hide it from the screen then start scrolling slowly
.block {
background: pink;
width: 50%;
height: 200px;
margin-top:120vh;
}
.move {
position: sticky;
bottom: 0;
}
<div class="block">
AAAA
<div class="move">
BBBB
</div>
</div>
You will notice that when your element is showing the BBB is overlapping the AAA until it reach its initial place. This is the sticky behavior when using bottom:0. So our element is kept position:relative and when the container start going out from the screen on the top, it become sticky to its bottom until it reach the opposite edge (the top of the container).
Exactly the same happen with top:0 but in the opposite direction:
.block {
background: pink;
width: 50%;
height: 200px;
margin-bottom:120vh;
}
.move {
position: sticky;
top: 0;
}
<div class="block">
AAAA
<div class="move">
BBBB
</div>
</div>
So sticky will not position the element to the top or the bottom but it will decide how the element shoul stick in order to be visible when the container will start moving out of the screen.
In order to obtain what you want you need to put your element in the bottom using other properties and keep it bottom sticky.
Here is an example where I place the element at the bottom using flexbox and I specify that I need it to be sticky at the bottom.
.block {
background: pink;
width: 50%;
height: 200px;
margin-top:120vh;
display:flex;
flex-direction:column;
}
.move {
margin-top:auto;
position: sticky;
bottom: 0;
}
<div class="block">
AAAA
<div class="move">
BBBB
</div>
</div>
So position:sticky will never define the position of the element like we do with absolute or fixed but it will define how the element will stick when there is a scrolling behavior.
Here more examples to better understand:
.block {
background: pink;
display:inline-flex;
vertical-align:top;
height: 200px;
max-width:100px;
flex-direction:column;
margin:100vh 0;
}
.e1 {
position: sticky;
top: 0;
}
.e2 {
margin-top:auto;
position: sticky;
top: 0;
}
.e3 {
position: sticky;
top: 20px;
}
.e4 {
position: sticky;
bottom: 0;
margin:auto;
}
.e5 {
position: sticky;
bottom: 0;
top:0;
margin:auto;
}
.e5 {
position: sticky;
bottom: 0;
}
<div class="block">
<div class="e1">Top sticky</div>
</div>
<div class="block">
<div class="e2">Top sticky at bottom (nothing will happen :( )</div>
</div>
<div class="block">
<div class="e3">Top sticky at 10px</div>
</div>
<div class="block">
<div class="e4">bottom sticky in the middle</div>
</div>
<div class="block">
<div class="e5">top/bottom sticky in the middle</div>
</div>
<div class="block">
<div class="e6">bottom sticky at the top (nothing will happen :( )</div>
</div>
Another common mistake with sticky is to forget about the height/width of the element relatively to the one of its parent. If the height of element is equal to the height of the parent (containing block) then logically there will be no sticky behavior because we are already at the opposite edge.
.block {
background: pink;
display:inline-flex;
vertical-align:top;
height: 200px;
max-width:100px;
flex-direction:column;
margin:100vh 0;
}
.block > div {
border:2px solid;
}
.e1 {
position: sticky;
top: 0;
}
<div class="block">
<div class="e1">Top sticky</div>
</div>
<div class="block">
<div class="e1" style="height:100%">I will not stick</div>
</div>
<div class="block">
<div class="e1" style="height:80%">I will stick a little ..</div>
</div>
<div class="block" style="height:auto">
<div class="e1">I will not stick too</div>
</div>
Notice the last case where the height of the parent is set to auto (default value) thus its height will be defined by its content which make the sticky element to have the same height as the containing block and nothing will happen because there is no room for a sticky behavior.
Try the following code:
.block {
background: pink;
width: 50%;
}
.movetop {
position: sticky;
top: 0;
background: #ccc;
padding: 10px;
color: #ae81fe;
z-index: 1;
border: 1px solid #777;
}
.movebot {
background: #ccc;
padding: 10px;
color: #ae81fe;
position: -webkit-sticky;
position: sticky;
border: 1px solid #777;
}
.movebot {
bottom: 0
}
11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>11111<br/>
<div class="block">
<div class="movetop">
header
</div>
content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>content<br>
<div class="movebot">
footer
</div>
</div>
222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>222222<br/>
You can find more about position:sticky on gedd.ski/post/position-sticky
I have a site that has a top navigation bar, a header, a sidebar and a content body next to the sidebar. The header, sidebar, and content body are positioned absolutely so that they don't move when you navigate to other pages that are using the same template. The sidebar and content body have scroll bars. The header and sidebar are always visible even with scrolling. This works great as shown in the demo. But suppose the top navigation changes height. Then the vertical alignment is off. Since this site is using a global top navigation that's used in other sites as well, the top navigation can change at any moment. When it does change, this layout will not be future proof. Is there a way to make this future proof?
What I have currently:
http://codepen.io/codingninja/pen/nKwox
body {
margin: 0;
padding: 0;
}
.content {
/*position: relative;*/
}
.top-nav {
background: #000;
height: 42px;
color: #fff;
}
.header{
position: absolute;
height: 100px;
width: 100%;
background: #ddd;
}
.sidebar {
position: absolute;
top: 142px;
left: 0;
bottom: 0;
background: #aaa;
overflow-y: auto;
overflow-x: hidden;
width: 100px;
}
.body {
position: absolute;
top: 142px;
right: 0;
left: 150px;
bottom: 0;
overflow-y: auto;
overflow-x: hidden;
}
What happens when the top nav changes height:
http://codepen.io/codingninja/pen/nICzK
.top-nav {
background: #000;
height: 100px;
color: #fff;
}
Do you mean this:
Css3 has a Calc() Function
Height: Calc( 100% - 100px )
Instead of absolutely positioning everything you can make use of display:table to achieve the layout you want. Using the following html
<div class="table">
<div id="top-nav" class="row">
<div class="cell">top-nav</div>
</div>
<div id="header" class="row">
<div class="cell">header</div>
</div>
<div id="content" class="row">
<div class="cell">
<div class="table">
<div id="side-bar" class="cell">
<div class="overflow">
sidebar
</div>
</div>
<div id="body-content" class="cell">
<div class="overflow">body-content</div>
</div>
</div>
</div>
</div>
</div>
And Css
html,
body,
.table {height:100%; padding:0; margin:0;}
.table {display:table; width:100%;}
.table .row {display:table-row;}
.table .cell {display:table-cell;}
#top-nav {height:42px;}
#header {height:100px;}
#content {height:100%;}
#side-bar {width:100px;}
.overflow {height:100%; overflow:auto;}
Example
You will notice that when your top nav grows, your main content area will shrink. You will also not get into a positioning / z-index nightmare
I found a solution that involves a line of javascript to set top to the calculated height based on the height of the top nav and the header.
$(".sidebar, .body").css('top', topnavheight+100);
I'm trying to make a floating div have a height that fills in the parent div.
http://jsfiddle.net/sergep/2qPZ2/1/
The structure is as follows:
Parent div______________________
| Middle child
| Left child - float:left
| Right child - float:right
The problem is that the left child has less text than the right, meaning the right increases the height of the parent div (to fit the div), but the left floating div does not follow suit.
The css looks like so:
.bottomcontainer {
bottom: 0;
position: absolute;
width: 100%;
height: auto;
}
.bottomleft {
background: #346CA5;
float:left;
width: 50%;
}
.middle {
background: #FFCE3C;
}
.bottomright {
background: #65B237;
float:right;
width: 50%;
}
How can I make the blue .bottomleft class stick to the bottom of the .bottomcontainer? - I'm trying to make responsive, so I don't want to use actual pixel sizes!
Consequently, how do I make the text inside vertically align middle?
Use display:table-cell; on the child divs, see here for an example that can be extrapolated
I misunderstood the question. You can fix that by adding an extra div around .bottomleft and .bottomright and display it as table / tablecells:
HTML:
<div id="nav"></div>
<div id="container">
<div class="bottomcontainer">
<div class="middle">
<h2>Intro tag line here</h2>
</div>
<div class="bottom">
<div class="bottomleft">
<h2>Tag line here</h2>
</div>
<div class="bottomright">
<h2>Longer tag line goes here</h2>
</div>
</div>
</div>
</div>
<div name="content" id="content"></div>
CSS:
.bottom {
display: table;
}
.bottomleft {
display: table-cell;
background: #346CA5;
opacity: 1.0;
width: 50%;
vertical-align: middle;
}
.bottomright {
display: table-cell;
background: #65B237;
opacity: 1.0;
width: 50%;
}
And updated Fiddle 2
Delete the float, and add an absolute positioning:
.bottomleft {
background: #346CA5;
opacity: 1.0;
position: absolute;
bottom: 0;
width: 50%;
vertical-align: middle;
}
Also check the updated Fiddle.
I have two div elements inside one div element. These two div elements are both 50% wide and other one is floated to left and the other is floated to right. The right floated div contains one high picture (in different heights) and left floated div contains text. On the left div these texts are separated into three different sized rows and the whole left div should be as high as the right div. How am I able to do this using only CSS? Here's my example code:
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
body {
margin: 0;
}
.container {
width: 100%;
height: 100%;
overflow: auto;
background: #FF0;
}
.left {
float: left;
width: 50%;
background: #F0F;
}
.left .first {
height: 20%;
}
.left .second {
height: 50%;
}
.left .third {
height: 30%;
}
.right {
float: right;
width: 50%;
}
.right img {
display: block;
max-width: 100%;
}
p {
margin: 0;
}
</style>
</head>
<body>
<div class="container">
<div class="left">
<div class="first">
<p>First</p>
</div>
<div class="second">
<p>Second</p>
</div>
<div class="third">
<p>Third</p>
</div>
</div>
<div class="right">
<img src="http://upload.wikimedia.org/wikipedia/commons/3/3a/Centara_Grand_Hotel.jpg" alt="" />
</div>
</div>
</body>
</html>
The short answer is that you can kind of do this, but I don't think it will behave the way you expect.
You would have to declare explicit heights for the two <div>'s -
.left, .right {
height: 100px /*or whatever height you want*/;
}
If this is a static page, and the image never changes, you can manually enter the pixel amount.
If the picture is going to change, and you don't know what the height is going to be, you cannot get the left div to match the height of the right div using plain CSS.
There are ways to fake it (see the faux columns technique), but you cannot programmatically get one div to change it's height to match another one.
There are ways to do this with JavaScript, but I'm not going to get into them because you asked about CSS (and I hate using JS to manipulate layout like that - it's very unreliable).
Also: if your containing div, .container, collapses, it's because you need to either float it, or apply a clearfix technique.
There are a few things you need to do:
You need to float the containers.
You need to add an extra container and nest the divs in the following order:
<div class="container2">
<div class="container">
<div class="left">
<div class="first">
<p>First</p>
</div>
<div class="second">
<p>Second</p>
</div>
<div class="third">
<p>Third</p>
</div>
</div>
<div class="right">
<img src="http://upload.wikimedia.org/wikipedia/commons/3/3a/Centara_Grand_Hotel.jpg" alt="" />
</div>
</div>
</div>
Then you need to relative position your containers and move them to the right. After that, you'll move your content divs from the left.
For your CSS:
.container {
width: 100%;
float: left;
position: relative;
right: 50%;
}
.container2 {
width: 100%;
float: left;
overflow:hidden;
position:relative;
}
.left {
float: left;
width: 50%;
left: 50%;
position: relative;
background: #F0F;
}
.right {
float: left;
width: 50%;
left: 50%;
position: relative;
}
Please see this page if you're having difficulties.
I new to webdesign and I wonder how I could do something like this:
..........................
LEFT --- CENTER ---- RIGHT
..........................
Its one parent div in the center of the window, with 3 divs inside like columns. I want them to be dynamic, so they always scale to the browser window.
This is how it looks now.
My current HTML:
<div id="container_m">
<div id="left">
<p>My name is Barnabas</p>
</div>
<div id="right">
<p>Till salu</p>
</div>
<div id="center">
<p>Senaste nytt</p>
</div>
</div>
My currrent CSS:
#container_m
{
position:absolute;
height: 40%;
width: 60%;
left: 20%;
top: 45%;
background-color:rgba(0,0,0,0.2);
}
#left
{
position: relative;
height: 100%;
width: 33%;
float: left;
background-color: blue;
}
#right
{
position: relative;
height: 100%;
width: 33%;
float: right;
background-color: green;
}
#center
{
position: relative;
height: 100%;
width: 33%;
margin:0 auto;
background-color: yellow;
}
Floating divs can sometimes ruin the auto-resize of the parent div. What I do to ensure proper auto-resize of the parent div is to add this to parent div, just behind the last floating child:
<div style="clear: both;"></div>
This may be a dirty fix or whatever but it ensures the parent div always resizes along with its children.
whats wrong with that? I'm resizing my browser and they seem to be getting bigger and smaller. if you are talking about the fact they're not all inline then you need to do this:
<div id="parent">
<div id="left">
Left Content
</div>
<div id="center">
Center Content
</div>
<div id="right">
Right Content
</div>
</div>
And then float them all left. :)
You can simplify that hugely: http://www.jsfiddle.net/fsnuh/
HTML:
ids not needed on each child, as on your website, they are styled identically. classes attached below purely for the colored backgrounds
<div id="container_m">
<div class="red">
<p>My name is Barnabas</p>
</div>
<div class="yellow">
<p>Till salu</p>
</div>
<div class="green">
<p>Senaste nytt</p>
</div>
</div>
CSS
Styles for left, right and center combined into one. Overuse of position: relative removed.
#container_m
{
position: absolute;
height: 40%;
width: 60%;
left: 20%;
top: 45%;
background-color:rgba(0,0,0,0.2);
}
#container_m div
{
height: 100%;
width: 33.33%;
float: left;
}
.red
{
background-color: red;
}
.green
{
background-color: green;
}
.yellow
{
background-color: yellow;
}