Friday, September 09, 2011

How To Calculate Browser Height And Display An In-Page-Pop-Up [tutorial]


While recently working on a website I wanted to add an in-page-pop-up whenever a user clicked a feedback button. It became slightly tricky because there were some pages where the content was longer than the browser height (i.e. you had to scroll), and other times where the content was shorter than the browser's height. I did some online hunting, but never found a great solution. Then, I had my own little insight: use a hidden div at the bottom of my content. I can calculate where it is, then compare it to the height of my browser. Whichever is longer, that's the one I'll use.

So, here's a tutorial on how to make a simple in-page-pop-up with a semi-transparent backdrop. You get lots out of this tutorial:
  • How to calculate your browser height using javascript
  • How to compare your browser height to your content's length
  • How to make a div transparent using CSS
  • I also throw in some rounded corners using CSS
  • How to use the onclick="" mouse action in javascript
  • A simple javascript "for" loop
  • How to insert new content into an element using javascript's innerHTML function.
  • How to make your popup display, and disappear

First, here's all the code, then I'll break it down. You can save this as your own file and mess with it. You can also see it working here.

======================

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
   <head>
      <style>
         *{margin:0; padding:0}

         html, body {
            margin:0px;
            padding:0px;
            background:#fff;
            font-family:arial,sans-serif;
            font-size:.95em;
            text-align:left;
            overflow:auto;
         }

         #backdrop{
            position:absolute;
            top:0px;
            left:0px;
            width:100%;
            height:0px;
            background:#333;
            opacity:0.4;
            filter:alpha(opacity=40);
            }

         #popup-wrapper{
            position:fixed;
            top:150px;
            left:0px;
            width:100%;
            }

         #popup{
            background:#fff;
            width:500px;
            margin:auto;
            padding:.5em;
            -moz-border-radius:5px;
            -webkit-border-radius:5px;
            border-radius:5px;
            }

         #bottomofcontent{
            display:hidden;
            }
      </style>
   </head>

   <body>
      <div id="maincontent">
         <p>All of your normal content here. Can be longer or shorter than the browser window.</p>
         <p><a href="javascript:void(0)" onclick="addmoretext()">Add More Text!</a></p>
         <p id="moretext"></p>
         <p><a href="javascript:void(0)" onclick="displaypopup()">Show Popup!</a></p>
      </div>
      <div id="backdrop" style="display:none"></div>
      <div id="popup-wrapper" style="display:none">
          <div id="popup" >
            <p>Put new things in here.</p>
            <p><a href="javascript:void(0)" onclick="hidepopup()">Close me!</a></p>
         </div>
      </div>
      <div id="bottomofcontent"></div>
   </body>

   <script type="text/javascript" language="javascript">
      function addmoretext(){
         var newtext = "";
         for(i=1; i <= 100; i++){
            newtext = newtext + "line " + i + "<br />";
         }
         document.getElementById('moretext').innerHTML = newtext;
      }

      function displaypopup(){
         var totalheight = heightcalc();
         document.getElementById('backdrop').style.height = totalheight + "px";
         document.getElementById('backdrop').style.display = "block";
         document.getElementById('popup-wrapper').style.display = "block";
      }

      function hidepopup(){
         document.getElementById('popup-wrapper').style.display = "none";
         document.getElementById('backdrop').style.display = "none";
      }

      function heightcalc(){
         // Calculate the size
         var myHeight = 0;
         var myContent = document.getElementById('bottomofcontent').offsetTop;
         if( typeof( window.innerWidth ) == 'number' ) {
            myHeight = window.innerHeight;
         } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
            myHeight = document.documentElement.clientHeight;
         } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
            myHeight = document.body.clientHeight;
         }
         if( myHeight > myContent ){
            return myHeight; 
         } else{
            return myContent;
         }
      }
   </script>

</html>

======================

I'm going to start with the body:

<body>
      <div id="maincontent">
         <p>All of your normal content here. Can be longer or shorter than the browser window.</p>
         <p><a href="javascript:void(0)" onclick="addmoretext()">Add More Text!</a></p>
         <p id="moretext"></p>
         <p><a href="javascript:void(0)" onclick="displaypopup()">Show Popup!</a></p>
      </div>
      <div id="backdrop" style="display:none"></div>
      <div id="popup-wrapper" style="display:none">
          <div id="popup" >
            <p>Put new things in here.</p>
            <p><a href="javascript:void(0)" onclick="hidepopup()">Close me!</a></p>
         </div>
      </div>
      <div id="bottomofcontent"></div>
   </body>

  • First, we have our main content. This can be anything.
  • I added a little text, and a couple links which when clicked will run the function called "addmoretext" or "displaypopup". Hopefully it's obvious what each of these functions do. We'll get to the actual javascript in a bit.
  • Then we have our "backdrop" and "popup-wrapper". The display needs to be set to "none". Also, it has to be as an inline style="" modifier. Otherwise javascript won't make it appear. So, these two containers are there, but are not displayed yet.
  • Then the actual pop-up div which will display whatever you want the pop-up to be.
  • Why have two separate divs ("backdrop" and "popup-wrapper")? Because the backdrop is going to be semi-transparent. If the popup-wrapper was inside the backdrop, it too would be semi-transparent. In this case, we want it to be fully opaque.
  • Inside the "popup-wrapper" is the actual "popup". The "popup" has some text and then a link which will close/hide it.
  • Finally, we have the "bottomofcontent" div. This should be right next to the "body" tag. The very end of all your content.


Here's the CSS. I'll make a comment about each one as we go:

         *{margin:0; padding:0}
// Just a standard setting I use to make all browsers look the same

         html, body {
            margin:0px;
            padding:0px;
            background:#fff;
            font-family:arial,sans-serif;
            font-size:.95em;
            text-align:left;
            overflow:auto;
         }
// Another standard I use to make sure everything looks the way I would expect.

         #backdrop{
            position:absolute;
            top:0px;
            left:0px;
            width:100%;
            height:0px;
            background:#333;
            opacity:0.4;
            filter:alpha(opacity=40);
            }
// I position it at the top. It stretches 100% of the browser width. Height = 0 because later we'll calculate what it should be. Why not just use 100% for the height? We could, but if the content is longer than the browser window, it won't cover everything.

         #popup-wrapper{
            position:fixed;
            top:150px;
            left:0px;
            width:100%;
            }
// Also fixed to the top, but brought down a little. Remember, this one and "backdrop" are not displayed when the page loads. I choose to use "fixed" for the position so the box will always display in the same place in the browser no matter how far the user scrolls.

         #popup{
            background:#fff;
            width:500px;
            margin:auto;
            padding:.5em;
            -moz-border-radius:5px;
            -webkit-border-radius:5px;
            border-radius:5px;
            }
// The popup. "margin:auto"centers it on the page. Those 3 radius settings give it round corners. You could set the width to a percent if you wanted. You can also set borders, change colors, whatever. It's a regular div. Notice this one isn't hidden. It doesn't have to be because it's parent div ("popup-wrapper") is hidden.

         #bottomofcontent{
            display:hidden;
            }
// Notice I put "display:hidden" instead of "display:none". If it was display:none, the browser wouldn't know it's position. Visually, it's the same as none, but the browser interprets it differently.



OK. Let's look at the javascript. Again, I'll make comments along the way.

  function addmoretext(){
         var newtext = "";
         for(i=1; i <= 100; i++){
            newtext = newtext + "line " + i + "<br />";
         }
         document.getElementById('moretext').innerHTML = newtext;
      }
// This is really just for the example. I use a for loop to create 100 new lines of text. That should be enough for the content to be longer than the browser. I then fill my "p" element called "moretext" with this new text. innerHTML does what the name implies: it fills inside the element which whatever you put.

      function displaypopup(){
         var totalheight = heightcalc();
         document.getElementById('backdrop').style.height = totalheight + "px";
         document.getElementById('backdrop').style.display = "block";
         document.getElementById('popup-wrapper').style.display = "block";
      }
// First we get the height (wait for it... it's coming). Then we apply that height to "backdrop". Then we display "backdrop" and "popup-wrapper". To display something, we either use "block" or "inline". Since these are div elements, they are block elements, so we use block.

      function hidepopup(){
         document.getElementById('popup-wrapper').style.display = "none";
         document.getElementById('backdrop').style.display = "none";
      }
// When it's time to hide the pop-up, just use .display = "none". Notice, I reversed the order in which they're hidden from when they were displayed. Computers are typically fast enough that the order doesn't matter too much, but I feel good about knowing the disappear in an order than makes sense to me. You could also set the height of "backdrop" to zero, but there's no real reason to.

      function heightcalc(){
         // Calculate the size
         var myHeight = 0;
         var myContent = document.getElementById('bottomofcontent').offsetTop;
         if( typeof( window.innerWidth ) == 'number' ) {
            myHeight = window.innerHeight;
         } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
            myHeight = document.documentElement.clientHeight;
         } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
            myHeight = document.body.clientHeight;
         }
         if( myHeight > myContent ){
            return myHeight; 
         } else{
            return myContent;
         }
      }
// here's the height calculation. First we set myHeight to 0 as a placeholder. The we get the "bottomofcontent" by using offsetTop function. Now, different browsers calculate browser heights differently. The set of if/elseif's goes through each browser type. When it finds the right one, it sets myHeight to the browser height. Then we have one final if statement that compares myHeight to myContent. Whichever is longer gets returned. Boom.

So that's how you make a simple in-page-pop-up in a website. You can make it more complicated using ajax and fill the pop-up with new content pulled off the server, but that's for another time. Hopefully there was at lease one tidbit that was helpful.

No comments:

Post a Comment