Justian Meyer Justian Meyer - 7 days ago 4
CSS Question

Getting images to position/layer properly with CSS

Our group is trying to create a slide-out option panel for products to be sold on our site.

For some reason, CSS is acting up on us and it's a pain to get our images to layer properly. In the past, z-index did the trick, but now we have to test random stylings and workarounds just to get remotely what we're looking for.

At the moment, we have a relative div with absolute content, which should already be raising a red flag for you layout designers.

Everything functions as it should, but why isn't this working right? I would provide an example from our ftp, but for some reason my internet is acting up and I can't get the content uploaded.

For now, here's our source:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link type="text/css" href="css/ui-lightness/jquery-ui-1.8.5.custom.css" rel="Stylesheet" />
<script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.8.5.custom.min.js"></script>
<script type="text/javascript">
function move(name){
if (name.style.left == "500px")
{
$(name).animate({left: 0}, 300);
}
else if(name.style.left == "0px")
{
$(name).animate({left: 500}, 300);
}
}
</script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>JQuery Test</title>
</head>
<body>
<div class="item">
<div id="top" style="z-index:1; position: absolute; top:0px; left:0px; width:500px; height:375px;">
<img src="images/car1.jpg" />
</div>
<div id="bottom" style="z-index:-1; position:absolute; top: 0px; left:0px; width:550px; height:375px;">
<img src="images/car2.jpg" />
<div class="optionsExpandButton" style=" position:absolute; left: 500px; width:50px; height:375px; background-color: #000; z-index:inherit; float:left" onclick="move(bottom);"></div>
</div>
</div>
</body>
</html>


EDIT:

Forgot to mention the main issue.

Typically when we create our z-indexes, the images will end up below each other instead of beneath each other.

Ex:

-------------------------
| z-index: 1 | <- img 1
-------------------------
| z-index: -1 | <- img 2
-------------------------

Answer

Edit:

After discussion I realized you wanted a slide right / left solution. Here is that solution, followed by some more general advice.

First the HTML:

<div class="item">
    <div id="top">
        <img src="http://img814.imageshack.us/img814/8089/car1j.jpg" alt="..." />
    </div>
    <div id="bottom">
        <img src="http://img178.imageshack.us/img178/3779/car2dy.jpg" alt=".." />
    </div>
    <div class="optionsExpandButton"></div>    
</div>

I had some positioning and clicking issues with .optionsExpandButton inside #bottom, so I put it outside. I'm sure you could actually do it either way.

Anyway, notice the complete lack on inline CSS or JS. Dont' forget to add your alt tags for accessibility!

Now let's set the positioning up so we can slide left to right correctly.

We'll position .item absolutely and the 3 divs inside relatively.

This means that #top is at left:0, top:0. Now #bottom would be below that at left:0, top:375, but we want it right on #top so #bottom will get left:0, top:-375. The expand div would be at left:0, top:750, but we want it at the height of #top and to the right of it, since #top is 500 wide that make the expand button at left:500, top:-750:

The CSS

img, div { border:0; padding:0; margin:0; }
div.item {
    position: absolute; /* This could also be relative */ }
#top {
    z-index:1;
    position: relative; 
    top:0px; left:0px; 
    width:500px; height:375px; }
#bottom {
    z-index:-1; 
    position:relative; 
    top: -375px; left:0px; 
    width:550px; height:375px; }
div.optionsExpandButton {  
    position:relative;
    width:50px; height:375px; 
    top: -750px; left: 500px;
    background-color: #000; 
    z-index:999; }

Now, let's make use of .toggle() for sliding right than left instead of an awkward if statement:

The JS:

$(function() {
    $(".optionsExpandButton").toggle(function() {
        $(this).animate({left: '+=425' });
        $("#bottom").animate({left: '+=425' });
    }, function() {
        $(this).animate({left: '-=425' });        
        $("#bottom").animate({left: '-=425' });    
    });
});
​

Try it out at this jsFiddle

(on its own page)

Below is the old answer:


I would advise against inline JS and inline CSS. Keep the content separate from the functionality and styling.

You might find it much easier to just list all your divs without positioning, and then position everything with jQuery. This also applies to your z-index.

It looks like you want to show one image, and on click slide down another image.

I'll show you a way to do this quite simply without worrying about CSS. The method degrades nicely if a user has JS disabled in that both images will be visible without JS, which is not true if you rely on setting CSS z indices and position one image above the other.

First I'll show you how to do one slider with IDs, similar to how you have. Then I'll show you how to put as many different image sliders as you want on one page using classes.


One slider with IDs:

So, first, I would set up the HTML in a way that makes sense without JS. Just one image after the other. I would make no JS or CSS inline. Don't forget about your alt tags for accessibility.

<div class="item">
       <div id="top">
               <img src="images/car1.jpg" alt="..." />
       </div>
       <div id="bottom">
               <img src="images/car2.jpg" alt="..." />                   
       </div>

       <!-- Don't nest this button in either top or bottom! -->
       <div id="expand">+ Expand</div>
</div>

Now the jQuery can hide image #2 when the page is ready and slide it up and down when the expane div is pressed. You can use classes for the button, but that's a little more complicate, so first I'll show how to do it with an id:

$(function() {  // <== doc ready

    $("#bottom").hide();          // Hide the second image

      // Define what happen on button click
    $("#expand").click(function() {
        var $this = $(this);   // This is for efficiency

          // Toggle the second image sliding up or down
        $("#bottom").slideToggle();

          // Toggle the writing in the button.
        $this.html() == "+ Expand" ? 
            $this.html("- Contract") :
            $this.html("+ Expand");
    });
});​

Try it out with the jsFiddle example



Many sliders with classes:

Now let's generalize and use just classes with divs set up a certain way.

HTML:

<div class="item">
       <div class="top"><img src="img1a"  alt="..." /></div>
       <div class="bottom"><img src="img2a"  alt="..." /></div>
       <div class="expand">+ Expand</div>
</div>
<div class="item">
       <div class="top"><img src="img1b"  alt="..." /></div>
       <div class="bottom"><img src="img2b"  alt="..." /></div>
       <div class="expand">+ Expand</div>
</div>
...

jQuery

$(function() {
    $("div.item div.bottom").hide();
    $(".expand").click(function() {
        var $this = $(this);
        $this.prev().slideToggle();
        $this.html() == "+ Expand" ? 
            $this.html("- Contract") :
            $this.html("+ Expand");
    });
});​

Try it out with this jsFiddle



References: