Creating a smooth transition for an element's width change as a neighboring element shows or hides using v-show

I'm working on a Vue.js application with tailwind styling. Within a flex parent container in my template, I have two child elements - one is always present, and the other is conditionally rendered using v-show.

The issue arises when the conditional element appears, causing the width of the first element to adjust automatically to accommodate the new space within the flex container. While this behavior is expected, I am looking to enhance it by adding a smooth animation to the width change of the first element, such as a sliding effect.

Here's a simplified version of my template structure:

<div>
  <div
    v-for="(group, groupName, index) in groups"
    :key="groupName"
    class="flex flex-row mb-2 relative"
  >
    <Transition
      mode="in-out"
      enter-from-class="-translate-x-[150%] opacity-0"
      leave-to-class="-translate-x-[150%] opacity-0"
      enter-active-class="transition duration-200"
      leave-active-class="transition duration-200"
    >
      <div class="join join-vertical" v-show="buttonsVisibility[groupName]">
        <!-- Conditionally rendered element -->
      </div>
    </Transition>

    <div class="shadow-md rounded-lg collapse">
      <!-- The element I would like to animate when the other element is shown/hidden -->
    </div>
  </div>
</div>

Current behavior:

https://i.sstatic.net/y3uqsV0w.gif

I'm seeking advice on how to achieve an animated transition effect for the specific element. Any help or suggestions would be highly appreciated!

I've attempted to use Vue's "Transition" component and Tailwind's transition properties for the dynamically changing width element without success.

Answer №1

This code provides a practical solution for creating an animation on a flexbox element.

<script setup>
import { ref } from 'vue'

const shown = ref(true)
</script>

<template>
  <nav class="flex">
    <div class="first" :class="shown && 'open'">first block</div>
    <div class="second" @click="shown = !shown">second block that we do not really care about</div>
  </nav>
</template>

<style>
.flex {
  display: flex;
  height: 50px;
}
.second {
  background-color: #e9edc9;
  flex: 12 0; /* set to 1 0 if you want to have an even width for the elements */
}

.first {
  background-color: #caf0f8;
  width: 0; /* this is important for the element to shrink */
  display: hidden; /* this replaces the v-show in a better way */
  transition: all 250ms ease-in-out;
}

.open {
  background-color: #90e0ef;
  flex: 1 0; /* where the transition happens */
}
</style>

Check out this interactive playground to experiment with the code. It's straightforward and can be easily translated into Tailwind CSS.

Let's break down what's happening in the code:

  • The use of v-show typically adds display: none; to an element, which can complicate transitions due to CSS limitations. Instead, using display: hidden; achieves the same visual effect while allowing for smoother transitions.
  • In this example, a simple
    @click="shown = !shown"
    event handler is used, but alternatives like @mouseenter or @mouseleave could also work depending on the desired behavior.
  • The flex: 12 0; property creates a small width on one side by enlarging the parent container twelve times its normal size.
  • Avoiding unnecessary transforms in favor of leveraging flexbox properties ensures an efficient layout approach. Check out this comprehensive guide to Flexbox for more information.
  • In this scenario, using a <transition> component isn't necessary as the width distribution is handled effectively through flexbox properties, making it easy to translate to Tailwind CSS.
  • The
    :class="shown && 'open'"
    syntax applies the .open class to the element when shown is truthy.

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

Troubleshooting issues with Vue.js page routing

Currently, I am diving into the world of vue.js and encountering difficulties with setting up routing. My goal is to utilize templates stored in separate HTML files, rather than inline templates. The issue I'm facing is that the routing does not seem ...

Has there been a recent update to Tailwind CSS' sizing rules?

After working with Tailwind CSS for the past few months, I have encountered some issues with sizing parameters such as font size, padding, and margin. I am wondering if this is a common problem or if it could be an issue with my local files. Thank you. ...

Secure the API with CORS to prevent unauthorized access from different frontends, such as Postman, when making

Having trouble calling a POST request to API from React JS using Axios due to CORS error. Is there any way around this, or is there another frontend framework that can handle this issue? View the code sandbox here: https://codesandbox.io/s/axios-forked-g ...

Sticky CSS - A guide to making aside elements fill the entire available height

How can I create a grid layout where the aside is sticky to top: 0 and fills all remaining height (e.g. 100% of height), but when scrolling down, the aside height should be changed to 100% minus the footer's height? Is it possible to achieve this with ...

What is the best way to simultaneously check two conditions in Vue.js?

In my current scenario, I am facing a challenge with checking both conditions simultaneously. If an attachment exists in the request but the attachment field does not exist in the form, it should display a message in the modal. Similarly, if body text exis ...

The jQuery DataTable with footer is lacking responsiveness

Why is my table not responsive when I add a tfoot? I tried using the example found at https://datatables.net/examples/api/multi_filter.html Interestingly, when the footer contains only text, the table is responsive. However, if there's an input fie ...

The slider thumb on materialized CSS HTML5 Range is not visible

After updating to Materialize 1.0.0, I noticed that the thumb is not showing on the HTML5 range input. Interestingly, when using Materialize 0.100.2 or 0.97.3, the thumb is displayed correctly. Unfortunately, I can't revert back to the older version ...

Shifting the placement of a component in Vue JS when hovering the mouse

I am facing an issue regarding the positioning of components. I have four images, and when you hover over them, a specific component is displayed as shown below: https://i.sstatic.net/gybcy.png For example, hovering over a yellow image will display a dif ...

Open a new HTML page with jQuery with a click event trigger on an iframe element

Hello everyone, I have a simple question as I am still learning about Jquery. I am attempting to load another .html page whenever a figure element is clicked on this .html page. However, the script tag is not working as expected. Can someone please assist ...

I am looking to host several iterations of jQuery on a content delivery network within my Nuxt application

Currently, we are loading jQuery 3.1.4 externally from a CDN on the top page. index.vue head: { bodyAttrs: { id: 'overview' }, script: [ { src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min ...

Tips for achieving a scrollable table in the shadcn/ui framework?

I am attempting to create a layout with a fixed TableHeader and a scrollable TableBody. While the current code accomplishes this, the content in the TableBody is being squished into the first column. How can I resolve this issue? export default function ...

Is there a way to get rid of those pesky red lines that appear when declaring variables in a .scss file in VS

Encountering red lines when defining variables in a .scss file using VS Code. The error message reads as follows: I have attempted various settings configurations in VS Code, but none seem to resolve the issue. Any suggestions for fixing this problem? ...

Python Selenium tutorial: Navigating inner scrollbars on websites

Struggling to implement scrolling within a container with its own scrollbar. Various methods have been attempted, but none have succeeded or met the desired standard. Here is the HTML code snippet of the scrollbar: <div id="mCSB_2_dragger_vertical ...

The desired hover effect on the navigation bar is not functioning properly

I have successfully created a hover effect for my navigation bar and the list inside it. However, I am facing an issue where the box shadow effect is only appearing in a small area when hovered (see image below). My goal is to extend the shadow effect to ...

Combining different HTML table borders

Here is some example code: <!DOCTYPE html> <html> <body> <h4>Creating a table with nested tables:</h4> <table border="1"> <tr> <td>100</td> <td>200</td> <td> </td> < ...

v-tooltip specifically designed for the append-icon

I'm currently working with Vuetify and facing an issue with applying a tooltip only for the append-icon in a v-text-field. The current problem is that the tooltip does not work for icons at all! View code on CodePen <v-tooltip bottom> < ...

Is there a way to eliminate the "x" in the upper right corner of a Foundation Joyride?

Edit 7/16/15: I decided to place the following code between the <li> tags within the joyride that required the removal of the "x" button: <script>$('.joyride-close-tip').remove();</script> While not the most elegant solution ...

Is there a challenge in setting up a tag search bar similar to Stack Overflow's?

First and foremost, I apologize for the awkwardly phrased question. The issue at hand is that when the tags exceed the container size, the search option becomes hidden. My goal is to have the search bar adjust dynamically, moving everything back inside the ...

Image alignment

Currently, I am designing a website that requires an image to be centered in the left side of a div, aligned with the right div which has a background. I attempted a common solution, but unfortunately it is not functioning properly. The design must also be ...

Issue with Vue.js component not properly retrieving value from variable

Having recently started using Vue.js in my laravel application, I have incorporated the following component from https://github.com/saintplay/vue-swatches. It works well, but I am encountering an issue when trying to pass a HEX color value from a variable ...