vue-stack-grid icon indicating copy to clipboard operation
vue-stack-grid copied to clipboard

Horizontal scrollbar is visible on page refresh

Open bustarice opened this issue 5 years ago • 3 comments
trafficstars

I noticed when I refresh the page, I can see a horizontal scrollbar. However, if I resize the browser window it goes away and recalculates the grid items correctly again.

I can easily add an overflow-y: hidden to remove but it's not really a solution as the right side items will be cutoff and not fully shown.

I also tried adding:

ref="stacker"

and then a button to call a method:

<b-button @click="reflow">reflow</b-button>

reflow() {
     this.$refs.stacker.reflow()
 }

which does work but adding it to mounted to do it automatically doesn't seem to do anything.

Is there any workaround or fix to remedy this situation?

bustarice avatar Dec 25 '19 20:12 bustarice

So I tried adding a delay after the data has completed updating the variable for the stack in axios with the following:

setTimeout(() => { this.reflow() }, 800)

and it actually worked. However, I feel I shouldn't have to do this in order to get the initial page load to reflow correctly. Perhaps the stack component should detect full page load and then call a reflow and/or do what I did with the delay? Seems as if it's doing the reflow too soon.

I'll stick to this workaround for now until I get some input on this issue.

Thanks.

bustarice avatar Dec 26 '19 08:12 bustarice

@bustarice thanks for the report. The Stack component should call reflow on the next tick after it's mounted. You can see this in the source code (src/Stack.vue). It seems that either the DOM isn't ready yet at that point, or the update/reflow methods don't get called correctly.

Could you check if this happens in any browser, and if the appropriate methods get called on page load? You should be able to debug this pretty easily by adding console.logs to the mounted, update and reflow methods of the Stack component.

WouterFlorijn avatar Jan 01 '20 17:01 WouterFlorijn

Could you check if this happens in any browser, and if the appropriate methods get called on page load? You should be able to debug this pretty easily by adding console.logs to the mounted, update and reflow methods of the Stack component.

So I did as you suggested with the following console.log:

mounted() {
	window.addEventListener('resize', this.reflow)
	this.update()
	console.log('mounted')
},

update() {
	this.$nextTick(this.reflow)
	console.log('updated')
},

reflow() {
	this.updateColumnData()
	let cols = this.getBaseColumns()

	this.$emit('reflow', {
	  containerWidth: this.containerWidth,
	  columnCount: this.columnCount,
	  columnWidth: this.columnWidth,
	})

	this.$children.forEach((child, i) => {
	  child.$el.style.width = this.columnWidth + 'px'

	  let n = 0
	  if (i < this.columnCount)
		n = i
	  else
	  {
		let minH = -1
		cols.forEach((col, j) => {
		  if ((minH == -1) || (col.h < minH))
		  {
			n = j
			minH = col.h
		  }
		})
	  }

	  child.$el.style.transform = 'translate(' + cols[n].x + 'px, ' + cols[n].h + 'px)'
	  cols[n].h += child.$el.offsetHeight + this.gutterHeight
	})

	let containerHeight = 0
	cols.forEach(col => containerHeight = Math.max(containerHeight, col.h))
	this.$el.style.height = containerHeight + 'px'

	console.log('reflowed')
}

console

updated			Stack.vue?d914:76
mounted			Stack.vue?d914:40
reflowed		Stack.vue?d914:114
reflowed		Stack.vue?d914:114

home.vue

<template>
    <b-container id="home-page" fluid>
        <stack
            :column-min-width="250"
            :gutter-width="1"
            :gutter-height="1"
            monitor-images-loaded
            ref="stacker"
            v-if="images.length"
        >
            <stack-item
                v-for="(image, i) in images"
                :key="i"
                style="transition: transform 300ms"
            >
                <div class="content">
                    <div class="content-overlay"></div>
                    
                    <b-img-lazy class="grid-image content-image" :src="image.image" :alt="image.alt_description"></b-img-lazy>

                    <div class="content-details fadeIn-bottom">
                        <b-link :to="image.link">
                            <h5 class="content-title">{{ image.title }}</h5>
                            <p class="content-text">{{ image.alt_description }}</p>
                        </b-link>
                    </div>
                </div>
            </stack-item>
        </stack>
        <!-- <span v-else>no results found</span> -->
    </b-container>
</template>

<script>
    import { Stack, StackItem } from 'vue-stack-grid'
    export default {
        components: {
            Stack,
            StackItem
        },

        data () {
            return {
                currentPath: '',
                images: []
            }
        },

        methods: {
            getActiveListings() {
                let routePath = this.currentPath
                let url = 'listings/gethomelistings'
                axios.post(url, {
                    path: routePath
                })
                .then((res) => {
                    this.images = res.data.listings

                    // temp workaround due to initial page load doesn't reflow correctly
                    // setTimeout(() => {
                    //     if (res.data.listings.length) {
                    //         this.reflow()
                    //     }
                    // }, 800)
                }, () => {
                    this.has_error = true
                })
            },

            reflow() {
                this.$refs.stacker.reflow()
            }
        },

        created() {
            this.getActiveListings()
        },

        mounted() {
            this.currentPath = this.$route.path
        },

        watch: {
            '$route.path': {
                handler: function(route) {
                    this.currentPath = route
                },
                deep: true,
                immediate: true
            },

            currentPath: function() {
                this.getActiveListings()
            }
        }
    }
</script>
<style lang="scss">
    #home-page {
        a { 
            cursor: pointer;
        }

        padding-left: 0px;
        padding-right: 0px;

        .content {
            position: relative;
            // width: 90%;
            // max-width: 400px;
            margin: auto;
            overflow: hidden;

            .content-overlay {
                background: rgba(0,0,0,0.7);
                position: absolute;
                // height: 99%;
                height: 100%;
                width: 100%;
                left: 0;
                top: 0;
                bottom: 0;
                right: 0;
                opacity: 0;
                -webkit-transition: all 0.4s ease-in-out 0s;
                -moz-transition: all 0.4s ease-in-out 0s;
                transition: all 0.4s ease-in-out 0s;

                img .grid-image {
                    width: 100%;
                    height: auto;
                }
            }
        }

        .content:hover .content-overlay {
            opacity: 1;
        }

        .content-image {
            width: 100%;
        }

        .content-details {
            position: absolute;
            text-align: center;
            padding-left: 1em;
            padding-right: 1em;
            width: 100%;
            top: 50%;
            left: 50%;
            opacity: 0;
            -webkit-transform: translate(-50%, -50%);
            -moz-transform: translate(-50%, -50%);
            transform: translate(-50%, -50%);
            -webkit-transition: all 0.3s ease-in-out 0s;
            -moz-transition: all 0.3s ease-in-out 0s;
            transition: all 0.3s ease-in-out 0s;

            h5 {
                color: #fff;
                font-weight: 500;
                letter-spacing: 0.15em;
                margin-bottom: 0.5em;
                text-transform: uppercase;
            }

            p {
                color: #fff;
                font-size: 0.8em;
            }
        }

        .content:hover .content-details {
            top: 50%;
            left: 50%;
            opacity: 1;
        }

        .fadeIn-bottom {
            top: 80%;
        }

        .fadeIn-top {
            top: 20%;
        }

        .fadeIn-left {
            left: 20%;
        }

        .fadeIn-right {
            left: 80%;
        }
    }
</style>

So it seems everything gets called correctly on the Stack component.

By removing my delay code, I tried on IE/Edge/Firefox/Chrome and all exhibit the same behavior.

bustarice avatar Jan 01 '20 19:01 bustarice