221

I have a navigation bar on the left hand side of my page, and I want it to stretch to 100% of the page height. Not just the height of the viewport, but including the areas hidden until you scroll. I don't want to use javascript to accomplish this.

Can it be done in HTML/CSS?

Tom
  • 4,341
  • 9
  • 27
  • 21

15 Answers15

191

Here is the solution I finally came up with when using a div as a container for a dynamic background.

  • Remove the z-index for non-background uses.
  • Remove left or right for a full height column.
  • Remove top or bottom for a full width row.

EDIT 1: CSS below has been edited because it did not show correctly in FF and Chrome. moved position:relative to be on the HTML and set the body to height:100% instead of min-height:100%.

EDIT 2: Added extra comments to CSS. Added some more instructions above.

The CSS:

html{
    min-height:100%;/* make sure it is at least as tall as the viewport */
    position:relative;
}
body{
    height:100%; /* force the BODY element to match the height of the HTML element */
}
#cloud-container{
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
    overflow:hidden;
    z-index:-1; /* Remove this line if it's not going to be a background! */
}

The html:

<!doctype html>
<html>
<body>
    <div id="cloud-container"></div>
</body>
</html>

Why?

html{min-height:100%;position:relative;}

Without this the cloud-container DIV is removed from the HTML's layout context. position: relative ensures that the DIV remains inside the HTML box when it is drawn so that bottom:0 refers to the bottom of the HTML box. You can also use height:100% on the cloud-container as it now refers to the height of the HTML tag and not the viewport.

Knyri
  • 2,968
  • 1
  • 17
  • 24
  • this is great, but wont center. any fix for that? margin:0 auto; isn't working. – cream Oct 26 '12 at 07:48
  • Awesome answer. I noticed that you have to use min-height (and not just height) on the `html` element though. Why is that? – HartleySan Sep 27 '13 at 20:29
  • Using `height` is saying 'you are this tall; no more and no less.' Which means it will be the height of the viewport. We want it to be at least as tall as the viewport or taller. `min-height` does this nicely. – Knyri Sep 28 '13 at 19:55
  • Why did you include `z-index: -1`? – Joe Mornin Jan 10 '14 at 20:57
  • 1
    The z-index is there because this is a snippet for a moving background I did and I wanted to make sure the div stayed in the background. It's not needed for normal elements. – Knyri Jan 20 '14 at 22:10
  • Interesting and helpful, thanks. Shame there you can't just do something similar to get the width to work in the same way. – BJury Mar 19 '14 at 12:19
  • This answer was given two years ago, and I'm sure there is a new way to do this; however, I have tried different options and this still seems like the best. On another note, I had to remove the z-index for my links in the div to be clickable. – tehlivi Mar 21 '14 at 15:50
  • Same here, I had to set z-index: 0 because my links were not clickable and the :hover in css didnt work for any element. It just worked in Chrome but not in Firefox or IE. For the "full screen" div it worked perfect. – Carlos Calla Jul 03 '14 at 17:05
  • 5
    This is excellent. I've been doing CSS for 15 years and it never clicked that positioning to the `` and positioning to the viewport were two separate things. Thank you! – Ben Hull Aug 06 '15 at 05:49
  • The line html{... position:relative} did the trick for me. Just a little remark (not important for the topic itself): could you please add the semicolons on html{... position:relative } and body{ height:100% ...} ? Just to prevent copy/paste error. – flumingo Sep 11 '15 at 10:01
  • This answer should be edited to reflect the newer 'flex' strategies. There's most likely a way to make it much more compact and more streamlined. – jeancallisti Oct 26 '21 at 11:19
  • @jeancallisti Feel free to add your own answer using flex boxes – Knyri Dec 07 '21 at 15:24
  • @Knyri I'm not good enough for that, that's the problem :-D – jeancallisti Feb 09 '22 at 09:40
87

With HTML5, the easiest way is simply to do height: 100vh. Where 'vh' stands for viewport height of the browser window. Responsive to resizing of browser and mobile devices.

Taylor Ham
  • 42
  • 1
  • 9
alchuang
  • 3,487
  • 3
  • 34
  • 48
15

I had a similar problem and the solution was to do this:

#cloud-container{
    position:absolute;
    top:0;
    bottom:0;
}

I wanted a page-centered div with height 100% of page height, so my total solution was:

#cloud-container{
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    right:0; 
    width: XXXpx; /*otherwise div defaults to page width*/
    margin: 0 auto; /*horizontally centers div*/
}

You might need to make a parent element (or simply 'body') have position: relative;

Nate Barr
  • 4,640
  • 2
  • 25
  • 21
  • 23
    Why is everyone calling it a `cloud-container`? – Wilf Feb 17 '14 at 07:27
  • This is a nice one! Ignoring fixing the height is a brilliant idea actually and I didn't notice any bug with it yet. Love it. KISS ! Thanks for the tip man! – daneczech May 18 '16 at 13:55
  • Making the position not solving it .. some bugs of fixed footer i have noticed – mercury Dec 15 '20 at 22:29
12

You can cheat using Faux Columns Or you can use some CSS trickery

Barnyard
  • 273
  • 3
  • 11
Ryan Doherty
  • 38,580
  • 4
  • 56
  • 63
8

I ran into the same problem as you. I wanted to make a DIV as background, why, because its easy to manipulate div through javascript. Anyways three things I did in the css for that div.

CSS:

{    
position:absolute; 
display:block; 
height:100%; 
width:100%; 
top:0px; 
left:0px; 
z-index:-1;    
}
Pbk1303
  • 3,702
  • 2
  • 32
  • 47
Talha
  • 1,546
  • 17
  • 15
8

Use position absolute. Note that this isn't how we are generally used to using position absolute which requires manually laying things out or having floating dialogs. This will automatically stretch when you resize the window or the content. I believe that this requires standards mode but will work in IE6 and above.

Just replace the div with id 'thecontent' with your content (the specified height there is just for illustration, you don't have to specify a height on the actual content.

<div style="position: relative; width: 100%;">
      <div style="position: absolute; left: 0px; right: 33%; bottom: 0px; top: 0px; background-color: blue; width: 33%;" id="navbar">nav bar</div>
      <div style="position: relative; left: 33%; width: 66%; background-color: yellow;" id="content">
         <div style="height: 10000px;" id="thecontent"></div>
      </div>
</div>

The way that this works is that the outer div acts as a reference point for the nav bar. The outer div is stretched out by the content of the 'content' div. The nav bar uses absolute positioning to stretch itself out to the height of its parent. For the horizontal alignment we make the content div offset itself by the same width of the navbar.

This is made much easier with CSS3 flex box model, but that's not available in IE yet and has some of it's own quirks.

tstanis
  • 186
  • 1
  • 1
7

I want to cover the whole web page before prompting a modal popup. I tried many methods using CSS and Javascript but none of them help until I figure out the following solution. It works for me, I hope it helps you too.

<!DOCTYPE html>
<html>
 <head>
  <style>
   html, body {
       margin: 0px 0px;
       height 100%;
   }
          
            div.full-page {
                position: fixed;
                top: 0;
                bottom: 0;
                width: 100%;
                height: 100%;
                background-color: #000;
                opacity:0.8;
                overflow-y: hidden;
                overflow-x: hidden;
            }
          
            div.full-page div.avoid-content-highlight {
                position: relative;
                width: 100%;
                height: 100%;
            }
          
            div.modal-popup {
                position: fixed;
                top: 20%;
                bottom: 20%;
                left: 30%;
                right: 30%;
                background-color: #FFF;
                border: 1px solid #000;
            }
  </style>
  <script>
  
   // Polling for the sake of my intern tests
   var interval = setInterval(function() {
    if(document.readyState === 'complete') {
     clearInterval(interval);
     isReady();
    }    
   }, 1000);
   
   function isReady() {
    document.getElementById('btn1').disabled = false;
    document.getElementById('btn2').disabled = false;
    
    // disable scrolling
                document.getElementsByTagName('body')[0].style.overflow = 'hidden';
   }
   
   function promptModalPopup() {
                document.getElementById("div1").style.visibility = 'visible';
                document.getElementById("div2").style.visibility = 'visible';
    
    // disable scrolling
                document.getElementsByTagName('body')[0].style.overflow = 'hidden';
            }
          
            function closeModalPopup() {
                document.getElementById("div2").style.visibility = 'hidden';  
                document.getElementById("div1").style.visibility = 'hidden';
    
    // enable scrolling
                document.getElementsByTagName('body')[0].style.overflow = 'scroll';
            }
  </script>
  
 </head>
 <body id="body">
  <div id="div1" class="full-page">
   <div class="avoid-content-highlight">
                
            </div>
  </div>
        <button id="btn1" onclick="promptModalPopup()" disabled>Prompt Modal Popup</button>
  <div id="demo">
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
   <h2>Original content</h2>
  </div>
        <div id="div2" class="modal-popup">
            I am on top of all other containers
            <button id="btn2" onclick="closeModalPopup()" disabled>Close</button>
        <div>
 </body>
</html>

Good luck ;-)

7

It's simple using a table:

<html>

<head>
    <title>100% Height test</title>
</head>

<body>
    <table style="float: left; height: 100%; width: 200px; border: 1px solid red">
        <tbody>
            <tr>
                <td>Nav area</td>
            </tr>
        </tbody>
    </table>
    <div style="border: 1px solid green;">Content blabla... text
        <br /> text
        <br /> text
        <br /> text
        <br />
    </div>
</body>

</html>

When DIV was introduced, people were so afraid of tables that the poor DIV became the metaphorical hammer.

Reza Ghorbani
  • 2,396
  • 2
  • 28
  • 33
Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • 6
    While DIVs and fluid styles are great, I think CSS still fails to capture the essence of screen layout in the same way that TABLE achieves the essence of table layout. ...And table layout is still an acceptable way to do things. – Jeff Meatball Yang Jun 20 '09 at 13:55
  • 13
    Tables are meant for tabular data, not page layout. That being said, CSS has some major shortcomings when it comes to the age-old 100% height question. I have to admit that I have used this solution when on a tight deadline, but it always felt like I was giving up. – Scott Greenfield Dec 10 '11 at 22:06
  • 6
    @Scott: I've once wasted three weeks trying to get a 100% height design right in three major browsers. I really can't hear the "tables are evil" bullshit anymore :-( Even with my knowledge, using DIVs is way too complicated. – Aaron Digulla Dec 12 '11 at 09:08
  • 1
    Proper planning ensures that no reliance on tables is necessary. Now in 2012, with the industry as a whole pushing past IE6/7, I strongly advise against using tables for 100% height! – Vael Victus Jan 27 '12 at 04:44
  • 1
    @ScottGreenfield Agreed, but until CSS can do a simple `height: 100%` and *just have it work*, sometimes the quicker win is more worthwhile. – Cypher Jan 19 '14 at 06:55
  • 5
    You don't have to use , you could use
    – Wilf Feb 17 '14 at 07:26
  • 1
    The only problem with this answer is that it doesn't work. The table is being sized to 100% of the viewport, not 100% of the page. – Lumberjack Aug 30 '16 at 15:09
3
* {
margin: 0;
}
html, body {
height: 90%;
}
.content {
min-height: 100%;
height: auto !important;
height: 100%;
margin: 0 auto ;
}
Swadesh Behera
  • 927
  • 9
  • 13
2

If you are targeting more modern browsers, life can be very simple. try:

.elem{    
    height: 100vh;
 }

if you need it at 50% of the page, replace 100 with 50.

Adam Boostani
  • 5,999
  • 9
  • 38
  • 44
  • 12
    This assumes that the page height is the same as the screen height. A page can often be a lot longer than the height of the screen, hence why we scroll down. – TidyDev Nov 24 '19 at 07:10
1

 
           document.body.onload = function () {
                var textcontrol = document.getElementById("page");
                textcontrol.style.height = (window.innerHeight) + 'px';
            }
<html>
<head><title></title></head>
<body>

<div id="page" style="background:green;">
</div>
</body>
</html>
reaw_ni
  • 11
  • 2
1

This is how you can make your side nav as tall as the page content, without having to change the body to be flex or table.

Don't set html or body to height 100%, because that will make it only as tall as the browser viewport, and the page will be overflowing that, and your nav will only be as tall as the viewport.

Just set your nav to height:100% position:absolute with the html tag position:relative.

The reason this works is because height 100% only works if its container is fixed height, with the exception (for some reason) the html tag.

<html style='position:relative'>
    <body style='margin:0'>
        <div style='height:100%; position:absolute; top:0; background:linear-gradient(to bottom,red,green); border:2px solid blue'>
            nav
        </div>
        <div style='font-size:99px;padding:33px'>
            I want my side div to be as tall as the page content.<br />
            I want my side div to be as tall as the page content.<br />
            I want my side div to be as tall as the page content.<br />
            I want my side div to be as tall as the page content.<br />
            I want my side div to be as tall as the page content.<br />
            I want my side div to be as tall as the page content.<br />
            I want my side div to be as tall as the page content.<br />
            I want my side div to be as tall as the page content.<br />
            I want my side div to be as tall as the page content.<br />
            I want my side div to be as tall as the page content.<br />
            I want my side div to be as tall as the page content.<br />
        </div>
    </body>
</html>
Curtis
  • 2,486
  • 5
  • 40
  • 44
1

This code works but not fully supports:

height: 100svmax;

Browsers support

Edit

Sorry, old answer is not correct.. i have tried all viewport units but the only solution work using javascript here

Hisham Dalal
  • 565
  • 4
  • 10
0

Simple, just wrap it up in a table div...

The HTML:

<div class="fake-table">
   <div class="left-side">
     some text
   </div>
   <div class="right-side">
     My Navigation or something
   </div>
</div>

The CSS:

<style>

 .fake-table{display:table;width:100%;height:100%;}
 .left-size{width:30%;height:100%;}
 .left-size{width:70%;height:100%;}

</style>
Steffan Perry
  • 2,112
  • 1
  • 21
  • 21
-1

I succeeded with

min-height: 100vh

for both, the menu and content div.

sntrcode
  • 202
  • 1
  • 7
  • 10
  • This could work poorly on mobile since the address bar can appear or disappear without technically changing the vertical height value, creating strange effects. – Tim Krief Jul 10 '21 at 23:57
  • 1
    vh = viewport height (the height of the screen) != page height (the height of the website) – honk31 Jan 31 '22 at 15:22