views:

508

answers:

4

I apologize for the long paste of code here, but this has been bugging me for a good few hours now. I'm working on porting my entire site over into a new template, and I'm trying to make the various areas and things more size-aware so I can contain most of them in resizeable dockable windows and things, a very neat concept that's working out pretty well. Anyway, I've got one page with an external style sheet that I can't figure out for the life of me. Regardless of the vertical size of the content, it's showing a scrollbar and like 20px of extra blank page at the bottom. I've checked and rechecked, but all of my divs seem to be self-contained, and the only real odd bits (the edges, which involve negative positioning) don't fix the issue when removed.

This is the HTML I use on the page (It's generated dynamically a bit, this is a dump from when I'm logged on)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Objectives</title>
<script type="text/javascript" src="windows/jquery.js"></script>
<link href="windows/windows.css" rel="stylesheet" type="text/css">
<!-- Page Scripts -->

<!-- Generic "always on" scripts -->
<script type="text/javascript">
$(document).ready(function(){
   //Make that backgroud !ugly
   $("body").css("background-color","#000000");
   $("html").css("background-color","#000000");

   //Make all the tags open in new windows. Hee hee hee... good luck there
   $("a").click(function () {
    var url = $(this).attr("href");

    //Build the URL based on a select few modifications.
    if (url.charAt(0) == '?')
     url = "/"+url;

    //Grab the value of action for the string
    var type = url.substr(url.indexOf("action=") + 7);
    if (type.indexOf("&") != -1)
        var type = type.substr(0, type.indexOf("&"));

    parent.spawnNewWindow(url+'&noframe=none', document.title, type);
    return false;
   });

});

</script>

<script language="Javascript" type="text/javascript">
$(document).ready(function(){
    $(".tierPickerShown").click(function () { 
          $(this).parent(".tier").addClass("hideme");
    });
    $(".tierPickerHidden").click(function () { 
          $(this).parent(".tier").removeClass("hideme");
    });
});

</script>

</head>
<body>

    <div class="tier">
     <div class="tierCorner top left"></div>
     <div class="tierCorner top right"></div>
     <div class="tierCorner bottom left"></div>
     <div class="tierCorner bottom right"></div>
     <div class="tierEdgeTop"></div>
     <div class="tierEdgeMiddle"></div>

     <div class="tierEdgeBottom"></div>

     <div class="tierPickerShown"></div><div class="tierPickerHidden"></div>
     <div class="tierMarker"></div>
     <div class="tierTitle">Tier 1</div>
     <div class="tierSpacer"></div>


    <div class="tierItem">
     <div class="tierCheckbox tierActiveCheckbox "></div>
     <div class="tierObjective">Choose a Nova and devote your clan to that Nova.</div>

     <div class="tierUnderline"></div>
     <div class="tierReward">+5 Treasure&nbsp;&nbsp;&nbsp;</div>
     <div class="tierSpacer"></div>
    </div>

    <div class="tierItem">
     <div class="tierCheckbox tierActiveCheckbox "></div>
     <div class="tierObjective">Win an attack with a mage that has an item equipped.</div>
     <div class="tierUnderline"></div>

     <div class="tierReward">+10 Treasure&nbsp;&nbsp;&nbsp;</div>
     <div class="tierSpacer"></div>
    </div>

    <div class="tierItem">
     <div class="tierCheckbox"></div>
     <div class="tierObjective">Steal at least 2 treasure from another player in a single attack.</div>
     <div class="tierUnderline"></div>
     <div class="tierReward">+10 Treasure&nbsp;&nbsp;&nbsp;</div>

     <div class="tierSpacer"></div>
    </div>

    <div class="tierItem">
     <div class="tierCheckbox tierActiveCheckbox "></div>
     <div class="tierObjective">Complete 2 jobs.</div>
     <div class="tierUnderline"></div>
     <div class="tierReward">+25 Treasure&nbsp;&nbsp;&nbsp;</div>
     <div class="tierSpacer"></div>

    </div>

    <div class="tierItem">
     <div class="tierCheckbox tierActiveCheckbox "></div>
     <div class="tierObjective">Win an attack on a player who is devoted to a different Nova than you are.</div>
     <div class="tierUnderline"></div>
     <div class="tierReward">+10 Treasure&nbsp;&nbsp;&nbsp;</div>
     <div class="tierSpacer"></div>
    </div>


    <div class="tierItem">
     <div class="tierCheckbox tierActiveCheckbox "></div>
     <div class="tierObjective">Become a member of a guild.</div>
     <div class="tierUnderline"></div>
     <div class="tierReward">+15 Treasure&nbsp;&nbsp;&nbsp;</div>
     <div class="tierSpacer"></div>
    </div>

    <div class="tierItem">

     <div class="tierCheckbox"></div>
     <div class="tierObjective">Recruit at least one (1) new player to the game using the Invite system. The player must verify their account to qualify for the objective.</div>
     <div class="tierUnderline"></div>
     <div class="tierReward">+200 Treasure&nbsp;&nbsp;&nbsp;</div>
     <div class="tierSpacer"></div>
    </div>

    </div>

    <div class="tier">

     <div class="tierCorner top left"></div>
     <div class="tierCorner top right"></div>
     <div class="tierCorner bottom left"></div>
     <div class="tierCorner bottom right"></div>
     <div class="tierEdgeTop"></div>
     <div class="tierEdgeMiddle"></div>
     <div class="tierEdgeBottom"></div>

     <div class="tierPickerShown"></div><div class="tierPickerHidden"></div>
     <div class="tierMarker"></div>

     <div class="tierTitle">Tier 2</div>
     <div class="tierSpacer"></div>


    <div class="tierItem">
     <div class="tierCheckbox tierActiveCheckbox "></div>
     <div class="tierObjective">Be in first place after 3 days, or attack someone who has joined the Light Team.</div>
     <div class="tierUnderline"></div>
     <div class="tierReward">+10 Treasure&nbsp;&nbsp;&nbsp;Title Awarded: Recruit</div>

     <div class="tierSpacer"></div>
    </div>

    <div class="tierItem">
     <div class="tierCheckbox tierActiveCheckbox "></div>
     <div class="tierObjective">Be in second place after 3 days, or attack someone who has joined the Dark Team.</div>
     <div class="tierUnderline"></div>
     <div class="tierReward">+10 Treasure&nbsp;&nbsp;&nbsp;Title Awarded: Recruit</div>

     <div class="tierSpacer"></div>
    </div>

    <div class="tierItem">
     <div class="tierCheckbox"></div>
     <div class="tierObjective">Donate at least 25 Treasure to your Guild</div>
     <div class="tierUnderline"></div>
     <div class="tierReward"></div>
     <div class="tierSpacer"></div>

    </div>

    <div class="tierItem">
     <div class="tierCheckbox tierActiveCheckbox "></div>
     <div class="tierObjective">Win an attack on someone between 12 AM and 8 AM.</div>
     <div class="tierUnderline"></div>
     <div class="tierReward"></div>
     <div class="tierSpacer"></div>
    </div>


    <div class="tierItem">
     <div class="tierCheckbox"></div>
     <div class="tierObjective">Steal at least 10 treasure from another player in a single attack.</div>
     <div class="tierUnderline"></div>
     <div class="tierReward"></div>
     <div class="tierSpacer"></div>
    </div>

    <div class="tierItem">

     <div class="tierCheckbox"></div>
     <div class="tierObjective">Win an attack on a player who has at least 5 levels of Defense on each of his Mages at home.</div>
     <div class="tierUnderline"></div>
     <div class="tierReward"></div>
     <div class="tierSpacer"></div>
    </div>

    <div class="tierItem">
     <div class="tierCheckbox tierActiveCheckbox "></div>

     <div class="tierObjective">Win an attack on someone on a Weekend.</div>
     <div class="tierUnderline"></div>
     <div class="tierReward"></div>
     <div class="tierSpacer"></div>
    </div>

    </div>

    <div class="tier">
     <div class="tierCorner top left"></div>

     <div class="tierCorner top right"></div>
     <div class="tierCorner bottom left"></div>
     <div class="tierCorner bottom right"></div>
     <div class="tierEdgeTop"></div>
     <div class="tierEdgeMiddle"></div>
     <div class="tierEdgeBottom"></div>

     <div class="tierPickerShown"></div><div class="tierPickerHidden"></div>
     <div class="tierMarker"></div>
     <div class="tierTitle">Tier 3</div>

     <div class="tierSpacer"></div>


    <div class="tierItem">
     <div class="tierCheckbox"></div>
     <div class="tierObjective">Be the highest ranked [Team] Recruit after 1 week, or win an attack on an enemy Cleric</div>
     <div class="tierUnderline"></div>
     <div class="tierReward">Title Awarded: Cleric</div>
     <div class="tierSpacer"></div>
    </div>


    </div>
    </body>
</html>

And this is the corresponding CSS stylesheet. This is windows.css:

/* Body information for the windower, to theme the whole thingy. */

@import url('/tier.css');

html, body {
    width: 100%;
    height: 100%;
    padding: 0px;
    margin: 0px;
    background-color: #FFFFFF; /* Yes, the same color as the text. jQuery will change this to black for us, so it's a good
        indicator of any syntax errors in the javascript. */
    color: #DEDEDE;

    /* May be changed later, to be theme-specific */
    font-family: Trebuchet MS, sans-serif;  
    font-weight: bold;
    font-size: 14px;

}

a {
    color: #FFFFFF;
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
}

/* Windowing Information Here */

/* OMITTED - Doesn't seem relevant, the classes here aren't used */

And the problem code: tier.css

.tier {
    position: relative;
    width: 90%;
    margin-bottom: 25px;
    margin-top: 20px;
    margin-left: auto;
    margin-right: auto;
}

/* Classes to describe the shower/hider thing. One class for each state-- hidden and shown. The 
   respective class is shown based on whether or not its parent has the "hideme" class.          */

.tierPickerShown {
    position: relative;
    display: block;
    float: left;
    width: 24px;
    height: 24px;
    margin: 4px;
    z-index: 5;
    background-image: url('images/show_me_shown.png');
}

.tierPickerShown:hover {
    background-image: url('images/show_me_shown_hover.png');
}

.tierPickerHidden {
    position: relative;
    display: none;
    float: left;
    width: 24px;
    height: 24px;
    margin: 4px;
    z-index: 5;
    background-image: url('images/show_me_hidden.png');
}

.tierPickerHidden:hover {
    background-image: url('images/show_me_hidden_hover.png');
}

.tier.hideme .tierPickerShown {
    display: none;
}

.tier.hideme .tierPickerHidden {
    display: block;
}

/* Container for a tier objective. Holds the checkbox and the text elements. */
.tierItem {
    position: relative;
    width: auto;
    z-index: 5;
}

.tier.hideme .tierItem {
    display: none;
}

.tierCheckbox {
    float: left;
    width: 32px;
    height: 32px;
    margin-left: 8px;
    margin-right: 8px;
    background-image: url('images/checkbox.png');
}

.tierActiveCheckbox {
    background-image: url('images/checkbox_checked.png');
}

.tierObjective {
    margin-left: 54px;
    margin-bottom: 3px;
}

.tierUnderline {
    /* this is just WRONG */
    width: 200px;
    height: 2px;
    margin-left: 54px;
    background-color: #000000;
}

.tierReward {
    margin-left: 54px;
    font-size: 0.7em;
}

.tierSpacer {
    /* Empty div, designed to make sure there's some breathing room below the floated content. */
    clear: both;
    width: 100%;
    height: 5px;
}

.tierTitle {
    font-size: 2.0em;
    padding-left: 54px;
    z-index: 5;
}

.tierMarker {
    float: left;
    background-image: url('images/tier_incomplete.png');
    width: 48px;
    height: 32px;
}

.tierMarkerComplete {
    background-image: url('images/tier_complete.png');
}

/* Aesthetics Stuff */

.tierCorner {
    background-image: url('images/tier_round.png');
    width: 9px;
    height: 9px;
    position: absolute; 
}

.tierCorner.top.left {
    top: -9px;
    left: -9px;
    background-position: 0px 0px;
}

.tierCorner.bottom.left {
    bottom: -9px;
    left: -9px;
    background-position: 0px -9px;
}

.tierCorner.top.right {
    top: -9px;
    right: -9px;
    background-position: -9px 0px;
}

.tierCorner.bottom.right {
    bottom: -9px;
    right: -9px;
    background-position: -9px -9px;
}

.tierEdgeMiddle {
    position: absolute;
    left: -9px;
    right: -9px;
    height: 100%;
    background-image: url('images/tier_bg.png');
    z-index: 2;
}

.tierEdgeTop {
    position: absolute;
    width: 100%;
    top: -9px;
    height: 9px;
    background-image: url('images/tier_bg.png');
}

.tierEdgeBottom {
    position: absolute;
    width: 100%;
    bottom: -9px;
    height: 9px;
    background-image: url('images/tier_bg.png');
}

I appologize for the semi-poor CSS arrangement, there's a lot of duplicates sprinkled in everywhere, but I'd much prefer to understand what's making it auto-scrollbar the body area before I go on a shrink-this-code fest. Does anyone see anything blatantly obvious that I'm missing here? The only thing I can do to that page to make the scrollbars is to omit tier.css, which makes it look rather craptastic anyway.

If you'd like, I've set up a live version so you can see what it's supposed to look like, images, scrollbar and all, here.

Thanks, this will gain me several hours of sleep back if someone can point out what I've missed.

+2  A: 

Taking the height 100% off the body windows.css fixes the problem on Firefox, that may give you a place to start looking.

David Waters
This is true, but that's the weird thing: the height 100% is there the entire time, even on other pages, and only this one page seems to put stuff down below the bottom mark. I'm trying to figure out if margins are the cause? I'm almost ruling out a bug in rendering since all browsers seem to behave the same with it...
Nicholas Flynt
+1  A: 

Rather than try to make sense of the stylesheet jumble and html, I much prefer using Firefox with the Firebug plugin installed. Firebug allows you to Inspect page elements and it shows you which styles were applied to that element. You can also dynamically change styles to see how it affects the layout.

kbosak
Firebug doesn't work in FF3 unfortunately, the "Web developer toolbar" offers much much better inspection tools than firebug anyway.
Sam152
Firebug *does* work with FF3. I use Firebug AND the WebDev toolbar together - they both have different benefits.
Peter Boughton
Chrome's element inspection facilities kicks the **** out of firebug. Not to start a flamewar or anything.
Will
A: 

Your code is a classic example of 'divitis', and is far more complicated than it needs to be: with everything a div and using too many classes - this makes it harder to debug (even with Firebug/WDT) when problems like this arise.

Sometimes, just simplifying a page is enough to make odd quirky behaviour go away, so this is always the first thing I recommend. Here is a (very quick) example of some better code.
It may not be a perfect fit for what you want, but is a better base to start from than using divs for everything.

<!DOCTYPE html>
<html>
<head>
    <title>Objectives</title>

    <style type="text/css">
     * {margin:0;border-width:0;padding:0;}

     html
     {
      background: black;
      color:#DEDEDE;
      font: 14px Trebuchet MS bold;
     }

     .tier
     {
      width: 90%;
      margin: 20px auto 25px;
      padding: 0.5em;

      background: #404040;
      border-radius: 9px;
      -moz-border-radius: 9px;
      -webkit-border-radius: 9px;
     }

     .tier .picker
     {
      background: none;
      float: left; clear: left;
     }

     .tier h2
     {
      font-size: 2em;
      padding-left: 54px;
      margin: 0.1em 0;
     }

     .tier ul
     {
      list-style: none;
     }

     .tier ul li
     {
      margin-bottom: 5px;
     }

     .tier ul li .checkbox
     {
      width: 32px;
      height: 32px;
      margin: 0 8px;

      float: left; clear: left;
     }

     .tier ul li p
     {
      float: none; clear: right;
      margin-left: 48px;
     }

     .tier ul li p.reward
     {
      font-size: 0.7em;

      width: 200px;
      border-top: solid 2px black;
      margin-top: 4px;
     }

     .tier ul li p.reward .title
     {
      margin-left: 2em;
     }
    </style>
    <script type="text/javascript" src="jquery-1.3.2.min.js"></script>
    <script type="text/javascript">
     $j = jQuery.noConflict();

     $j(document).ready(init);

     function init()
     {
      $j('.picker').toggle
      (
       function()
       {
        $j(this).siblings('ul').hide();
        $j(this).children('img').attr('src','images/show_me_hidden.png').attr('alt','>');
       }
      ,
       function()
       {
        $j(this).siblings('ul').show();
        $j(this).children('img').attr('src','images/show_me_shown.png').attr('alt','v');
       }
      );
     }

    </script>
</head>
<body>
    <h1>Objectives</h1>


    <div class="tier">

     <button type="button" class="picker">
      <img src="images/show_me_shown.png" alt="v" />
     </button>

     <h2>Tier 1</h2>
     <ul>
      <li>
       <img class="checkbox" src="images/checkbox_checked.png" alt="*" title="Completed" />
       <p class="objective">Choose a Nova and devote your clan to that Nova.</p>
       <p class="reward">+5 Treasure</p>
      </li>
      <li>
       <img class="checkbox" src="images/checkbox_checked.png" alt="*" title="Completed" />
       <p class="objective">Win an attack with a mage that has an item equipped.</p>
       <p class="reward">+10 Treasure</p>
      </li>
      <li>
       <img class="checkbox" src="images/checkbox.png" alt=" " title="Uncompleted" />
       <p class="objective">Steal at least 2 treasure from another player in a single attack.</p>
       <p class="reward">+10 Treasure</p>
      </li>
     </ul>
    </div>

    <div class="tier">

     <button type="button" class="picker">
      <img src="images/show_me_shown.png" alt="v" />
     </button>

     <h2>Tier 2</h2>
     <ul>
      <li>
       <img class="checkbox" src="images/checkbox_checked.png" alt="*" title="Completed" />
       <p class="objective">Be in first place after 3 days, or attack someone who has joined the Light Team.</p>
       <p class="reward">+10 Treasure <span class="title">Title Awarded: Recruit</span></p>
      </li>
     </ul>
    </div>

</body>
</html>
Peter Boughton
Ooh... I hadn't thought about using an ul, but I suppose it does make a lot more sense there. I'll see what I can do that way.
Nicholas Flynt
Indeed, it's easy to miss when lists can be useful. Although once you start using lists more, it's also easy to overuse/misuse them. As with most things, it's a case of getting the right balance. :)
Peter Boughton
A: 

I think I've figured it out, although it still doesn't make any sense. The .tier class, which encompases individual groups of tiers (and is the only direct descendant of body) has a margin-top of 20px. Removing this also removes the ghost space at the bottom of the page, making the scrollbar die. However, it also pushes my tiers past the top of the page, so I compensated for this using a spacer. I don't like it, but it was the only way I could get it to work and look like I wanted it to.

I can't explain why margin-top was producing the extra space on the bottom of the container area, body in this case. Perhaps it's a rendering bug? Strange that it would be a bug in all implementations. If anyone could shed some insight on why this particular fix works, it would be most helpful.

Nicholas Flynt