JQuery animate border without moving div
Asked Answered
F

4

10

I want to animate a div by first making it's border thicker by 5px on mouseenter, then decreasing the border by 5px on mouseleave, the tricky part is that I don't want the div to look like it's moving (if you just animate the borders, the whole div will look like it shifts, not just the border getting thicker/thinner). I'm very close, but I'm stuck on the last part: mouseleave. What I have so far is:

$("#thumbdiv<%=s.id.to_s%>").bind({
            mouseenter: function(){
                $(this).animate({
                    borderRightWidth: "25px",
                    borderTopWidth: "25px",
                    borderLeftWidth: "25px",
                    borderBottomWidth: "25px",

                    margin: "-5px"
                }, 500);
            },
            mouseleave: function(){

                $(this).animate({
                    borderRightWidth: "20px",
                    borderTopWidth: "20px",
                    borderLeftWidth: "20px",
                    borderBottomWidth: "20px",

                    margin: "0px"
                }, 500);
            }
        });

I set the border to be 20px somewhere before this, and the margin is not set, so it's 0px. The div animates just fine on mouseenter, I can make the border thicker without the div actually moving out of place, but when the mouseleave is triggered, the div will first relocate itself to the position as if the "margin -5px" was never called, and then decrease it's border slowly and it seems like the "magin: '0px'" isn't actually being called.

I'm not sure if my description makes sense, I can put up a prototype if needed.

Favor answered 11/6, 2011 at 3:18 Comment(4)
I can't get a fiddle for that to work at all; it just goes nuts :-(Gomar
I found the answer, we can't animate shorthand values in JQuery yet, so the margin has to be marginTop, marginRight, marginBottom, and marginLeft. Will post my own answer when I can.Favor
Yup that does it :-) jsfiddle.net/25EsVGomar
The fiddle I posted work with shorthands in the class definition.Prenatal
F
6

So I finally found my own answer. To reiterate what I wanted:

  1. Circular divs
  2. Animation of increasing border width
  3. Don't want the div to look like it's "moving", only the borders should be the moving parts

I achieved this by animating BOTH the margin and border at the same time, because if you just animate the border, then the whole div will shift. But if you decrease the margin at the same time as increasing the border, you get the illusion of the div standing still.

Simply, we have a circular div:

#somediv {
    display: inline-block;
    height: 200px;
    width: 200px;
    border: solid 0px;
    vertical-align: middle;
    border-radius: 2000px;
    background-color: #ccc;
    margin: 0px;
}

And with a JQuery function like:

$(function(){
    $("#somediv").mouseover(function(){
    $(this).animate({"borderLeftWidth" : "5px",
                     "borderRightWidth" : "5px", 
                     "borderTopWidth" : "5px", 
                     "borderBottomWidth" : "5px",

                     "marginLeft" : "-5px",
                     "marginTop" : "-5px",
                     "marginRight" : "-5px",
                     "marginBottom" : "-5px"
                    }, 300);
    }).mouseout(function(){
        $(this).animate({"borderLeftWidth" : "0px", 
                         "borderRightWidth" : "0px", 
                         "borderTopWidth" : "0px", 
                         "borderBottomWidth" : "0px",

                         "marginLeft" : "0px",
                         "marginTop" : "0px",
                         "marginRight" : "0px",
                         "marginBottom" : "0px"
                        }, 300);
    });
});

We can achieve what we want.

Check out this fidddle as an example.

Now, another question up for debate is: We want to be able to only animate the border when the mouse is actually over the circular element inside the div, because if you mouseover the corners of the invisible div box, the circle will animate, but that's not what we want. I will post a link to how we can achieve this later.

Favor answered 16/6, 2011 at 1:26 Comment(0)
W
7

I didn't read the whole code, but I think there's a better aproach to do what you want.

It's the "outline" css property.

As the spec says: "...does not influence the position or size of the box... ...does not cause reflow or overflow..."

http://www.w3.org/TR/CSS21/ui.html#dynamic-outlines

The code would be something like this:

jQuery(#thumbdiv<%=s.id.to_s%>").mouseenter( function() {
jQuery(this).css("outlineStyle", "solid").animate({
    'outlineWidth': '5px'
}, 500);
}).mouseout( function() {
jQuery(this).animate({
    'outlineWidth': '0px'
}, 500).css("outlineStyle", "solid");
});

Note:

OK, I edited the @Nabab "Fiddle" (I didn't know about that service) and I got this: http://jsfiddle.net/EbTms/ ...I think it works.

Weywadt answered 11/6, 2011 at 4:2 Comment(1)
I would say this is acceptable, but it won't work 100% of the time. Because what I have actually are circular divs. If you animate the outlineStyle, it makes the outline of the invisible box containing the div to be thicker, so if you have any border-radius, this would not look right, and especially in my case where my div is a circle. Good answer though!Favor
F
6

So I finally found my own answer. To reiterate what I wanted:

  1. Circular divs
  2. Animation of increasing border width
  3. Don't want the div to look like it's "moving", only the borders should be the moving parts

I achieved this by animating BOTH the margin and border at the same time, because if you just animate the border, then the whole div will shift. But if you decrease the margin at the same time as increasing the border, you get the illusion of the div standing still.

Simply, we have a circular div:

#somediv {
    display: inline-block;
    height: 200px;
    width: 200px;
    border: solid 0px;
    vertical-align: middle;
    border-radius: 2000px;
    background-color: #ccc;
    margin: 0px;
}

And with a JQuery function like:

$(function(){
    $("#somediv").mouseover(function(){
    $(this).animate({"borderLeftWidth" : "5px",
                     "borderRightWidth" : "5px", 
                     "borderTopWidth" : "5px", 
                     "borderBottomWidth" : "5px",

                     "marginLeft" : "-5px",
                     "marginTop" : "-5px",
                     "marginRight" : "-5px",
                     "marginBottom" : "-5px"
                    }, 300);
    }).mouseout(function(){
        $(this).animate({"borderLeftWidth" : "0px", 
                         "borderRightWidth" : "0px", 
                         "borderTopWidth" : "0px", 
                         "borderBottomWidth" : "0px",

                         "marginLeft" : "0px",
                         "marginTop" : "0px",
                         "marginRight" : "0px",
                         "marginBottom" : "0px"
                        }, 300);
    });
});

We can achieve what we want.

Check out this fidddle as an example.

Now, another question up for debate is: We want to be able to only animate the border when the mouse is actually over the circular element inside the div, because if you mouseover the corners of the invisible div box, the circle will animate, but that's not what we want. I will post a link to how we can achieve this later.

Favor answered 16/6, 2011 at 1:26 Comment(0)
W
3

OK, this became challenging.

Having in mind that your divs are circular:

Use a wrapper (another div) for every one of your divs, bigger than them, center your divs in the wrappers (vertically and horizontally) as "inline-block" and then animate them.

Every border has to be animated independently to work well ("borderLeftWidth", "borderRightWidth", etc. instead of just "borderWidth"). It's a not very well documented bug in jQuery: http://bugs.jquery.com/ticket/7085 (it was hard to discover).

It seems working: http://jsfiddle.net/y4FTf/2/

HTML

<div class="wrapper">
<div class="content">Hello World!
</div>
</div>
<div class="wrapper">
<div class="content">Foo Bar
</div>
</div>

CSS

.wrapper {
width: 210px;
height: 210px;
line-height: 210px;
text-align: center;
padding: 0px;
}
.content {
display: inline-block;
height: 200px;
width: 200px;
border: solid 0px;
vertical-align: middle;
border-radius: 2000px;
background-color: #ccc;
margin: 0px;
}

Javascript

$(function(){
$(".content").mouseover(function(){
    $(this).animate({"borderLeftWidth" : "5px",
                     "borderRightWidth" : "5px",
                     "borderTopWidth" : "5px",
                     "borderBottomWidth" : "5px"
                    }, 300);
}).mouseout(function(){
        $(this).animate({"borderLeftWidth" : "0px",
                         "borderRightWidth" : "0px",
                         "borderTopWidth" : "0px",
                         "borderBottomWidth" : "0px"
                        }, 300);
});
});
Weywadt answered 14/6, 2011 at 2:43 Comment(1)
This is a very good answer, I'm not sure if this is a better answer than animating the margin. I would argue against this because of the extra parts, and the fact that the div that wraps around the inner div must be at least bigger than how much you want to animate the border by. To plug this into a useful application might be more difficult. Compare it to my answer and see what you think.Favor
P
0

Interesting issue... It works better by switching classes, but still it's not very smooth:

http://jsfiddle.net/dzTHB/13/

Prenatal answered 11/6, 2011 at 3:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.