views:

54

answers:

3

I have two divs, whose heights I would like to control relative to each other. The point of these divs is that when a user mouses over one of them, it expands vertically and the other retracts vertically (smoothed with CSS transitions). Basic markup:

<div class="product">
    <h2>Product Name</h2>

    <div class="preview" style="background:url('/images/preview.png'); "></div>
    <div class="detail" style="background:url('/images/design.png'); "></div>

    <div class="product_info">
        <span class="quantity">7 Available</span>
        <span class="price">$19</span>
    </div>
</div>

This is generated a number of times with unique images and other data pulled from a database, so these images are just placeholders, but that's not the question.

Here's the stripped down CSS:

div.product {
    margin: 4px;
    padding: 4px;
    display: inline-block;
    width: 221px;
    height: 319px;
    box-shadow: 0 0 5px #ccc;
    -moz-box-shadow: 0 0 5px #ccc;
    -webkit-box-shadow: 0 0 5px #ccc;
}

div.product div.preview, div.product div.detail {
    height: 127px;
    width: 205px;
    margin: auto;
    margin-bottom: 2px;
    -webkit-border-radius: 4px;
    -moz-border-radius: 4px;
    border-radius: 4px;
    box-shadow: 0 0 5px #ccc;
    -moz-box-shadow: 0 0 5px #ccc;
    -webkit-box-shadow: 0 0 5px #ccc;
    -moz-transition: 0.25s linear;
    -o-transition: 0.25s linear;
    -webkit-transition: 0.25s linear;
}

div.product div.detail:hover, div.product div.preview:hover {
    height: 254px;
}

div.product h2 {
    width: 100%;
    text-align: center;
    margin-bottom: 4px;
}

div.product span.price {
    color: #B32B2B;
    font-weight: bold;
    font-size: 14px;
    text-align: right;
    float: right;
}

div.product span.quantity {
    text-align: left;
    float: left;
}

Now, the idea is that when you mouse over either image it expands to fill the space of the other image, which shrinks in response. This can't be done in CSS with this markup, and not with anything I've tried.

I need to use JavaScript on each one of those divs for onmouseover and previousSibling to modify the CSS height. The problem is, things just don't want to work for me. Anyone have a solution?

A: 

For a start, for accessibility reasons you might want to use onFocus and onBlur, to take into account the fact that someone might not be using the mouse.

I don't know what JS you're using, but I'd nudge you toward JQuery. Docs on focus here.

Chris Cox
Sounds like a good plan… But this is a visual trick, so I'm not worried about that too much.
Dakota
+1  A: 

There are several javascript libraries that will make this an easy process. One of the options is jQuery and jQuery-UI (two seperate parts).

Something like this (updated after re-reading question):

<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"&gt;&lt;/script&gt;
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.5/jquery-ui.min.js"&gt;&lt;/script&gt;
<style type="text/css">
.big {height:250px;}
</style>
<script type="text/javascript">
    $(document).ready(function(){
        $('div.preview').each(function(){
            var curDiv = $(this);
            curDiv.hover(function(){curDiv.nextAll($('div.detail:first')).removeClass('big',1000);
            curDiv.addClass('big',1000);
            },function(){});
       });
        $('div.detail').each(function(){
            var curDiv = $(this);
            curDiv.hover(function(){curDiv.prevAll($('div.preview:first')).removeClass('big',1000);
            curDiv.addClass('big',1000);
            },function(){});
       });
    });
    </script>
    </head>
<body>
<div id="container">
<div class="preview big" style="background-color:red;width:50px;">&nbsp;</div><br>
<div class="detail" style="background-color:blue;width:50px;">&nbsp;</div>
</div>
</body>
</html>

Documentation:
jQuery hover, nextAll, prevAll
jQuery-UI addClass, removeClass

Explanation:
Once the document loads the script looks for divs with those classes and attached an OnHover handler. Inside the enter portion we are putting our add and remove classes - in this case we have one class that is the bigger size. We then use jquery to traverse the DOM to the next div with the class of detail and we add the big class to it. At the same time we remove the big class from our current div.

In add/remove classes is a duration in milliseconds option that gives the nifty look automatically.

In the detail part we do the exact same, but we traverse backwards to find the first preview div.

This works smoothly on Chrome, but on IE7 its slow - mainly because of IEs javascript engine.

WSkid
I get what's going on there, but it's way sketchy in Safari5. If you navigate to http://memeshirtz.com/shop/ I've got it working with purely CSS, but only for hover over the top div. CSS's lack of an inverse of the + operator is killing me. BTW, I'm not worried about IE7 support too much. if it works, great; if not, too bad.
Dakota
A: 

Okay, thanks to WSkid, I've got a solution working. Took only minor modifications. Final JavaScript:

<script type="text/javascript">
    $(document).ready(function(){
        $('div.preview').each(function(){
            var curDiv = $(this);
            curDiv.hover(function(){
                curDiv.nextAll($('div.detail:first')).addClass('short');
                curDiv.addClass('expand');
            },function(){
                curDiv.nextAll($('div.detail:first')).removeClass('short');
                curDiv.removeClass('expand');
            });
       });
        $('div.detail').each(function(){
            var curDiv = $(this);
            curDiv.hover(function(){
                curDiv.prevAll($('div.preview:first')).addClass('short');
                curDiv.addClass('expand');
            },function(){
                curDiv.prevAll($('div.preview:first')).removeClass('short');
                curDiv.removeClass('expand');
            });
       });
    });
</script>

Final CSS:

div.preview, div.detail {
    height: 205px;
}

div.expand {
    height: 248px;
}

div.short {
    height: 8px;
}
Dakota