Hello guys, I hope you can clarify something for me please.
I was looking into carousels, found an excellent one and replicated in my code (for reference this is the one I looked at, it’s really good and easy to understand https://tutsplus.com/lesson/the-obligatory-slider/).
Anyway, I have implemented that and I thought I’d do my own controllers, so I grabbed a few images and positioned them absolutely inside the container with the pictures (screenshot attached for reference).
fe2b66806a64f4f99ab98b863add69cc

Let’s have a look at some code.
This is the HTML structure. the carouselWrapper div contains the images and the controllers

<body>
<!-- carousel -->
<div class="carouselWrapper">
<ul>
<li><img src="image1.jpg"></li>
<li><img src="image2.jpg"></li>
<li><img src="image3.jpg"></li>
<li><img src="image4.jpg"></li>
</ul>
<div class="sliderNav">
<button data-dir="prev" class="left transparent"></button>
<button data-dir="next" class="right transparent"></button>
</div>
</div>

<!-- end of carousel -->

</body>

Here is the relevant CSS:
Nothing too involved, the carouselWrapper has default position:static.

.carouselWrapper{
    width:500px; /*size of the pix*/
    /* height:375px; */
    overflow:hidden;
    margin:0 auto;
}

.carouselWrapper ul{
    list-style-type: none;
    width:10000px;  

}
 .sliderNav button.right{
    background:url("controllersRight.jpg") no-repeat 0 0;
    width:48px;
    height:39px;
}
.sliderNav button.left{
    background:url(controllersLeft.jpg) no-repeat 0 0;
    width:48px;
    height:39px;
}
 .sliderNav button.left, .sliderNav button.right{
    position:absolute;
    border:0;
}

And here is the relevant part of the script that positions the two controllers. Again, nothing fancy: I get all the widths and heights I need and then update the top and left value of both the controllers.

/*positioning the controllers*/
    var containerWidth = $(".carouselWrapper").width();//get width of
    var containerHeight = $(".carouselWrapper").height();
    var controllerWidth = $(".sliderNav button").width();
    var controllerHeight = $(".sliderNav button").height();
    var $controllerPrev = $("button.left"); 
    var $controllerNext = $("button.right");
    var imageContainerPosLeft = $(".carouselWrapper").offset().left;
    var imageContainerPosTop = $(".carouselWrapper").position().top;
    var controllersTop = (containerHeight / 2) - controllerHeight;
    var controller1Left = imageContainerPosLeft;
    var controller2Left = (imageContainerPosLeft + containerWidth ) - controllerWidth ;
    //set the position of the two controller dynamically
    $controllerPrev.css({
        "top":controllersTop,
        "left":controller1Left      
    });
    $controllerNext.css({
        "top":controllersTop,
        "left":controller2Left
    });

    console.log("width of picture container is " + containerWidth + " controller width " + controllerWidth + " left pos is  "+ imageContainerPosLeft + " top pos is " + imageContainerPosTop + " container height " + containerHeight + " new controller top position: " +  controllersTop + " controller1 left pos is " + controller1Left + "second controller left pos is " + controller2Left + " controller height is " + controllerHeight);

I would like to draw your attention to this line:var imageContainerPosLeft = $(".carouselWrapper").offset().left; Here I am using offset() and it works fine in every browser, but my first choice was position().left instead. When I used position() I noticed that only Firefox, IE7 and 8 and opera worked ok. Safari, Chrome, IE9 and 10 made a mess, the controllers were shifted to the left of the page. I run a few console logs and found out that the culprit was actually that position().left which was returning a value of 0 and I was expecting something like 710px. So I replaced it with offset().left and now it is all fine in every browser. Now, I looked at the API for both methods and it says that

The .position() method allows us to retrieve the current position of an element relative to the offset parent.

Funnily enough the parent of carouselWrapper is the body tag which has no explicit position declared. SO my questions are:

1)Is that the reason why the position method failed?
2)If so why did it fail only in certain browsers and not in others? I mean even IE7 and 8 got it right!
3)As an alternative, rather than fixing the problem using offset().left, would it be fair to say that I could have fixed it by adding position:relative to the body tag?

Recommended Answers

All 8 Replies

Sorry, this thing got really interesting. I built a much simpler page with just on div in the middle:
HTML

    <!DOCTYPE html>
    <html>
        <head>
            <link rel="stylesheet" type="text/css" href="carouselStyle.css">
            <title>Test</title>
            <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
            <script type="text/javascript" src="script.js"></script>
        </head>
        <body>
            <div class="bigBox"></div>
        </body>
    </html>

CSS

*{
    margin:0;
    padding:0;
}


.bigBox{
    width:600px;
    height:300px;
    background-color:yellow;
    margin:0 auto;
}

Script

$(document).ready(function(){
    //alert("ohi");
    var imageContainerPosLeftOffset = $(".bigBox").offset().left;
    var imageContainerPosLeftPosition = $(".bigBox").position().left;
    $(".bigBox").html("Offset is " + imageContainerPosLeftOffset + " position is " + imageContainerPosLeftPosition);
});

Same problem here. Position().left returns 0 in IE9, 10, and Chrome, whereas it returns a value other than 0 (the same as offset().left)in any other browser. So is this a bug with the browsers, in that they can't understand position().left?

Interesting.. i haven't spent much time on this before, but looking at this now, it does seem confusing. I was reading over the document on the jQuery site for the position().

http://api.jquery.com/position/

This doesnt seem like a bug though. it may be that it is simply not clear. According to the site... "The .position() method allows us to retrieve the current position of an element relative to the offset parent."

I see that the method returns 0 in your example. However, if I add padding to the body element, say 5px, the left property then returns 5 for the position().left on the bigBox.

So we need clarity on what this means exactly.... "retrieve the current position of an element relative to the offset parent". What is offset parent signify?

"The .position() method allows us to retrieve the current position of an element relative to the offset parent."

Means: The current position of the nested element edge relative to its parent element edge.

If element wrapper has padding = 10px, and the nested element has style.left = 13px, plus margin-left = 30px, -its (the nested element) position().left will be = 23. (Its margin will not be taken into account, because the nested element edge is 30px outwards).

Whereas, the offset left will always report the distance from the left edge of the document. Meaning that if you are aiming to move/reposition the element relative to its immediate wrapper, you'd be using position left.

Regards.

Thanks. I guess the confusion comes in on why the bigBox div comes back with a position.left of zero when it's clearly centered on the screen and it's not 0px left of the left most position of the parent, the body element. . Based on your explanation the div is in the correct position of 0 because there is no padding in the body element that is affecting the bigBox. It doesn't matter that the width of the bigBox places it in the center due to the left/right auto margin. Without the left/right auto margin, the bigBox div would be displayed all the way to the left in position 0.

Makes sense. I think.

thanks guys, yes it makes sense, but then again, why do browsers interpret this in a different way? I mean clearly chrome and any browser returning 0 when position() is called ignore the margins, but firefox and the other ones that do not return 0, take the margins into account and add them to the calculation of the value returned by position().

I didn't try with different browsers but could the slight differences be due to default user agent margin and padding styles being applied?

@Violet,
generally spoken -it means that offset is more reliable than position in a mixed web environment.

I'm not sure I can recall well, but as I remember, the possition specs have changed in later standards.

OK, thanks guys :-)!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.