Arnauld
Arnauld

Reputation: 6130

Click event not firing because of a "pressed button" effect with :active pseudo-class

I'm trying to animate a div when it gets clicked, using a css ":active" pseudo-class. The div gets shifted by 10 pixels to the right and 10 pixels down:

#myButton:active {
    margin:10px 0 0 10px;
}

See complete example here: http://jsfiddle.net/WdABS/

The problem is that if you click on the top or left border of the div (in red in the jsFiddle example), the mouse pointer is not over the div anymore when the button is released. So, neither mouseup nor click are fired.

Technically speaking, this behavior makes perfect sense. However, this is not what the final user would expect and I don't know how to fix it in a clean and easy way. I tried to put a parent container around the moving div and catch the click event from it, but it appeared to just make things more complex and didn't work very well either.

Thanks for reading!

Upvotes: 9

Views: 1192

Answers (2)

ScottS
ScottS

Reputation: 72261

Pure CSS: Use a Psuedo-Element

This is working for IE8+, Firefox, and Chrome (all those were tested). See this fiddle.

#myButton:active {
    margin:10px 0 0 10px;
}
#myButton:active:before {
    content: '';
    position: absolute;
    top: -20px; /* border plus shift amount */
    right: 0;
    bottom: 0;
    left: -20px; /* border plus shift amount */
}

Your #myButton will need either position: relative or absolute so the :before element locates itself correctly.

Pure CSS: Shift with the Border Itself (CSS3)

If the button did not already have a border on it, then using the border property itself (with a transparent color) and background-clip (to not have the button color overlap the border), you can get the same functionality. See this fiddle.

#myButton:active {
    border-top:10px transparent solid;
    border-left:10px transparent solid;
    background-clip: padding-box;
}

Upvotes: 5

Blake Plumb
Blake Plumb

Reputation: 7199

So my idea is to bind the mouseup event handler to the document when the mousedown event handler is fired. Then you can run the code you wanted to run for mouseup and click. Here is a fiddle showing this.

$(document).ready(function() {
    $('#myButton').mousedown(function() { 
        debug('button down'); 
        $(document).on('mouseup', function(){
            $(document).off('mouseup');
            debug('button up');
            debug('click'); 
        });
    });
});

function debug(msg) {
    $('#debug').append('[' + msg + ']');
}

Upvotes: 3

Related Questions