views:

233

answers:

4

I am having a tough time thinking a solution to the following problem.
Let me illustrate it first
Navigation Interface - Hourglass like

Situation
I have 26 items (in this example, in general the number is not known..) but only 12 can be visible at one time.. I also have some navigation elements (the green boxes)

Width of purple and green boxes is fixed but height of purple can vary according to content ..

All is normal and i can do it with css.

I am using an unordered list (of floated items) for my items and i have designated the first two <li> elements as the navigations ones. First has float left and second float right. It all works and the flow of the rest of the items goes between the two green ones.

Problem
But now i need the green items to be on the second row (or last if that concept helps as there will only be two rows)

I want to be able to hide the first X elements and show the next X and they fall in position on their own ..

To rephrase the question, can i position some elements (the green ones) in such a way to control their position but still allow them to interfere with the flow from their new locations ?

I hope this is clear. If not ask away and i will provide as much info as possible..

Things i have tried that did not work

  • Moving the green item with negative bottom margins, or positive top margins. They will move out of their place but the other elements will not fill in their position.
  • Using absolute position, but then the elements are completely removed from the flow and they do not affect the other elements so they overlap with the other elements..

[they grayed out items are hidden, i just show them so you know that they exist..]

Some code to get you started

<style type="text/css">
    ul,li{padding:0;margin:0; list-style-type:none;}
    ul{
        width:155px;
        position:relative;
        height:125px;
        border:1px solid red;
    }
    li{
        float:left;
        background-color:purple;
        margin-left:5px;
        margin-top:5px;
        width:25px;
        text-align:center;
        line-height:25px;
        color:white;
    }
    .prev{
        color:black;
        background-color:green;
    }
    .next{
        color:black;
        float:right; 
        margin-right:5px;
        background-color:green;
    }
</style>

and

<body>
    <ul>
        <li class="prev">&lt;</li>
        <li class="next">&gt;</li>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
        <li>7</li>
        <li>8</li>
        <li>9</li>
        <li>10</li>
        <li>11</li>
        <li>12</li>
        <li>13</li>
        <li>14</li>
        <li>15</li>
        <li>16</li>
        <li>17</li>
    </ul>
</body>
+3  A: 

It may be worth it to use javascript for a situation this complex. Libraries like jQuery can make it pretty painless. Defining these wrapping rules explicitly in js will be clearer and easier to maintain than doing it implicitly with a lot of css rules.

Christian Oudard
:) Halfway through the question, I thought about answering "No. Use JQuery." you beat me to the punch. To be fair though, I don't understand the question fully yet, and it might be possible to do without Javascript.
Pekka
just added some starting code
Gaby
ok Jquery is a possibility.. Do you suggest i turn everything to position:absolute and calculate and apply the positioning by code on all involved elements ?
Gaby
+1  A: 

Without seeing your code I cannot be sure. However, have you tried putting the green elements into tags and marking them as clear: both;? This might move them into a 3rd row though. It is something you should checkout.

RandomBen
code added, but the navigation elements being on their own is not an option .. :(
Gaby
+1  A: 

Make the li except the navigation ones as display: inline-block and perhaps move the navigation li to the end of the list?

Chetan Sastry
Made me excited there for a moment .. problem is with the left arrow which is floated left, if the elements are less than 7 then it will move to that line .. i want it to stay together with the right arrow on the last row..
Gaby
Also, IE6 cannot handle it correctly in this situation .. it puts the arrows on a row of their own (although if it worked on the rest of the browsers i could accept IE6 non-compatibility ..)
Gaby
You did not mention anything about less than 7 items in your question!! :p Could you have some 'ghost elements' to make it always greater than 7 elements? What is this to do with 'hourglass' anyway?
Chetan Sastry
The ghost elements is the way i did it (it is in the code i posted in my answer but i do not have comments ..). The hourglass is just the shape it looks like with two navigation elements on the sides and the free numbered elements floating on the inside sides.. (perhaps a bad metaphor .. :s )
Gaby
+2  A: 

OK obviously this can not be solved with only Css/Html ..

So, to solve it, i used some CSS (with inline-block crossbrowser) and some jQuery to move the navigation buttons around so they stay always at the point i want them..

For reference here is the solution ..

CSS

<style type="text/css">
    ul,li{padding:0;margin:0; list-style-type:none;}
    #performances{
        width:155px;
        border:1px solid red;
        line-height:0;
        font-size:0;
    }
    #performances li{
        font-size:12px;
        background-color:purple;
        margin-left:5px;
        margin-bottom:5px;
        margin-top:5px;
        width:25px;
        text-align:center;
        line-height:25px;
        color:white;
        display:none;
        vertical-align:top;
    }
    #performances .prev{
        color:black;
        background-color:green;
        display: -moz-inline-stack;
        display:inline-block;
    }
    #performances .next{
        color:black;
        background-color:green;
        display: -moz-inline-stack;
        display:inline-block;
    }
    #performances .shown{
        display: -moz-inline-stack;
        display:inline-block;
    }
    #performances .placeholder{visibility:hidden;}
</style>
<!--[if lte IE 7]><style>
    #performances .prev,#performances .next,#performances .shown{zoom:1;*display:inline;}
</style><![endif]-->

Javascript (jQuery )

<script type="text/javascript">
    function resetNextPrev( ){
        $next.insertAfter('#performances li.shown:eq('+ ($perpage-1) +')');
        $prev.insertAfter('#performances li.shown:eq('+ ($perline-1) +')');
    }
    $(document).ready(function(){
        $perpage = 8;
        $perline = ($perpage+2) / 2;
        $page = 1;
        $itemcount = $('#performances li.performance').length;
        $pages = Math.ceil ( $itemcount / $perpage);
        $next = $('#performances li.next');
        $prev = $('#performances li.prev');

        $('#performances li.performance').slice(0,$perpage).addClass('shown');

        if (($pages * $perpage) > $itemcount )
                for (var i =0;i< ($pages * $perpage)-$itemcount;i++) 
                        $('<li class="performance placeholder">test</li>').appendTo('#performances');
        resetNextPrev();

        $('li.next').click(function(){
            if ($page < $pages)
                $('#performances li.performance').filter('.shown').removeClass('shown').end().slice($perpage * (++$page-1),$perpage * $page).addClass('shown');
            resetNextPrev( $perline );

        });
        $('li.prev').click(function(){
            if ($page > 1)
                $('#performances li.performance').filter('.shown').removeClass('shown').end().slice($perpage * (--$page-1),$perpage * $page).addClass('shown');
            resetNextPrev( $perline );

        });
    });
</script>

.. and the HTML

    <ul id="performances">
        <li class="prev">&lt;</li>
        <li class="next">&gt;</li>
        <li class="performance">1</li>
        <li class="performance">2</li>
        <li class="performance">3</li>
        <li class="performance">4 dfs s sf</li>
        <li class="performance">5</li>
        <li class="performance">6</li>
        <li class="performance">7</li>
        <li class="performance">8</li>
        <li class="performance">9</li>
        <li class="performance">10</li>
        <li class="performance">11</li>
        <li class="performance">12</li>
        <li class="performance">13</li>
        <li class="performance">14</li>
        <li class="performance">15</li>
        <li class="performance">16</li>
        <li class="performance">17</li>
        <li class="performance">18</li>
        <li class="performance">19</li>
    </ul>

There are a couple of hardcoded values inside, but i will leave it for anyone that might pick up something new from this ...

Thanks to all for the guidance :)

Gaby