Reputation: 1245
I need to make an animated border on a div. I figured out how to do it with a canvas overlay and some javascript, but it is super clunky right now. Is there anyway to accomplish this same animation with CSS animation? Please see this jsfiddle http://jsfiddle.net/L8ov2fk0/7/
EDIT: A lot of great answers! Some I found working on this and others not. The problem I kept running into is that the exact animation in my fiddle is what the customer wants, and I was never able to tweak anything I found into something even close to that.
And my code
HTML
<div id="buttona" class="button" >Button A</div>
<div id="buttonb" class="button" >Button B</div>
<canvas id="bordera"></canvas>
<canvas id="borderb"></canvas>
CSS
.button{
padding:10px;
border:1px solid red;
}
#buttona{
position:absolute;
}
#buttonb{
position: absolute;
left:100px;
}
#bordera{
position:absolute;
width:81px;
height:40px;
pointer-events:none;
}
#borderb{
position: absolute;
left:100px;
width:80px;
height:40px;
pointer-events:none;
}
Javascript
$('body').on('click', '#buttona', function (){
DrawButtonBorder("bordera");
});
$('body').on('click', '#buttonb', function (){
DrawButtonBorder("borderb");
});
/*animated borders*/
function Point(x, y, width, height, half) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.half = half;
}
Point.prototype.increment = function () {
if (this.half == "upper") {
if (this.y > 0 && this.x == 0)
this.y--;
else if (this.y == 0 && this.x < this.width)
this.x++;
else if (this.y < this.height / 2 && this.x == this.width)
this.y++;
}
else {
if (this.y < this.height && this.x == 0)
this.y++;
else if (this.y == this.height && this.x < this.width)
this.x++;
else if (this.y > this.height / 2 && this.x == this.width)
this.y--;
}
}
animatedBorder = null;
borderDrawn = "";
function DrawButtonBorder(id) {
if (borderDrawn != id) {
borderDrawn = id;
CancelButtonBorder();
ClearButtonBorder("bordera");
ClearButtonBorder("borderb");
var speed = 1;
var canvas = document.getElementById(id);
var context = canvas.getContext('2d');
var style = getComputedStyle(canvas);
var width = parseInt(style.width.replace("px", ""));
width = parseInt(width / speed);
var height = parseInt(style.height.replace("px", ""));
height = parseInt(height / speed);
context.canvas.width = width;
context.canvas.height = height;
var middle = parseInt(height / 2);
var a = new Point(0, middle, width, height, "upper");
var b = new Point(0, middle, width, height, "lower");
function draw() {
//upper half
context.strokeStyle = '#D7A95A';
context.moveTo(a.x, a.y);
a.increment();
context.lineTo(a.x, a.y);
context.stroke();
//lower half
context.strokeStyle = '#D7A95A';
context.moveTo(b.x, b.y);
b.increment();
context.lineTo(b.x, b.y);
context.stroke();
if (a.y > middle && b.y < middle)
return;
animatedBorder = requestAnimFrame(draw);
}
draw();
}
}
function ClearButtonBorder(id) {
var canvas = document.getElementById(id);
var context = canvas.getContext('2d');
context.clearRect(0,0,context.canvas.width, context.canvas.height);
}
function CancelButtonBorder() {
cancelAnimFrame(animatedBorder);
}
var requestAnimFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};
var cancelAnimFrame = window.cancelAnimationFrame ||
window.webkitCancelAnimationFrame ||
window.mozCancelAnimationFrame;
Upvotes: 2
Views: 2070
Reputation: 106058
you could use background image or gradient and background-size.
.button {
padding:0.25em;
display:inline-block;
border:none;
background-color:;
background:
linear-gradient(to top,red,red) 0 100%,
linear-gradient(to right,red,red)100% bottom,
linear-gradient(to top,red,red) bottom right ,
linear-gradient(to top,red,red) top right lightgray;
background-size: 3px 0%, 0% 3px,3px 0%, 0% 3px;
background-repeat:no-repeat,no-repeat,no-repeat,no-repeat;
transition:1s;
}
.button:hover {
background-size: 3px 100%, 100% 3px,3px 100%, 100% 3px;
<button id="buttona" class="button" >Button A</button>
<button id="buttonb" class="button" >Button B</button>
or animation made from shadow over background
.button {
padding:0.25em;
display:inline-block;
border:none;
background-color:;
background:
linear-gradient(to top,red,red) 0 100%,
linear-gradient(to right,red,red)100% bottom,
linear-gradient(to top,red,red) bottom right ,
linear-gradient(to top,red,red) top right lightgray;
background-size: 3px 100%, 100% 3px,3px 100%, 100% 3px;
background-repeat:no-repeat,no-repeat,no-repeat,no-repeat;
box-shadow:inset 0 0 0 0 lightgray;
transition:1s;
}
.button:hover {
box-shadow:inset 5em 2em 0 0 lightgray
<button id="buttona" class="button" >Button A</button>
<button id="buttonb" class="button" >Button B</button>
other CSS examples : http://codepen.io/gc-nomade/pen/IGliC http://codepen.io/gc-nomade/pen/bhxAL or http://codepen.io/gc-nomade/pen/pKwby
Upvotes: 3
Reputation: 34180
you can use border-image css style:
#myDIV {
border:15px solid transparent;
width:250px;
padding:10px 20px;
border-image:url(http://www.w3schools.com/cssref/border.png) 30 30 stretch;
transition: .2s;
}
#myDIV:hover{
border-image:url(http://www.w3schools.com/cssref/border.png) 0 0 stretch;
}
Upvotes: 1
Reputation: 123428
if you turn your div into actual <button>
elements you could achieve this effect with :focus
pseudoclass
Example : http://codepen.io/anon/pen/QwPxYm
<button id="buttona" class="button">Button A</button>
<button id="buttonb" class="button">Button B</button>
CSS
.button {
padding:10px;
background: none;
outline: none;
border:1px solid red;
}
#buttona, #buttonb {
position:absolute;
}
#buttonb {
left:100px;
}
.button:after {
content: "";
position: absolute;
bottom: -4px;
left: 0;
display: block;
width: 0;
height: 0;
border-top: 1px #ccc solid;
transition: width 3s;
}
.button:focus:after {
width: 100%;
}
Upvotes: 1
Reputation: 86
Create a div element to act as the border, place it in relation to the element that you want the animated border to happen to.
.border{
height: 10px; //Or whatever height for thickness
background-color: black; //Or whichever color
visibility: hidden; //So that it takes up space
}
When the button is clicked add this class to the border element and turn its visibility to visible
.extend{
animation: expand 3s;
-webkit-animation: expand 3s;
}
Include this action in the css
/* Chrome, Safari, Opera */
@-webkit-keyframes expand {
from {width: 0%;}
to {width: 100%;}
}
/* Chrome, Safari, Opera */
@keyframes expand {
from {width: 0%;}
to {width: 100%;}
}
Upvotes: 1