Animate the button to expand when hovering over it

In my bootstrap-vue project, I have a button with a right arrow icon that expands to show some text when hovered over. However, I noticed that the icon and text are too close together, so I added some margin to create space between them. This adjustment caused the button to close with some glitches when hovering off since it tries to revert back to its original state without any margin. You can view my code below or try it out live on CodeSandbox.

My main question is if there's a way to achieve a smoother transition using CSS.

<template>
<div>
    <b-card>
      <template v-slot:footer>
        <b-button id="buttonId" size="sm" pill variant="outline-info">
          <b-icon icon="arrow-right-circle" variant="danger"></b-icon>
          <span>View details</span>
        </b-button>
      </template>
    </b-card>
  </div>
</template>

<script>
export default {};
</script>

<style>
button span {
  max-width: 0;
  -webkit-transition: max-width 1s;
  transition: max-width 0.5s;
  display: inline-block;
  vertical-align: top;
  white-space: nowrap;
  overflow: hidden;
}
button:hover span {
  max-width: 7rem;
  margin-left: 0.3rem
}
</style>

Answer №1

Although Kamil's approach is clever, I noticed that if you quickly hover over the button without letting the animation finish, you may observe a strange "popping" effect since the separator only disappears after a 0.5s delay.

Therefore, I decided to adjust the padding of the button and span elements to achieve a similar outcome.

new Vue({
  el: '#app'
})
.details-button {
  padding-right: 0px !important; /* Eliminate default padding */
}

.details-button span {
  max-width: 0;
  display: inline-flex;
  white-space: nowrap;
  transition: max-width 0.5s, padding-right 0.45s; /* Smooth transition for width and padding changes to prevent "popping" */
  overflow: hidden;
  padding-left: 5px; /* Include default button padding */
}

.details-button:hover span, .details-button:focus span {
  max-width: 100px; /* Define maximum expansion width depending on content */
  padding-right: 10px !important; /* Add spacing on the right when text expands */
}
<link href="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="187a77776c6b6c6a7968582c362d3628">[email protected]</a>/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="44262b2b3037303625346932312104766a75716a74">[email protected]</a>/dist/bootstrap-vue.css" rel="stylesheet" />

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8defe2e2f9fef9ffecfda0fbf8e8cdbfa3bcb8a3bd">[email protected]</a>/dist/bootstrap-vue.js"></script>
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="94f6fbfbe0e7e0e6f5e4b9e2e1f1d4a6baa5a1baa4">[email protected]</a>/dist/bootstrap-vue-icons.js"></script>

<div id="app" class="p-5">
  <b-card>
    <template v-slot:footer>
      <b-btn class="details-button" size="sm" pill variant="outline-info">
        <b-icon icon="arrow-right-circle" variant="danger"></b-icon>
        <span>Read more</span>
      </b-btn>
    </template>
  </b-card>
</div> 

Answer №2

UPDATE

Take a look at the solution provided by Hiws. It's efficient, requires minimal code, and achieves the desired effect flawlessly.

Initial response

Refer to this customized version of your CodeSandbox.

In essence, instead of applying margin directly to the text, you can introduce a span element to act as a separator between the icon and text.

<b-button id="buttonId" size="sm" pill variant="outline-info">
  <b-icon icon="arrow-right-circle" variant="danger"></b-icon>
  <span class="separator"/>
  <span class="text">View details</span>
</b-button>

Afterwards, you can tweak the CSS styles as needed (modifications are clearly outlined)

button .text { /* added class to differentiate text from separator */
  max-width: 0;
  transition: max-width 0.5s;
  display: inline-block;
  vertical-align: top;
  white-space: nowrap;
  overflow: hidden;
}

button:hover .text { /* same as above */
  max-width: 7rem;
  transition-delay: 0.1s; /* Wait for separator to expand */
}

button .separator {
  display: inline-block;  
  width: 0;               
  transition: width 0.1s; 
  transition-delay: 0.5s; 
}

button:hover .separator {
  width: 0.3em;             
  transition-delay: unset;  
}

While timing adjustments could be made, the overall functionality is effective.

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

Align the content inside a ul element using Bootstrap 4's justify feature

Hello, I am currently using Bootstrap 4 and have a question regarding the "justify-content-around" property. When there are more than three li elements, it works perfectly, but if there are less than three, it does not work. Any tips on how to fix this iss ...

execute action after a specific point in time in the video is reached

How can I hide a div after a video has been playing for a certain amount of time? The code provided below seems like it should work in theory, but is currently not doing so. Any suggestions on how to fix this issue would be greatly appreciated! <body ...

Is there a way to place an image in front of every item in an inline list?

I am working on creating an inline list that shows an image before each list item. However, I am facing an issue where the image appears above the list item instead of being on the same line. My goal is to have the image displayed to the left of each item ...

Having trouble making a Bootstrap 4 input-group with beta 3 prepend/append function properly

When working with Bootstrap 4 Beta 3, I encountered some challenges with the Beta 3, particularly with the input-group-append and input-group-prepend classes. I struggled with placing these classes at the end of my input group. The last button in my inpu ...

Modifications to the toolbar styling are made by the Angular Material mat-form-field

Having some trouble creating an input field in my component alongside a mat-toolbar element. When I try to insert a mat-form-field, it ends up messing with the styling of the mat-toolbar. I've been unable to pinpoint exactly where the issue lies (if ...

The text in Outlook for Windows emails is being obscured by a button that is overlapping it

As a newcomer to HTML email development, I've encountered an issue that has been puzzling me for the past few days. The problem lies in creating a two-column layout where the left column contains an image and the right column holds text along with a b ...

Rendering a prototype and setting its display to none

I have created a slideshow with the following code: <div class="row-3"> <div class="slider-wrapper"> <div class="slider"> <ul class="items"> ...

What is the process for installing the paper.js library?

Recently, I've delved into the world of Paper.js Following a tutorial's instructions, but unfortunately, I'm not getting any output. Here's the code I've used. Can anyone assist in solving this issue? <!DOCTYPE html> &l ...

Split total based on checkboxes toggled with JavaScript

I'm facing a challenge. I have a total sum of donations collected, for example, 10€. Additionally, there are various NGOs that one can select to donate to. Individuals have the option to toggle on/off which NGO's they wish to contribute toward ...

How can you make a drop-down menu in React/Bootstrap appear above all other elements?

My current goal is to implement a Bootstrap dropdown menu that appears when a button is clicked. Within my component structure, the code looks like this: <> <div className='1'> <navbar/> <div> < ...

Adding Logging Features in ASP.NET

I am currently working with an .ascx file that contains both JavaScript and div elements. I need to add a log statement inside a function for troubleshooting purposes. Can someone please guide me on how to achieve this? Below is a snippet of my code: fu ...

What steps should I follow to update the template and seamlessly carry on with writing the function

Hey there! I've set up a function in my views.py file to send an email to the user, and then prompt them to input the body of that email. However, I'm facing a bit of confusion on how to proceed with integrating the email_confirmation.html templa ...

show fixed div when in view

After seeking inspiration from this specific thread on SO, I still need some help. The challenge I'm facing involves displaying a sticky footer within a parent div that is positioned halfway down the page. I've tried multiple tutorials, but none ...

<div.content> </div.content> - Structure

I recall encountering this code before but I can't remember where: <div.main> // .... </div.main> <div.secondary> // .... </div.secondary> Could someone please clarify for me what this syntax is referred to as and what ...

Having trouble with the jQuery removeClass method?

Here is the HTML code I am working with: <div class="span-6"> <p> <table id="symptomTable" class="symptomsTable hidden"><th>Selected Symptoms:</th><tr></tr></table> </p> </div> T ...

Enhancing User Experience with CSS

Is there a way to create a link within a div and change the hover color to indicate it's a link? The challenge is that my div contains both an image and text in separate divs. div { :hover { background-color: light cyan; } Currently, when I hov ...

Determine the height using jQuery before adding the class

I've been grappling with jQuery to accurately calculate the height of an element and then apply a specific CSS class to adjust its height. The issue I'm facing is that jQuery seems to be executing these calculations out of order, which is causing ...

Animating scrollTop using jQuery is a useful feature for creating

I am facing an issue with several section tags within a div that has overflow set to hidden. The structure of the code is as follows: <div id="viewport"> <section> content </section> <section> content </ ...

Issue with Jquery .html() not adding content

Utilizing Jquery to dynamically update a list based on dropdown selections. After successfully fetching data and constructing the correct HTML content within the "item" variable, applying .html(item) does not result in the expected HTML updates. <div c ...

Problems with scrolling in the navigation bar, main content area, and footer

The challenge Encountering a scrolling anomaly with the Navigation Bar, Body, and Footer while utilizing Bootstrap 4. Everything appears to function smoothly on the desktop view. The glitch arises when I reduce the viewport size. The body fails to stay in ...