Vue Smooth Reflow

Vue Smooth Reflow

The Vue Smooth Reflow lets you transition an elements reflow when the data changes.

Vue Smooth Reflow (VSR)

A Vue mixin that transitions reflow.

When the component's data is changed, any CSS properties that you register will transition to its new value.

Common use cases are:

  • Transitioning height: auto and width: auto.
  • Smoothly repositioning elements.

Note that this library has no overlap with Vue's built in <transition> components.

Table of Contents

Demo

https://vuesmoothreflow.guanzo.io

If you want to see how the examples were configured, the demo source is here: github

Installation

Download via npm:

$ npm install vue-smooth-reflow

Include via cdn:

<script src="https://unpkg.com/vue-smooth-reflow"></script>

Usage

Module:

<template>
    <div>
        <div v-for="n in children" />
    </div>
</template>

<script>
// The component's root el will now transition to
// accomodate new values of 'this.children'

import smoothReflow from 'vue-smooth-reflow'
export default {
    mixins: [smoothReflow],
    data() {
        return {
            children: '<Dynamic value>'
        }
    },
    mounted(){
        this.$smoothReflow()
    },
}
</script>

Browser:

The mixin is available via the global variable SmoothReflow

API

$smoothReflow(options)

Enables smooth reflow on an element. This method is available on the component instance.

options can be an object, or an array of objects.

Options reference

  • el

    Type: Element | String

    Default: The components root element.

    An element reference, or a CSS selector string. The resolved element will transition reflows on registered properties. This element is referred to as the "smooth element".

    Use a selector string if the element is not rendered initially, like if it's hidden with v-if. If the selector returns multiple elements, the first one will be used.

  • property

    Type: String | Array

    Default: height

    Valid values: height, width, transform

    The CSS property(s) that you want to transition. You can pass any combination.

    For transform, VSR will only transition the translate() function. This is to handle element repositioning due to reflow.

  • transition

    Type: String

    Default: height .5s

    A valid CSS transition value. If you register multiple properties, and want different transitions for each, you can use commas.

    this.$smoothReflow({
        property: ['height', 'width'],
        transition: 'height .25s ease-in-out, width .75s ease-out'
    })
    

    The default value is conditional on the property option.

    For example, if you register height and transform like so:

    this.$smoothReflow({
        property: ['height', 'transform']
    })
    

    The default value will become height .5s, transform .5s.

    If the smooth element has transitions on other properties like background-color, they will be preserved.

    NOTE: Any transitions defined as an inline style on the smooth element will be ignored and erased.

  • transitionEvent

    Type: Object

    Default: null

    Valid values:

    transitionEvent: {
        // Any valid CSS selector. Note that comma delimited selectors are valid.
        selector: String,
        // Any valid CSS property name.
        propertyName: String
    }
    

    Configures the smooth element to react to transitionend events that are emitted by other elements. You must opt-in for this behavior, there is no default.

    selector and propertyName serve as filters so that the smooth element doesn't cause reflows for every transitionend event that it catches, which impacts performance. When the smooth element receives a transitionend event, it will check if selector matches event.target, and/or if propertyName matches event.propertyName. You can specify one or the other, or both. All checks must pass in order for the smooth element to proceed with the smooth reflow.

    A common use case is to delay the smooth reflow until after a child element has been transitioned out with v-if/v-show and <transition>.

    For example, if you want to react to any child div elements that transition out with opacity, use this config:

    transitionEvent: {
        selector: 'div',
        propertyName: 'opacity'
    }
    

    Let's say you want to transition the smooth element's position. You want to wait for an element with class .i-cause-reflow to transition out before performing the smooth reflow. This element can be located anywhere within the component. Here's the configuration for that:

    transitionEvent: {
        selector: '.i-cause-reflow',
    }
    

    Check out the demo for more examples.

  • hideOverflow

    Type: Boolean

    Default: true

    Hides overflow during the transition.

    This has 2 benefits. It prevents the scrollbar from appearing, and will hide child elements that overflow.

$unsmoothReflow(options)

Disables smooth reflow on an element. This method is available on the component instance.

options can be an object, or an array of objects.

Registered elements that have the same el as the passed in options will be unregistered. This usually isn't necessary, but is useful if you want to disable the behavior while the component is still alive.

Smooth Component

Importing VSR into every component that needs it violates DRY. Instead, you can create one component that imports VSR then use it as needed. This should satisfy 90% of use cases.

Example:

// SmoothReflow.vue
<template>
    <component :is="tag">
        <slot/>
    </component>
</template>

<script>
import smoothReflow from 'vue-smooth-reflow'
export default {
    name: 'SmoothReflow',
    mixins: [smoothReflow],
    props: {
        tag: {
            type: String,
            default: 'div'
        },
        options: Object,
    },
    mounted () {
        this.$smoothReflow(this.options)
    }
}
</script>

Globally register this component for convenience.

// main.js
import SmoothReflow from './components/SmoothReflow'

Vue.component('SmoothReflow', SmoothReflow)

Update your existing components that import VSR. This is a modification of the first usage example. Goodbye boilerplate!

<template>
    <SmoothReflow>
        <div v-for="n in children"/>
    </SmoothReflow>
</template>

<script>
-import smoothReflow from 'vue-smooth-reflow'
export default {
-   mixins: [smoothReflow],
    data() {
        return {
            children: '<Dynamic value>'
        }
    },
-    mounted(){
-        this.$smoothReflow()
-    },
}
</script>

You may run into reactivity issues when using the SmoothComponent. VSR hooks into the component's beforeUpdate and updated lifecycle methods, so if those are never called, then the transition won't occur.

Examples:

mounted(){
    // Zero config. Enables smooth reflow on this.$el
    this.$smoothReflow()
    // Register with element reference
    this.$smoothReflow({
        el: this.$refs.wrapper,
    })
    // Register with classname. The first match will be used.
    this.$smoothReflow({
        el: '.wrapper-2',
    })
    // Pass an array of options
    this.$smoothReflow([
        // Wait for .reflow-causer to emit a transitionend event,
        // then transition the smooth element's position
        {
            el: this.$refs.wrapper,
            property: 'transform',
            transitionEvent: {
                selector: '.reflow-causer'
            }
        },
        // Wait for a transitionend event for opacity that
        // comes from the smooth elements descendants,
        // then transition the smooth elements height and width.
        {
            el: '.wrapper-2',
            property: ['height', 'width'],
            transitionEvent: {
                propertyName: 'opacity'
            }
        },
    ])
    // If the element reference is a component,
    // make sure to pass in its "$el" property.
    this.$smoothReflow({
        el: this.$refs.wrapper.$el,
    })
    // Unregister a smooth element that would match
    // the selector '.wrapper-5'
    this.$unsmoothReflow({
        el: '.wrapper-5'
    })
}
</script>

Differences from vue-smooth-height

  • Enables smooth reflows on width and transform.

  • VSR will no longer check for existing transition values for registered properties. It will only use the value of the transition option.

  • The hideOverflow option now defaults to true.

  • The way child transitions are handled is completely different.

License

MIT

Copyright (c) 2013-present, Eric Guan

Github Repository

Tags: #VueJs