Home > Net >  Vue slide up and down transition not working at all, elements just pop in and out
Vue slide up and down transition not working at all, elements just pop in and out

Time:10-08

I have a footer section that has some hidden content that can be toggled. For whatever reason the transition animation isn't working/ is super stuttery and I'm not too sure what I am doing wrong here.

I've read about making max-height the attribute you target with the animations, but this is still not working properly.

I've made a CodeSandbox to show the issue, so please take a look!

Any advise or tips would be greatly appreciated!

Cheers!

Footer.vue

<template>
  <div >
    <div >
      <div >
        <p >Something</p>
        <div>button</div>
        <div>button</div>
      </div>
      <div >
        <button
          v-if="!videoIsPlaying"
          key="1"
          style="cursor: pointer"
          @click.prevent="() => playVideo()"
          
        >
          <svg
            
            id="Play_Btn"
            data-name="Play Btn"
            xmlns="http://www.w3.org/2000/svg"
            width="100%"
            height="100%"
            viewBox="0 0 32 32"
          >
            <rect
              id="Rectangle_3351"
              data-name="Rectangle 3351"
              width="32"
              height="32"
              rx="4"
              fill="#4972fa"
              opacity="0.254"
            />
            <path
              id="Play"
              d="M7.649,1.382a1,1,0,0,1,1.7,0l6.71,10.893A1,1,0,0,1,15.21,13.8H1.79a1,1,0,0,1-.851-1.524Z"
              transform="translate(25.16 7.5) rotate(90)"
              fill="#466ff4"
              opacity="0.998"
            />
          </svg>
        </button>
        <button
          v-else
          key="2"
          style="cursor: pointer"
          @click.prevent="() => stopVideo()"
          
        >
          <svg
            
            id="Stop_Btn"
            data-name="Stop Btn"
            xmlns="http://www.w3.org/2000/svg"
            width="100%"
            height="100%"
            viewBox="0 0 32 32"
          >
            <rect
              id="Rectangle_2865"
              data-name="Rectangle 2865"
              width="32"
              height="32"
              rx="4"
              fill="rgba(71,113,250,0.25)"
            />
            <rect
              id="Rectangle_3155"
              data-name="Rectangle 3155"
              width="15"
              height="15"
              rx="1"
              transform="translate(8.5 8.5)"
              fill="#4771fa"
            />
          </svg>
        </button>
        <p >{{ videoTime }}</p>
      </div>
      <div >
        <p >{{ time }}</p>
        <p >{{ timezone }}</p>
      </div>
    </div>
    <Transition name="slide" mode="out-in">
      <div
        v-if="liveInferenceManagementPanelIsVisible"
        style="
          display: flex;
          justify-content: center;
          align-items: center;
          max-height: 0;
          background-color: #202634;
          padding: 3em 0;
        "
      >
        <div>something here</div>
      </div>
    </Transition>
  </div>
</template>
<script>
import { defineComponent, ref } from "vue";

export default defineComponent({
  setup() {
    const videoIsPlaying = ref(false);
    const liveInferenceManagementPanelIsVisible = ref(false);
    const videoTime = ref("00:00:00");
    const time = new Date().toLocaleTimeString([], {
      hour: "2-digit",
      minute: "2-digit",
      // hour12: false,
    });
    const timezone = new Date()
      .toLocaleDateString(undefined, { day: "2-digit", timeZoneName: "long" })
      .substring(4)
      .match(/\b(\w)/g)
      .join("");
    function playVideo() {
      videoIsPlaying.value = true;
      liveInferenceManagementPanelIsVisible.value = false;
      console.log("Video starts");
    }
    function stopVideo() {
      videoIsPlaying.value = false;
      liveInferenceManagementPanelIsVisible.value = true;
      console.log("Video ends");
    }
    return {
      videoIsPlaying,
      liveInferenceManagementPanelIsVisible,
      videoTime,
      time,
      timezone,
      playVideo,
      stopVideo,
    };
  },
});
</script>
<style lang="sass" scoped>
._real-time-footer
  position: absolute
  bottom: 0
  left: 0
  right: 0
  &-top
    display: flex
    justify-content: center
    align-items: center
    width: 100%
    padding: 1rem 2rem
    color: #A5B0CB
    background: #283044
    &-left-side
      flex: 1 1 0
      display: flex
      align-items: center
      gap: 2em
      // flex-wrap: wrap
      &-inferences-text
        margin-right: 2em
      &-live-feed
        position: absolute
        top: 1.5em
        left: 1.5em
        color: #fff
._video-play-and-time
  flex: 1 1 0
  display: flex
  align-items: center
  background: none
  gap: 1.25em
  &-play-button
    &:focus
      outline: none
    &-icon
      width: 2em
  &-time
    opacity: 50%
._current-time
  justify-self: right
  display: flex
  align-items: center
  gap: 0.75em
  border-radius: 12px
  padding: 0.35em 1.25em
  background-color: #202634
  &-time
    font-size: 14px
  &-timezone
    font-size: 8px
    opacity: 66%
._dsp-wrapper
  position: absolute
  top: 10px
  left: 10px
  height: 70%
  width: 20%
._fsp-wrapper
  position: absolute
  top: 8px
  right: 8px
  height: 43%
  width: 20%
._ccp-wrapper
  position: absolute
  bottom: 8px
  right: 10px
  left: 10px
  // width: 100%
  height: 23%
  background: red
  opacity: 70%

.fade-move,
.fade-enter-active,
.fade-leave-active
  height: inherit
  transition: opacity 0.3s

.fade-enter,
.fade-leave-to
  opacity: 0

.slide-enter-active
  -moz-transition-duration: 0.3s
  -webkit-transition-duration: 0.3s
  -o-transition-duration: 0.3s
  transition-duration: 0.3s
  -moz-transition-timing-function: ease-in-out
  -webkit-transition-timing-function: ease-in-out
  -o-transition-timing-function: ease-in-out
  transition-timing-function: ease-in-out

.slide-leave-active
  -moz-transition-duration: 0.3s
  -webkit-transition-duration: 0.3s
  -o-transition-duration: 0.3s
  transition-duration: 0.3s
  -moz-transition-timing-function: cubic-bezier(0, 1, 0.5, 1)
  -webkit-transition-timing-function: cubic-bezier(0, 1, 0.5, 1)
  -o-transition-timing-function: cubic-bezier(0, 1, 0.5, 1)
  transition-timing-function: cubic-bezier(0, 1, 0.5, 1)

.slide-enter-to,
.slide-leave
  max-height: 200px
  overflow: hidden

.slide-enter,
.slide-leave-to
  overflow: hidden
  max-height: 0
</style>


CodePudding user response:

A couple of remarks.

  • The class naming syntax has changed from vue2 to vue3 .slide-enter should be now .slide-enter-from. Check out the css based transitions.
  • I put your inline styling in a class above the transition classes to get the css specificity in order.
  • I used the padding property instead of the max-height. Since the padding property is the one deciding the container height.

With all this in place your sass code should look something like:

.slide-container
  display: flex
  justify-content: center
  align-items: center
  max-height: 0
  background-color: #202634
  padding: 3em 0

.slide-enter-active
  ...

.slide-leave-active
  ...

.slide-enter-to,
.slide-leave-from
  padding: 3em 0
  overflow: hidden

.slide-enter-from,
.slide-leave-to
  overflow: hidden
  padding: 0em 0

I forked your example and made the changes for you to play around.

  • Related