Reputation: 1027
I'm trying to animate a button with two states: saved and unsave. When it goes from save -> unsave, it should slowly expand and add the next text. It should do the reverse when going from unsave to save. I have the following fiddle:
https://jsfiddle.net/4x0svuLd/2/
My problem right now is that even though I have designated a width transition, it seems to ignoring it. My issue is this button could have arbitrary text, thats just boolean in nature, so I can't know the exact width beforehand. I just need to it animate to the proper text width, whatever that text is.
HTML:
<div class="button" >
<text class="text"> Save </text>
</div>
CSS:
.button {
background-color: transparent;
border: 1px solid;
border-color: black;
border-radius: 6px;
color: black;
cursor: pointer;
display: inline-block;
font-size: 14px;
margin-top: 8px;
outline-style: none;
padding: 6px 10px;
text-align: center;
transition: width 2s cubic-bezier(0.23, 1, 0.32, 1);
width: auto;
}
.button-depressed {
color: white;
background-color: #ADD8E6;
border-color: transparent;
}
JS:
var isSaved = false
function doSaveAnimation() {
var button = document.getElementsByClassName("button")[0];
button.classList.add("button-depressed");
setTimeout(function() {
button.innerHTML = "Unsave";
}, 80);
}
function doUnsaveAnimation() {
var button = document.getElementsByClassName("button")[0];
button.classList.remove("button-depressed");
setTimeout(function() {
button.innerHTML = "Save";
}, 80);
}
function animate(){
if (isSaved) {
doUnsaveAnimation();
} else {
doSaveAnimation();
}
isSaved = !isSaved;
}
document.getElementsByClassName("button")[0].addEventListener("click", animate);
Upvotes: 1
Views: 2021
Reputation: 7473
You could calculate the width of the text that you are setting to the button, and set calculated width to the button accordingly;
Once right away, and then each click.
In this post you have several examples of how to determine width of text, i have adapted one of those to the solution below:
var isSaved = false;
var button = document.getElementsByClassName("button")[0];
button.style.width = getWidthOfText("Save", "14","sans-serif") +20+ "px";
function getWidthOfText(txt, fontsize) {
var c = document.createElement('canvas');
var ctx = c.getContext('2d');
ctx.font = fontsize + 'px' ;
var length = ctx.measureText(txt).width;
return length;
}
function doSaveAnimation() {
button.classList.add("button-depressed");
setTimeout(function() {
button.innerHTML = "Unsave";
console.log(button.offsetWidth);
}, 120);
button.style.width = getWidthOfText("Unsave", "14") +20+ "px";
}
function doUnsaveAnimation() {
button.classList.remove("button-depressed");
setTimeout(function() {
button.innerHTML = "Save";
console.log(button.offsetWidth);
}, 120);
button.style.width = getWidthOfText("Save", "14") +20+ "px";
}
function animate() {
if (isSaved) {
doUnsaveAnimation();
} else {
doSaveAnimation();
}
isSaved = !isSaved;
}
document.getElementsByClassName("button")[0].addEventListener("click", animate);
.button {
background-color: transparent;
border: 1px solid;
border-color: black;
border-radius: 6px;
color: black;
cursor: pointer;
display: inline-block;
font-size: 14px;
margin-top: 8px;
outline-style: none;
padding: 6px 10px;
text-align: center;
transition: 1s cubic-bezier(0.23, 1, 0.32, 1);
text-align:center;
}
.button-depressed {
color: white;
background-color: #ADD8E6;
border-color: transparent;
transition: 1s cubic-bezier(0.23, 1, 0.32, 1);
}
<div class="button">
<text class="text">Save</text>
</div>
Upvotes: 1
Reputation: 607
One way to do this without javascript is to use max-width instead of width.
https://jsfiddle.net/LjchoLqt/
.button {
transition: max-width 2s cubic-bezier(0.23, 1, 0.32, 1);
width: auto;
max-width: 2em;
}
.button-depressed {
max-width:4em;
}
You'll need to pay around with the values to make sure it doesn't cut off. This isnt an ideal solution though, especially if you don't control the content (eg it's populated by a CMS)
Upvotes: 1