Skip to content

Instantly share code, notes, and snippets.

@mbostock
Last active Feb 8, 2016
Embed
What would you like to do?
CSS3 Modal Button
license: gpl-3.0

A frequent challenge in user interface design is how to avoid accidental destructive actions. Destructive actions are non-undoable; for example, you might want to allow the user to delete a file, and once deleted the file cannot be restored. JavaScript provides some simple facilities for this, such as the confirm dialog box, but modal interfaces are annoying and disruptive: they force the user to confirm or cancel the prompt before doing anything else, even accessing another browser tab or window.

Taking a queue from the elegant solution in iOS, here is a modal button. The button serves as its own confirmation dialog by asking “Are you sure?” on the first click. If the user clicks again, then the action is performed. Otherwise, the user can simply mouseout to cancel. CSS3 transitions and animations (in WebKit) are used to draw visual attention to confirmation. Note that unlike popup dialog boxes, the user conveniently does not need to move the mouse to confirm the action.

One subtlety in the implementation: users may inadvertently double-click on the button. This should not be interpreted as confirmation, so the click handler forces a 500ms delay before allowing confirmation.

button {
background: #222 url(http://bost.ocks.org/button-overlay.png) repeat-x;
color: #fff;
text-rendering: optimizeLegibility;
text-shadow: 0 -1px 1px #222;
padding: 6px 10px 6px 10px;
border: 0;
border-bottom: 1px solid #222;
-moz-border-radius: 5px;
-moz-box-shadow: 0 1px 3px #999;
-moz-transition: background-color 250ms linear;
-webkit-border-radius: 5px;
-webkit-box-shadow: 0 1px 3px #999;
-webkit-transition: background-color 250ms linear;
}
button:hover {
background-color: #555;
}
button.confirm {
background-color: brown;
-webkit-animation-name: pulse;
-webkit-animation-iteration-count: infinite;
-webkit-animation-delay: 250ms;
-webkit-animation-duration: 1000ms;
-webkit-animation-direction: alternate;
}
@-webkit-keyframes pulse {
0% { background-color: brown; }
100% { background-color: red; }
}
<!DOCTYPE html>
<html>
<head>
<title>CSS3 Modal Button</title>
<style type="text/css">
@import url("button.css");
body {
margin: 0;
}
center {
position: relative;
top: 250px;
}
#button {
position: relative;
bottom: 1em;
font: 16px Helvetica Neue;
width: 200px;
}
</style>
</head>
<body>
<center>
<button id="button">Launch missile!</button>
</center>
<script type="text/javascript">
var button = document.getElementById("button");
button.addEventListener("click", confirm(button), false);
function confirm(button) {
var className = button.getAttribute("class"),
html = button.innerHTML,
then,
state = 0;
button.addEventListener("mouseout", function() {
if (state == 1) cancel();
}, false);
function cancel() {
state = 0;
button.setAttribute("class", className);
button.innerHTML = html;
}
return function() {
if (state) {
if (new Date() - then > 500) {
state = 2; // launched
button.innerHTML = "Missile launched!";
setTimeout(cancel, 5000); // reset
}
} else {
state = 1; // confirming
then = +new Date();
button.setAttribute("class", className + " confirm");
button.innerHTML = "Are you sure?";
}
};
}
</script>
</body>
</html>
@srigi
Copy link

srigi commented Jul 5, 2014

Live demo please

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment