Question

I've built a slideshow using the jquery Cycle plugin, each image spans the width of the page (liquid layout) and has an accompanying caption. I need the caption to sit over the image and hence I'm using position: absolute in my CSS. However, as per some blog posts and Stack answers I've read, Cycle overides CSS positioning, and the caption is pushed below the image. I've used !important in my CSS but that doesn't work either.

Here is my Jquery:

$(document).ready(function(){
    $(".slideshow").cycle({
        fx: 'scrollRight',
        next: '#right-arrow',
        timeout: 0,})
    $(".slideshow").cycle({
        fx: 'scrollLeft',
        next: '#left-arrow',
        timeout: 0,})
    })  

and my HTML. Note that I've included the caption in a separate DIV element than the image. Putting it in the same DIV was making the caption a separate slide in the show.

<div class = "slideshow">
    {% for photo in gallery %}
        <img id = "gallery-image" src ="{{ photo.image.url }}"/>
    {% endfor %}    
</div>  

<div class = "slideshow">
    {% for photo in gallery %}
    <div id = "caption-container">{{ photo.caption }}</div> 
    {% endfor %}
</div>

and finally my CSS:

#copy-container {
        position: absolute;
        top: 350px;
        width: 7%;
        right: 3%;
        z-index: 10;
        background-color: red;} 

Here is what is showing up using Chrome Inspect Elements:

Computed Styles:
    display: block;
    height: 54px;
    overflow-x: hidden;
    overflow-y: hidden;
    position: relative;
    width: 101px;

Styles:
    :active :hover
    :focus  :visited
    element.style {
    position: relative;
    width: 101px;
    height: 54px;
    overflow: hidden;
    }

Matched CSS Rules
    user agent stylesheetdiv {
    display: block;
    }
    Inherited from body
    body {
    font: arial;
    }

HTML from Chrome Dev tools...

<div class="slideshow" style="position: relative; width: 154px; height: 36px; overflow: hidden;">


        <div id="copy-container" style="position: absolute; top: 0px; left: 0px; display: block; z-index: 3; opacity: 1; width: 154px; height: 36px;">
            <div id="client-container">client:American Express</div>

            <div id="caption-container">WOOOHOOOO</div>
        </div>  


        <div id="copy-container" style="position: absolute; top: 0px; left: 154px; display: none; z-index: 2; opacity: 1; width: 101px; height: 36px;">
            <div id="client-container">client:Selfridges</div>

            <div id="caption-container">nbew image</div>
        </div>  

</div>      
Was it helpful?

Solution

I'll note first that, especially when you're first learning new things, it's best to give every bit of information you have. It's easier for those with more experience to help you if they can see the whole picture.

This is pulling from koala_dev's answer. After figuring out what your requirements are I put together a fiddle: http://jsfiddle.net/rCsHG/

A couple of things to note:

  1. You have to get rid of those id attributes, as already mentioned

  2. You need to wrap your entire slideshow (which is actually 2 slideshows) in a wrapper. You can then position:relative the main wrapper, and position:absolute the slideshows.

  3. You should have separate classes for each slideshow; I know it was working for you, but it's just good practice.

So, your HTML will look like this:

<div class="slideshow-wrapper">
  <div class = "slideshow-img">
    {% for photo in gallery %}
      <img class = "gallery-image" src ="{{ photo.image.url }}"/>
    {% endfor %}    
  </div>  

  <div class = "slideshow-caption">
    {% for photo in gallery %}
      <div class = "caption-container">{{ photo.caption }}</div> 
    {% endfor %}
  </div>
</div>

Then CSS:

.slideshow-wrapper {
  position: relative;
}
.slideshow-img, .slideshow-caption {
  position: absolute;
  width: 100%;
}
.slideshow-caption {
  top: 0;
}

And, finally, JavaScript:

$(document).ready(function(){
var _timeout = 100; // when using the same value in multiple places, consider storing it in a variable for easy modification
$(".slideshow-img").cycle({
    fx: 'scrollRight',
    // add back in your prev/next
    timeout: _timeout,})
$(".slideshow-caption").cycle({
    fx: 'scrollLeft',
    // add back in your prev/next
    timeout: _timeout,})
})  

OTHER TIPS

You should have everything inside one container but use a div for each slide, also you need to use classes instead of ids since ids should be unique in a HTML page

<div class = "slideshow">
    {% for photo in gallery %}
    <div class="slide">
        <img class="gallery-image" src ="{{ photo.image.url }}"/>
        <div class="caption">{{ photo.caption }}</div> 
    </div>
    {% endfor %}    
</div> 

The position your caption using CSS

.slide{
    position: relative;
}

.caption{
    position: absolute;
    top: 350px;
    width: 7%;
    right: 3%;
    background-color: red;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top