Search code examples
htmlcsscss-tables

Can this be achieved without using a table? Percentage height in dynamic container


I am at a loss! For the first time ever, I have found something that I believe cannot be achieved without using a table for layout.

I am trying to place a separator div inbetween unordered lists, that sizes its height automatically based on the size of the container.

  1. I cannot use height: x%; because there is not a set height on the container as the content is dynamic!
  2. I cannot use position: absolute;top: 10px; bottom: 10px; because the div must be placed relative to the unordered list!

Achieving this with a table would be very easy by simply manipulating the rows to give the same effect, however, as much of you will agree, tables are for the 1990's and I like to stay away from them unless absolutely necessary or if I am displaying tabular data.

I have recreated the problem in this jsFiddle. There is a lot of code in this fiddle, most of which can be ignored. The div's in question are part of a sub menu (Item 2 on the menu) and they have a class of 'separator', the styles of which can be found right at the end of the css.

Although all the code is in the jsFiddle, I have extracted the relevant snippets below:

Note that I have temporarily fixed the height of the separator to 150px to make sure they are visible in the example

HTML:

<li id="shiNav"><a href="#" title="#">Item 2</a>
    <div class="subMenuHandle horizontal-sprite">
        <div class="bg-noise"></div>
    </div>
    <div class="subMenu horizontal-sprite">
        <div class="bg-noise"></div>
        <ul>
            <li><a href="#"><strong>Menu Item 1</strong></a></li>
            <li><a href="#"><strong>Menu Item 2</strong></a></li>
            <li><a href="#"><strong>Menu Item 3</strong></a></li>
            <li><a href="#"><strong>Menu Item 4</strong></a></li>
        </ul>
        <div class="separator"></div>
        <ul>
            <li class="title">Recently Opened File</li>
            <li><a href="#">File 1</a></li>
            <li><a href="#">File 2</a></li>
            <li><a href="#">File 5</a></li>
            <li><a href="#">File 20</a></li>
        </ul>
        <div class="separator"></div>
        <ul>
            <li class="title">Most Used Customers</li>
            <li><a href="#">John Smith &amp; Co</a></li>
            <li><a href="#">ManSys Limited</a></li>
            <li><a href="#">Sine Macula Limited</a></li>
            <li><a href="#">Infralobo PLC</a></li>
            <li><a href="#">Lays PLC</a></li>
        </ul>
    </div>
</li>

CSS:

/* Navigation */
#global-nav {position:absolute;width:460px;height:27px;left:15px;top:43px;}

#global-nav ul {margin:0;padding:0;list-style-type:none;}
#global-nav ul li {position:relative;display:block;width:92px;height:27px;float:left;padding:0;margin-left:8px;z-index:10;background-image:url("http://www.mansys.net/_test/sprite.png");background-position:-173px -32px;}
#global-nav ul li:hover {background-position:-173px -59px;}
#global-nav ul li:active {background-position:-173px -86px;}
#global-nav ul li a {display:block;width:92px;height:27px;line-height:27px;text-align:center;color:#fff;font-size:12px;text-shadow:#666 0 -1px 0;}
#global-nav ul li:hover a {color:#666;text-shadow:#fff 0 1px 0;}
#global-nav ul li:active a {color:#666;text-shadow:none;}

/* Set styles for specific navigation buttons */
#homNav {width:47px !important;margin-left:0 !important;margin-right:12px;background-position:-126px -32px !important;}
#homNav a {width:47px !important;}
#homNav:hover {background-position:-126px -59px !important;}
#homNav:active {background-position:-126px -86px !important;}

/* Set hovers of sub menu buttons to active images */
#masNav:hover,
#shiNav:hover,
#repNav:hover,
#setNav:hover
{background-position:-173px -86px !important;}

/* Set the sub menu handles */
#global-nav .subMenuHandle {position:relative;display:none;width:90px;height:12px;margin-top:-1px;border-left:1px solid #666;border-right:1px solid #666;z-index:1000;background-color:#fff;background-repeat:repeat-x;}

/* Set the sub menu container */
#global-nav .subMenu {position:relative;display:none;margin-top:-1px;width:870px;padding:10px 20px;border:1px solid #666;z-index:999;background-color:#ddd;background-position:0 -12px;background-repeat:repeat-x;overflow:hidden;clear:both;border-radius:3px;}

/* Set the menu hovers to show sub menus */
#global-nav ul li:hover .subMenuHandle,
#global-nav ul li:hover .subMenu
{display:block;}

/* Set the sub menu container positions */
#masNav .subMenu {margin-left:-83px;}
#shiNav .subMenu {margin-left:-183px;}
#repNav .subMenu {margin-left:-283px;}
#setNav .subMenu {margin-left:-383px;}

/* Set the noise in the menus */
.bg-noise {position:absolute;left:0;top:0;width:100%;height:100%;background:url("https://www.mansys.net/_images/_global/bg-noise.png") repeat;}

/* Define sub menu Contents */
#global-nav .subMenu ul {display:block;float:left;overflow:hidden;}
#global-nav .subMenu ul li {display:inline;width:auto;height:25px;margin:0;float:none;background:none;}
#global-nav .subMenu ul li.title {line-height:25px;font-size:12px;color:#666;text-shadow:#fff 0 1px 0;text-align:left;}
#global-nav .subMenu ul li a {position:relative;display:block;width:auto;height:25px;line-height:25px;font-size:12px;color:#333;text-shadow:#fff 0 1px 0;text-align:left;z-index:1000;}

/* Define the sub menu separator */
#global-nav .subMenu .separator {position:relative;float:left;width:1px;background:#999;margin:20px 20px 0;height:90%}

Solution

  • It is achievable in modern browsers, however I don't have a device to hand to test any of the Internet Explorers of this world, and they will be the ones to watch out for (they are notorious when it comes to position relative oddness or float problems).

    Basically you need to rely on your menu container being position:relative, and then make sure you wrap your separators with a div that uses float:left to position the separator in the right locations (i.e. along the right side of your ul lists) - I've used .psep.

    Once you do that you can use position:absolute; top:0; bottom:0; for your separator because it will calculate it's height in-regard to the first positioned parent (i.e. #menu not .psep) but calculate it's horizontal position in-regard to your ul lists.

    Hope that makes sense? I put together an example below...

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html>
    <head>
    <style type="text/css">
    
    #menu {
      position: relative;
      overflow: hidden;
    }
    
    #menu ul {
      display: block;
      float: left;
      overflow: hidden;
      list-style-type: none;
      margin: 0;
      padding: 0;
    } 
    
    .psep {
      float: left;
      height: 1px;
      margin-left: 10px;
      margin-right: 10px;
    }
    
    .sep { 
      position: absolute;
      top: 0;
      bottom: 0;
      background: #000;
      width: 1px;
    }
    
    </style>
    </head>
    <body>
      <div id="menu">
        <ul>
          <li>This is a test with a long title</li>
          <li>2</li>
          <li>3</li>
          <li>4</li>
          <li>5</li>
        </ul>
        <div class="psep"><div class="sep"></div></div>
        <ul>
          <li>1</li>
          <li>2</li>
          <li>3</li>
          <li>Another long text</li>
          <li>5</li>
          <li>6</li>
          <li>7</li>
          <li>8</li>
        </ul>
        <div class="psep"><div class="sep"></div></div>
        <ul>
          <li>1</li>
          <li>2</li>
          <li>3</li>
        </ul>
      </div>
    </body>
    </html>