I have a simple route transition between two components, that horizontally slide in and out, based on this example
I have a position: fixed footer that is inside the main #app element but outside the router-view.
<div id="app">
<ul>
<li><router-link :to="{ path: '/' }">Foo</router-link></li>
<li><router-link :to="{ path: '/test/bar' }">Bar</router-link></li>
</ul>
<transition :name="transitionDirection">
<router-view class="test"></router-view>
</transition>
<footer>Test</footer>
</div>
Durring transitions, if the transitioned components fall outside the viewport, the position of the footer is affected. It's width stretches outside the viewport (since the new component is sliding in from outside the viewport) and it's vertical position is also shifted down, as if it's been added back to the flow, and being pushed down by the newly added content.
The only hunch I have is that this is related to fixed positioned elements behaving as absolute if their parent has been transformed. Here's an article by Eric Meyer on the issue.
A relevant quote from that article:
...where things got really troublesome for me: a transformed element creates a containing block even for descendants that have been set to position: fixed. In other words, the containing block for a fixed-position descendant of a transformed element is the transformed element, not the viewport. Furthermore, if the transformed element is in the normal flow, it will scroll with the document and the fixed-position descendants will scroll with it.
It seem like that's the behavior I'm seeing, but that doesn't make any sense because the parent of the footer isn't being transformed... I'm applying the transform to the router, which is a sibling to the footer. Unless Vue is doing something else under the hood??
Here's a Vue example with the issue. I've added the transition classes by default to force the issue. http://s.codepen.io/chasebank/debug/QpYKeR
Here's an identical example with just raw html/css and no Vue, where everything behaves as expected without issue: http://s.codepen.io/chasebank/debug/VpgPZg
I'm seeing this in Chrome. You have to open Chrome dev tools device viewer and set it to a mobile device.
Ugh. After taking another look at this, it seems the same issue actually does show in the non-Vue example. It must have been a strange fluke/fatigue that lead me to believe otherwise. So this is purely a CSS issue and not caused by Vue.
Furthermore, I was able to finally find a fix after stumbling onto a stack overflow thread I've seen before but had forgotten.
When mobile browsers detect "viewport" as a meta property (ie <meta name="viewport" content="width=device-width, initial-scale=1">) they tend to ignore overflow rules on body and html for some reason. The solution is to add overflow styling to another wrapping element inside body. You also need to apply positioning to that element to get it to work. The positioning part is strange, but regardless, this fixes it:
#app {
position: fixed;
width: 100%;
height: 100%;
overflow-x: hidden
}
Most helpful comment
Ugh. After taking another look at this, it seems the same issue actually does show in the non-Vue example. It must have been a strange fluke/fatigue that lead me to believe otherwise. So this is purely a CSS issue and not caused by Vue.
Furthermore, I was able to finally find a fix after stumbling onto a stack overflow thread I've seen before but had forgotten.
When mobile browsers detect "viewport" as a meta property (ie
<meta name="viewport" content="width=device-width, initial-scale=1">) they tend to ignore overflow rules on body and html for some reason. The solution is to add overflow styling to another wrapping element inside body. You also need to apply positioning to that element to get it to work. The positioning part is strange, but regardless, this fixes it: