vuejs / Discussion

Vue.js discussion
167 stars 17 forks source link

transition-mode="out-in" for elements #156

Open franciscolourenco opened 9 years ago

franciscolourenco commented 9 years ago

The component system has this handy transition-mode directive which allows you to set the order/timing in which the components are to be animated out and into the interface.

I'm replacing a normal element with another, using v-show and would like for the incoming element to be introduced only after the outgoing element is removed. It would be handy if there was a way to connect the two elements and of setting their transition-mode.

Is this possible already? If not, any thoughts on viability?


idea:

<div transition-mode="out-in">
    <div v-show="!loading" v-transition="fade">Load something</div>
    <div v-show="loading" v-transition="fade">Loading...</div>
</div>
azamat-sharapov commented 9 years ago

How about playing with transition-delay CSS property? Here is demo for you.

franciscolourenco commented 9 years ago

Thanks for the idea. However the incoming element is still inserted before removing the outgoing element, causing the later to move around before disappearing. The fix for that is absolute positioning, like in the demo, but it seems a big compromise and increase in complexity, no?

azamat-sharapov commented 9 years ago

However the incoming element is still inserted before removing

I don't think you can keep transitioning elements after removing them from DOM. So, even if "transition-mode" directive was implemented for regular elements, it can't transition them after removing.

azamat-sharapov commented 9 years ago

Oh I think I misunderstood you. Yes, you would want to remove element without transition and insert another with transition. That should be also possible with CSS again. I'll update fiddle now.

franciscolourenco commented 9 years ago

Hold on. Both elements should have transition, but the incoming element should only be inserted in the flow of the page, when the outgoing element is removed.

  1. Element A fades out
  2. Elements A is replaced by B
  3. Element B fades in
azamat-sharapov commented 9 years ago

How about this one? (uncomment line 16-18 in CSS, if you want transition for both elements).

franciscolourenco commented 9 years ago

Does't work like described.

(btw the example will not load i my browser if you include vue.js with http:// )

azamat-sharapov commented 9 years ago

Not sure about your browser, but jsfiddle does warn about HTTP, but you can just ignore warning.

Does't work like expected.

Visually, it is working like you described, but if you want element to be removed from DOM while transitioning, then you are just misunderstading how basic CSS transition works. Or if I'm wrong, explain what exactly is not working like expected.

franciscolourenco commented 9 years ago

There seems to be some miscommunication.

Desired effect

  1. Element A fades out
  2. Elements A is replaced by B
  3. Element B fades in

desired

The issue with the 1st demo is position: absolute

2nd Demo

last demo No animation on outgoing element

last demo 16-18 uncommented With lines 16-18 uncommented it just delays the appearance of the incoming element


Off-Topic: HTTPS

Not sure about your browser, but jsfiddle does warn about HTTP, but you can just ignore warning.

Chrome doesn't load scripts over HTTP if the page is loaded over HTTPS, which it is in my case because of HTTPS Everywhere. This blog post suggests using https for asset's URLs whenever possible.

Error message: https error screenshot

yyx990803 commented 9 years ago

If the items being transitioned has fixed size, you can add a container div with position:relative to wrap the two items with position:absolute.

azamat-sharapov commented 9 years ago

yeah, but he says it's "issue" for him

franciscolourenco commented 9 years ago

It can be made to work with some css (thanks azamat-sharapov for the delay suggestion), just looking for nicer and simpler alternative. Considering there is a transition-mode directive, it would be great if it worked not only with components.

azamat-sharapov commented 9 years ago

Here I come with another trick. I'm sure one could write code shorter, but I did it just to show how your desired functionality can be accomplished. Personally I think CSS way is cleaner and easier, but maybe in some cases JS solution wins.

Off-Topic: HTTPS

Just use https link then.. I changed link on my last fiddle, to https (from CDN).

franciscolourenco commented 9 years ago

Thanks, it is known that it can be accomplished with JS as well. The intent here is hiding all that verbosity in a concise re-usable directive. Also you wouldn't have to specify hardcode delay duration and keep it in sync with the transition-duration, it would automatically work for any transition duration.

Here is another idea:

<div v-if="loading" v-transition="fade">Loading...</div>
<div v-else v-transition="fade" v-transition-mode="out-in">Click to load</div>
azamat-sharapov commented 9 years ago

All right then. @yyx990803 may suggest, I'm out.

Sirk commented 8 years ago

I agree with @aristidesfl. It would be nice to have this feature. As it's a recurrent problem in components librairies such as Vue or React. Absolute positionning is in many case a complicated solution, and it would be nice to "configure" the transition.

In my mind, we should have 3 differents transitions mode :

The could be a nice to have this in the both CSS and JS version of Vue.Transition.

:+1:

igidas commented 8 years ago

+1 for transition-mode not only on components

chrisvfritz commented 8 years ago

Update: In 2.0, transition mode now works with HTML elements as well.

This is the new syntax for dynamic component transitions:

<transition name="fade" mode="out-in">
  <component :is="view"></component>
</transition>

And this code from the original proposal:

<div transition-mode="out-in">
  <div v-show="!loading" v-transition="fade">Loaded</div>
  <div v-show="loading" v-transition="fade">Loading...</div>
</div>

would instead be written as:

<transition name="fade" mode="out-in">
  <div :key="loading">{{ status }}</div>
</transition>

<script>
new Vue({
  // ...
  computed: {
    status: function () {
      return this.loading
        ? 'Loading...'
        : 'Loaded'
    }
  }
})
</script>

Here's a working example you can play with. For more information on the new transitions API, see the release notes for 2.0.0-beta.2.