I'm trying to achieve a particular layout for a website I'm working on, but I'm not sure how to about it. The layout will look like this:
The header has nothing special about it. The footer has position: fixed and bottom: 0px. The main body content needs to be centred vertically within the space from the bottom of the header down to the top of the footer. If the window height is adjusted, the body content should remain centred between these two points. Also note that the website will be responsive, but only from 960px up to about 1600px (so the minimum width it will ever be is 960px).
My only idea on how to achieve this is to have the div containing the body content somehow automatically expand to always be the full height from the bottom of the header down to the bottom of the browser window (and then add some padding at the bottom to account for the footer), then use display: table on this containing div, and use display: table-cell and vertical-align: middle on a child div.
Are there any other (preferably CSS-only) ways I could potentially do this? If not, how can I get the containing div for the body content expand to always be the full height from the bottom of the header down to the bottom of the browser window?
Here is one solution, for a header with a fixed height.
Your HTML needs to have the following pattern:
<div class="header">Header</div>
<div class="main-wrap">
<div class="container">
<div class="content">Content...</div>
</div>
</div>
<div class="footer">Footer</div>
and the CSS:
html, body {
height: 100%;
}
body {
margin: 0;
}
.header {
height: 50px;
background-color: beige;
}
.main-wrap {
position: absolute;
top: 50px;
bottom: 50px;
width: 100%;
background-color: silver;
overflow: auto;
}
.container {
display: table;
height: 100%;
width: 100%;
}
.content {
border: 1px solid blue;
display: table-cell;
height: 100%;
width: 100%;
vertical-align: middle;
}
.footer {
height: 50px;
width: 100%;
background-color: lightblue;
position: fixed;
bottom: 0;
}
See demo at: http://jsfiddle.net/audetwebdesign/aGTKs/
It is possible to adapt this to a header of flexible height.
The .main-wrap container defines the space between the header and footer.
The .container block uses display: table and inherits the height from .main-wrap.
Finally, .content uses display: table-cell, which allows you to use vertical-align: middle (default value) to center the content vertically.
You need to set the height of body and htmlto be 100% to capture the height of the view port.
You can hack it by doing {position: absolute; bottom: 0} !
Related
I have a layout with a content column and a sticky sidebar. Scrolling down the page I need to stop the sidebar at the end of the content column.
Here the HTML and CSS I'm using:
<div class="container">
<div class="content">Content</div>
<div class="sidebar">Sidebar (sticky)</div>
<div style="clear:both"></div>
</div>
.content{
float: right;
width: 80%;
margin-left: 20%;
}
.sidebar {
float: left;
width: 20%;
position: -webkit-sticky;
position: sticky;
bottom: 30px;
}
Also on https://codepen.io/anon/pen/awNorj
Where I'm wrong?
Your initial problem is that css tricks work fine for top elements but not for bottom elements. Because tricks rely on the top-left corner position. To do so with the bottom-left corner, you'd need to know the height of your sidebar.
With sticky top element, you could just:
put your sidebar div first
then your content div
finally set your sidebar float:left so the container adjusts its height to the content
Demo: https://jsfiddle.net/1owyqtcn/1/
With sticky bottom element, the float:left trick does not work: it will get your sidebar overflow the container at the bottom.
Demo: https://jsfiddle.net/d1byrhp6/4/
If you don't know the height of your sidebar.
An approach can be to use the negative margin-left trick: you put the sidebar div into the content div and display it outside. Both sidebar and content are now aligned. But the sidebar leaves blank space in the content.
.content{
background: purple;
width: 80%;
margin-left: 20%;
}
.sidebar {
position: sticky;
width: 25%; /* Adjust: 25% of 80% of container is 20% of container */
background: #ff6347;
bottom: 30px;
margin-left: -25%;
}
Demo: https://jsfiddle.net/zg9g3134/
If you know the height of your sidebar.
Another approach is to suppress the height with a negative margin-top trick, instead of a float: left.
.content{
background: purple;
width: 80%;
margin-left: 20%;
}
.sidebar {
height: 200px;
overflow-y: hidden;
margin-top: -200px;
position: sticky;
width: 20%;
background: #ff6347;
bottom: 30px;
}
Demo: https://jsfiddle.net/rLs8dLba/2/
I have a set of absolutely positioned fluid divs within a container and want to display an image within each div that is vertically and horizontally centred within the container and fills up as much of the available space as possible. Due to using these images for other purposes they have to be img tags and not background images (otherwise with CSS3 this would be easy!)
I would have thought the following code should do just this but for some reason on Firefox the image displays in it's original dimensions and is not constrained by the parent dimensions. In Chrome the width seems to be correctly linked to the container however the img height is not constrained by the container height.
I could understand it if there was no width/height set on the parent but every element in this example has a percentage width/height set so i don't think this is the problem. FYI if you set a specific width:100% on the img then this constrains the width correctly (but can't be done as it means it's loses the correct aspect) however it still doesn't work for height even if you set the height to 100%,
You can see a jsfiddle at http://jsfiddle.net/deshg/xrzk084d/ and the code is below.
If anyone could point me in the right direction as to what i'm doing wrong that would be greatly appreciated!
body, html, #outer {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#container {
background-color: #ffcc00;
display: table;
position: absolute;
left: 20%;
top: 30%;
width: 60%;
height: 40%;
}
#containerinner {
display: table-cell;
width: 100%;
height: 100%;
vertical-align: middle;
}
#containerinner img {
max-width: 100%;
max-height: 100%;
margin: 0 auto;
display: block;
}
<div id="outer">
<div id="container">
<div id="containerinner">
<img src="https://dl.dropboxusercontent.com/s/wypn5e7n5bgeoic/landscape.png?dl=0" alt="">
</div>
</div>
</div>
Cheers,
Dave
The issue here is that set a vertical alignment of middle is impossible without specifying the height of the containing element. In your situation, you want the height to be relative to the viewport which creates additional difficulty.
However, if we use both the vh (viewport height) and vw (viewport width) units defined in CSS3 we can achieve what you're after. I have then assumed that you want your image to be center aligned and with a max width and height of 60% and 40% of the viewport respective. I have reduced the markup to the following (See JSFiddle):
#container {
position: fixed;
top: 30vh;
left: 20vw;
background-color: #ffcc00;
}
#inner {
display: table-cell;
vertical-align: middle;
text-align: center;
height: 40vh;
width: 60vw;
}
img {
display: block;
max-width: 60vw;
max-height: 40vh;
margin: 0 auto;
}
<div id="container">
<div id="inner">
<img src="https://dl.dropboxusercontent.com/s/wypn5e7n5bgeoic/landscape.png?dl=0">
</div>
</div>
I have four DIVs :
The first div has a fixed height and located on top (header).
The second div also has a fixed height and located below the first div.
The fourth div has a fixed height located on bottom.
The third div will have a variable height: it will expand to make the total of four divs are full to vertical space in browser IF the content is less than that. But it will follow the content's height if the content's height is larger than that. So at all times, I want the first div (the header) to stick at the top of the page, and the fourth div (the footer) to stick at the bottom of the page. I have no way to know how tall the content will be.
header
header
header
header
the CSS file:
#container { width:800px; height:*; }
#header { height:200px; }
#menu { height:50px; }
#content { height:*; }
#footer { height:150px; }
can I actually do this? how is the correct css way to do this? I get the feeling this should be not too hard, but I can't find relatable answers anywhere. Thank you.
What you could do is something like this:
#content { height: 100vh; /*100% of viewport height*/
margin-top: 250px;
margin-bottom: 150px; }
This way it will always be 100% of the screen height in total.
Well that turned out looking cool, JSBin
HTML
<div class="header">Header !</div>
<div class="menu">Menu !</div>
<div class="content">Content !</div>
<div class="footer">Footer !</div>
CSS
body { margin: 0; }
.header { width: 100%; height: 200px; position: fixed; top: 0; }
.menu { width: 100%; height: 50px; position: fixed; top: 200px; }
.footer { width: 100%; height: 150px; position: fixed; bottom: 0; }
.content { width: 100%; position: fixed; top: 250px; bottom: 150px;
overflow: auto; }
I am trying to create a page which will be have header and footer div with unknown height (or min-height) and middle content with scroll if the content increases and all these three should fit in screen only.
I tried below and works if the height of header and footer is fixed and if only middle content increases then i get scroll for content div perfectly. How do to handle unknown height part for header and footer to make it fit? I gave min-height but doesn't work.
#Pageheader {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 100px;
background-color: Blue;
}
#Pagefooter {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 100px;
background-color:red;
}
#Pagecontent {
position: fixed;
top: 100px;
bottom: 100px;
left: 0;
right: 0;
background-color: #EEEEEE;
overflow: auto;
}
and Html side
<body>
<form id="form1" runat="server">
<div id="Pageheader">
</div>
<div id="Pagecontent">
</div>
<div id="Pagefooter">
</div>
</form>
The ol' school dirty way is to use Jquery. Detect height of header/footer, place and resize the content div according to window height and the previous heights.
A sophisticated solution is to use Flexbox. Using the align-content: stretch you can create the layout you want. You can check it here.
I got stuck trying the same thing last week. I ended up doing it with css tables (compatible with all browsers including IE8). Here's the CSS for it:
/* Layout-1 | Header Footer */
html {
min-height: 100%;
}
html, body {
height: 100%;
width: 100%;
}
body {
display: table;
}
header, footer {
display: table-row;
padding: 30px;
}
div#container {
display: table-row;
height: 100%;
}
If you wanted a fixed header and footer and for the scrolling to only effect the body section in between, the markup and css would be totally different, and utilize position: absolute;
Let me know if this works for you : )
I am trying to build a layout that consumes all the space that is visible in browser. I set html, body height 100% as was suggested in different SO posts. Following is the markup that I am trying
<div>
<div class="header">
</div>
<div class="main">
<div class="container">
<div class="content"></div>
</div>
</div>
</div>
CSS:
html, body {
height: 100%;
max-height: 100%;
}
.header {
height: 30px;
background-color: #000;
}
.main {
height: auto;
padding-right: 0px;
max-height: 100%;
width: 100%;
display: block;
clear: both;
background-color: #eee;
}
.container {
width: 90%;
overflow-y: scroll;
background-color: #ccc;
}
.content {
height: 2000px;
width: 80%;
background-color: #fff;
}
the content div height cause the whole body to grow and hence the browser's default scroll bars are shown. Though I have set the container div to scroll in order to display the content of content div, still the scroll bars for container div don't show. How can I fix this.
here is the jsfiddle
Edited:
By default the height of the div element depends on its content (unlike width which takes 100% width of the parent). That's why when you specify the height of inner element as a percentage it won't be accurate if your parent tag has no explicitly defined height (that means height has to be defined up to the very top of the DOM since height is not inheritable).
In your case you need to add height: 100%; or any other height to your .container , .main and the wrapper div
modified fiddle