Make the button come alive by expanding to reveal fresh text

I am currently working on animating a button with two states: saved and unsaved. The goal is for the button to slowly expand and show the next text when transitioning from saved to unsaved, and vice versa. Below is the link to my code:

https://jsfiddle.net/4x0svuLd/2/

My issue lies in the fact that even though I have set up a width transition, it appears to be ignored. Since the button could potentially contain any text (as long as it's boolean in nature), I cannot pre-determine the exact width beforehand. Therefore, I need the animation to adjust dynamically based on the width of the text.

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);

Answer №1

If you want to dynamically adjust the width of a button based on the text content, you can calculate the width of the text and then set it as the button's width. This can be done initially and also on each subsequent click.

  • Consider applying transitions to all properties, not just the width, to achieve smoother animations.

Check out this post for various examples on how to determine the width of text. Here is an adapted solution:

var isSaved = false;
var button = document.getElementsByClassName("button")[0];
button.style.width = getWidthOfText("Save", "14","sans-serif") + 20 + "px";

function getWidthOfText(txt, fontsize) {
  var canvas = document.createElement('canvas');
  var context = canvas.getContext('2d');
  context.font = fontsize + 'px';
  var length = context.measureText(txt).width;
  return length;
}

function doSaveAnimation() {
  button.classList.add("button-pressed");
  setTimeout(function() {
    button.innerHTML = "Unsave";
    console.log(button.offsetWidth);
  }, 120);
  button.style.width = getWidthOfText("Unsave", "14") + 20 + "px";
}

// Add more functions here as needed

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);
}
.button-pressed {
  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>

Answer №2

To achieve this without the use of JavaScript, consider utilizing max-width instead of width.

https://jsfiddle.net/XyzAbc12/

.box {
  transition: max-width 3s cubic-bezier(0.3, 1, 0.7, 1);
  width: auto;
  max-width: 5em;
}

.box-expanded {
  max-width:8em;
}

Adjust the values to prevent any content cutoff. Keep in mind that this approach may not be ideal, particularly if the content is dynamic (e.g., generated by a CMS).

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

`Discover the latest version of Tailwind using JavaScript or PHP`

My setup includes Laravel v8.81.0 (PHP v8.1.2), Vue v3.2.30, and Tailwind https://i.sstatic.net/fVbJB.png I am looking to fetch the Tailwind version in JavaScript similar to how I can get the Vue version using: //app.js require('./bootstrap'); ...

Rendering components before ComponentDidMount runs and Axios handles state updates

When I try to pass the gifs state to my GifList component in the render method, I encounter an issue. It seems that when trying to access the array within the component through props, it is returning as undefined. After investigating further, I noticed t ...

Creating a Hover Effect for DIV Elements Using Pure CSS, No JavaScript Needed

Imagine a straightforward, horizontal navigation on a website: | Home | About | Products | Contact | Impress | ... or something like that... A rectangular element is positioned above the navigation. Now, I want this rectangle to automatically shift hori ...

Using webpack with the production parameter

Currently working on an Express+React application which utilizes webpack for bundling. During development, I have been using "webpack --watch", but as I prepare to deploy to production, I am interested in uglifying my JavaScript code. Unfortunately, the ...

The use of absolute positioning in conjunction with overflow:hidden

<div id="container" style="overflow:hidden; position:relative;"> <div id="content" style="position:absolute;"> </div> </div> Is it possible to display the content element which is larger than its parent container, while still k ...

Centering all td elements except for those with a specific class

Consider the following code snippets: <tr> <td class="foo">chuchu</td> <td>chuchu</td> <td>chuchu</td> <td>chuchu</td> <td>chuchu</td> </tr> Is there a way to center align thes ...

Overlapping sliding toggles with jQuery on multiple elements

Just starting out with jQuery and I've come across a few examples of slideToggle but they are all overlapping. Here's the code I have so far: jQuery: <script src="jquery-1.9.1.js"> </script> <script> $ (document).ready(fun ...

Dealing with multiple occurrences of forward slashes in a URL

Currently utilizing React and grappling with resolving duplicate forward slashes on my site in a manner similar to Facebook. The process functions as follows: For example, if the user visits: https://facebook.com///settings, the URL is then corrected to h ...

Leverage JavaScript to retrieve the number of active Ajax requests in JSF

When running Selenium tests using JS, I want to ensure that there are no active Ajax requests. While I can successfully extract the amount of active Ajax requests for jQuery and PrimeFaces, I am facing some issues with JSF. String jsPF = "return PrimeFace ...

Adding a new value to an array of objects without altering the existing values in ReactJS and NextJS

I have a JSON file containing image names that I need to organize into a Key-Value Object. I am currently using regex to create keys by removing "-img[image No]". However, I am having trouble storing all the image names in the array without overwriting pre ...

File Upload yields a result of 'undefined'

Currently, I am utilizing Express File Upload. When attempting to send a post request to it, the error-handler returns an error indicating that no files were found. Upon logging console.log(req.files), it shows as undefined, causing the error to be sent ba ...

Sending arguments to a component without using quotation marks

Staying safe and staying productive at home with some coding! I've been working on creating a customized component for personal use that is essentially integrating the functionalities of the UI Kit framework when it comes to buttons. Here's the ...

Analyzing Data for Distributed / External Pages

Our team is currently exploring options for tracking metrics on content we produce for external pages. We are considering various approaches such as creating our own JavaScript, using a tracking pixel, or adapting Google Analytics to fit our needs. We wou ...

Having trouble displaying the fancybox helper buttons

I had everything working perfectly, but suddenly it stopped and I can't figure out what went wrong. I just need the left, right arrows, and helper buttons to appear when fancybox is open. Any assistance would be greatly appreciated. PS: All the neces ...

The alignment of inline-block elements is not being maintained on the same line

Here's a question I have about my embedded form. Why does the display property of inline-block make the "submit" and "terms" elements appear higher than the email field? And more importantly, how can I fix this issue? I've attempted to use the t ...

Troubleshooting the issue of array filtering not functioning properly in Async.js

When attempting to utilize async's filter method, I am not receiving the expected result. Could someone point me in the right direction? async.filter([1, 3, 5], function (item, done) { done(item > 1); }, function (results) { con ...

"Creating varying lengths of time with useSpring: A Step-by-Step Guide

Is there a way for my component to have an animation that fully displays in 0.3s when my mouse enters, but disappears in 0.1s when my mouse leaves? Currently, with useSpring, I can only define one duration for both scenarios. How can I set different dura ...

Error in Asp.Net Mvc Bundle: Incorrect Path for Scripts

In my ASP. NET MVC Project, I have set up BundleConfig to include jquery, bootstrap, and modernizr scripts. Everything works well when running locally, with the path leading to the exact .js file. However, when I publish the project to the hosting server, ...

Styling the pseudo element ::part() on an ion-modal can be customized based on certain conditions

Looking for a solution regarding an ion-modal with specific CSS settings? I previously had the following CSS: ion-modal::part(content) { width: 300px; height: 480px; } Now, I need to adjust the height based on conditions: if A, the height should be lo ...

Unable to display PHP variable in HTML

I am currently facing an issue while attempting to display user input that includes double quotes in an HTML form. When I echo the input, everything before the double quotes is being shown. For example, if the input is "6" Tropical Premium $8.99", only "6" ...