Tips for resolving vertical alignment styling for images of varying sizes within Vue.js transition-group?

I have created an image slider example, but I'm facing a styling issue when using images of different dimensions. The element leaving the array is positioned absolutely for smooth transitions, but this causes the image to move up.

I am trying to vertically align the images in the middle when they leave or enter the array, but so far I haven't found a solution.

Another problem I would like to address is regarding the animation when the window is left and then returned to after some time. Currently, all cycles of the animation run at once to reach the current state instead of just stopping the animation and continuing from where it left off. Is there a way to catch blur events in browsers?

Any suggestions or ideas would be greatly appreciated.

let numbers = [{key:1},{key:2},{key:3},{key:4},{key:5},{key:6},{key:7}]
 
 let images = [
  { key:1,
    src:"http://lorempixel.com/50/100/sports/"},
  { key:2,
    src:"http://lorempixel.com/50/50/sports/"},
  { key:3,
    src:"http://lorempixel.com/100/50/sports/"},
  { key:4,
    src:"http://lorempixel.com/20/30/sports/"},
  { key:5,
    src:"http://lorempixel.com/80/20/sports/"},
  { key:6,
    src:"http://lorempixel.com/20/80/sports/"},
  { key:7,
    src:"http://lorempixel.com/100/100/sports/"}
 ]
 
 new Vue({
  el: '#rotator',
  data: {
    items: images,
    lastKey: 7,
    direction: false
  },
  mounted () {
    setInterval(() => {
      if (this.direction) { this.prevr() } else { this.nextr() }
    }, 1000)
  },
  methods: {
    nextr () {
    let it = this.items.shift()
      it.key = ++this.lastKey
      this.items.push(it)
    },
    prevr () {
    let it = this.items.pop()
      it.key = ++this.lastKey
      this.items.unshift(it)
    }
  }
})
.litem {
  transition: all 1s;
  display: inline-block;
  margin-right: 10px;
  border: 1px solid green;
  background-color: lightgreen;
  padding: 10px 10px 10px 10px;
  height: 100px;
}
.innerDiv {
  border: 1px solid red;
}
.container {
  overflow: hidden;
  white-space: nowrap;
  height: 250px;
  border: 1px solid blue;
  background-color: lightblue;
}
.list-enter {
  opacity: 0;
  transform: translateX(40px);
}
.list-leave-to {
  opacity: 0;
  transform: translateX(-40px);
}
.list-leave-active {
  position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.11/vue.js"></script>

<div id="rotator">
  
  <button @click="direction = !direction">
      change direction
  </button>
  
  <transition-group 
    name="list" 
    tag="div" 
    class="container">
    
      <div 
        v-for="item in items"            
        :key="item.key" class="litem">
        <!-- 
          <div 
            class='innerDiv'>
              {{ item.key }}
          </div> 
        -->
        <div class='innerDiv'>
          <img :src='item.src'>
        </div>
    </div>
  </transition-group>
</div>

Answer №1

After spending some time on it, I finally managed to achieve a better result for the sliding animation with a changing direction feature.

However, there is one annoying issue when switching the sliding direction. The animation briefly changes to the next state and then returns to the correct one before continuing as expected. This only happens in one direction, and I'm struggling to find a solution for it. Additionally, the last box behaves oddly only once, which is quite puzzling.

So, it's not a perfect solution, but I'd say it's about 98% there :-)

let images = [
  {key:1, domKey:1, src:"http://lorempixel.com/50/100/sports/"  },
  {key:2, domKey:2, src:"http://lorempixel.com/50/50/sports/"   },
  {key:3, domKey:3, src:"http://lorempixel.com/100/50/sports/"  },
  {key:4, domKey:4, src:"http://lorempixel.com/20/30/sports/"   },
  {key:5, domKey:5, src:"http://lorempixel.com/80/20/sports/"   },
  {key:6, domKey:6, src:"http://lorempixel.com/20/80/sports/"   },
  {key:7, domKey:7, src:"http://lorempixel.com/100/100/sports/" }
]

let setPositionRelative = el => el.style.position = "relative"

new Vue({
  el: '#rotator',
  data: {
    items: images,
    lastKey: 7,
    direction: true,
    changeDirectionRequest: false
  },
  mounted () {
  Array.from(this.$el.querySelectorAll("div[data-key]")).map(setPositionRelative)
    setInterval(() => {
      if(this.changeDirectionRequest) {
        this.changeDirectionRequest = false
        this.direction = !this.direction
        if (this.direction) 
        Array.from(this.$el.querySelectorAll("div[data-key]")).map(setPositionRelative)
        else 
        Array.from(this.$el.querySelectorAll("div[data-key]")).map(el => el.style.position = "")
      } 
      if (this.direction) this.prevr() 
      else this.nextr()
    }, 1000)
  },
  methods: {
    nextr () {
      let it = this.items.shift()
      it.key = ++this.lastKey
      this.items.push(it)
    },
    prevr () {
    let it = this.items.pop()
      it.key = ++this.lastKey
      this.items.unshift(it)
      setPositionRelative(this.$el.querySelector("div[data-domkey='"+it.domKey+"']"))
    }
}
})
.container {
  overflow: hidden;
  white-space: nowrap;
  height: 200px;
  border: 1px solid blue;
  background-color: lightblue;
  display: flex;
  align-items: center;
}
.innerDiv {
  border: 1px solid red;
  width: auto; 
  height: auto; 

  display:-moz-box; 
  -moz-box-pack:center; 
  -moz-box-align:center; 

  display:-webkit-box; 
  -webkit-box-pack:center; 
  -webkit-box-align:center; 

  display:box; 
  box-pack:center; 
  box-align:center;
}
.litem {
  transition: all 1s;
  margin-right: 10px;
  border: 1px solid green;
  background-color: lightgreen;
  padding: 10px 10px 10px 10px;
}
.list2-enter, .list-enter {
  opacity: 0;
  transform: translateX(40px);
}
.list2-leave-to, .list-leave-to {
  opacity: 0;
  transform: translateX(-40px);
}
.list-leave-active {
  position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.11/vue.js"></script>

<div id="rotator">
  <button @click="changeDirectionRequest = true">change direction</button>
  <transition-group name="list" tag="div" class="container">
    <div   v-for="item in items" 
          :key="item.key" 
          :data-domkey="item.domKey" 
          class="litem">
          
       <div class='innerDiv'>
          <img :src='item.src'>
        </div>
    </div>
  </transition-group>
</div>

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

The :focus pseudo-class is failing to target the input element

I'm dealing with a simple input field of type text: <input matInput type="text" placeholder="{{placeholder}}" class="input-field" [ngClass]="{'error': hasErrors}" [readonly]="isReadonly&quo ...

Bringing to life in Vue.js

I am a beginner with Vue.js and I have been attempting to integrate Materialize into my project. I have experimented with various plugins such as vue-materialize (https://github.com/paulpflug/vue-materialize) and vue-material-components (https://www.npmjs. ...

Issue with Safari: Unable to trigger CSS :hover when tapping SVG element

On an iOS device in Safari, tapping this SVG element does not trigger the transition animation to fade in the replacement <g id="training-sub-menu">. The animation is confirmed to work, as there is a strange behavior where long-pressing whe ...

Adjusting the color of a cell based on its value

Currently, I am in the process of converting a CSV file to an HTML table by utilizing a tool available at . However, I am facing a challenge in modifying the background color of cells based on their values. I would greatly appreciate any help or guidance w ...

"Unexpected discrepancy: Bootstrap Glyphicon fails to appear on webpage, however, is visible

I am having some trouble getting the glyphicon to display properly in my side nav. The arrow head should rotate down, which is a pretty standard feature. Here is the link to the page: The glyphicon should be visible on the "Nicky's Folders" top leve ...

Is it possible to alter the color of a parent's pseudo-element when it is focused using CSS3?

This situation is quite challenging, and I believe achieving it with plain CSS3 alone is difficult (easier with jQuery, but I'm trying to avoid that). Are there any potential workarounds or hacks? My main goal is for it to be cross-browser compatible ...

Creating Images that appear optimized on smaller screens - the art of responsive design!

Currently, I am in the process of working on this test page located at the following link: While the page appears fine on my laptop screen, it is displaying poorly on my phone's browser. The images, in particular, appear disorganized and messy. Coul ...

What is the technique for implementing a slide animation on hover to move a div identified by the class `box`?

How can I create a div element with the class of box that already has some transitions applied to it, and also include a slide animation on hover effect for the same div? .box { background-color: red; width: 70px; height: 70px; transition-propert ...

Mastering the art of using div boxes in boxing form

When I box in information using divs, I've noticed that sometimes the wrapping boxes don't fill out the space completely. This can result in elements from other wrappers encroaching into the box area. For example: <div> <div style="le ...

Using base64 encoding for font-face with alternative fallbacks

After reading this article, I am interested in incorporating a font face in the following way: @font-face { font-family: 'MyWebFont'; src: url('webfont.eot'); src: url('webfont.eot?#iefix') format('embedded-openty ...

Creating a separate CSS file for a CSS class that sets the width of a <div

I am looking to enhance a div element by incorporating a specific class from a separate CSS file. For example, my HTML file contains the following snippet: /* width 90% */ @media (min-width: 960px) { div.width90 { max-width: 90%; } } <div cl ...

What are the steps to troubleshoot CSS issues in NextJS?

Currently, I am encountering challenges while trying to integrate markdown with CSS. The problem I am facing has been replicated in the link provided: https://codesandbox.io/s/react-quilljsbasic-forked-3rcxw?file=/src/App.js ...

What is the best way to center align and add an icon to the header in Ionic?

How can I center align an "ion-ios-arrow-up" icon in the header of my Ionic app, similar to the concept shown below? This is my HTML template: <ion-view cache-view="false" view-title="Historical HPP"> <ion-nav-bar class="nav-title-slide-ios7 ...

Connect your Nuxt.js application with Mailchimp for seamless integration

I've tried the solution recommended in this thread, but unfortunately, it's not working for me. Every time I run npm run dev, I encounter an error message: ERROR - Compilation failed with 1 error at 11:21:24 The following dependency was not fo ...

Is there a way to smoothly slide an element in the same way another element can be dragged out

I am currently using AngularJS. My goal is to achieve the following: When the 'Fade in' button is clicked, a hidden element should slide out from the left side. It should appear behind the 'MAIN BASE' element, giving the illusion that ...

What could be causing the overlap of my input box with its parent container?

Here is the code snippet I am working with: <section className="createTodo-box"> // parent <div className="createTodo-inside"> // child <Input value={this.state.text} style={{ width: '200px' }} ...

Exploring the art of div transitions and animations using React and Tailwind CSS

I successfully implemented the sidebar to appear upon clicking the hamburger icon with a transition. However, I am now facing the challenge of triggering the transition when the close button is clicked instead. I have attempted using conditional operations ...

Error: Unable to initialize VueRouter as a constructor

In my app.js, I have the code snippet below: const routes = [ {path:'/home', component:home}, {path:'/department', component:department}, {path:'/employee', component:employee} ] const router = new VueRouter({ ...

Vue.js: SCSS @import being overlooked

I've found great success using VueJS in two different projects. As I prepare to launch these projects, I'm encountering an issue when generating the files with npm run build. One project, created recently, is working fine. However, the other pro ...

Utilization of z-index with float: left within an image gallery in CSS

Currently, I am working on an image gallery that has content generated randomly. In terms of CSS, the images are positioned using the following code: .item { width: 200px; margin: 10px; float: left; } To add some functionality, I have implemented ...