fix jerky scrolling on Safari
This commit is contained in:
parent
2bd553d64c
commit
7582f34d24
|
@ -1,8 +1,10 @@
|
||||||
<Nav page={{page}} />
|
<Nav page={{page}} />
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
<main>
|
<main>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</main>
|
</main>
|
||||||
|
</div>
|
||||||
<script>
|
<script>
|
||||||
import Nav from './Nav.html';
|
import Nav from './Nav.html';
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<style>
|
<style>
|
||||||
.loading-page {
|
.loading-page {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 40vh;
|
min-height: 50vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
will-change: transform; /* avoids "repaints on scroll" for fixed position header */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<:Window bind:scrollY='scrollY' bind:innerHeight='innerHeight'/>
|
<:Window bind:innerHeight='innerHeight'/>
|
||||||
<div class="virtual-list" ref:node style="height: {{$height}}px;">
|
<div class="virtual-list" style="height: {{$height}}px;">
|
||||||
<!-- <div class="virtual-list-viewport" ref:viewport></div> -->
|
<!-- <div class="virtual-list-viewport" ref:viewport></div> -->
|
||||||
{{#each $visibleItems as item @key}}
|
{{#each $visibleItems as item @key}}
|
||||||
<VirtualListItem :component
|
<VirtualListItem :component
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
import { virtualListStore } from '../_utils/virtualListStore'
|
import { virtualListStore } from '../_utils/virtualListStore'
|
||||||
import debounce from 'lodash/debounce'
|
import debounce from 'lodash/debounce'
|
||||||
|
|
||||||
const DEBOUNCE_TIME = 200
|
const DEBOUNCE_TIME = 500
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
oncreate () {
|
oncreate () {
|
||||||
|
@ -35,12 +35,16 @@
|
||||||
'items': items
|
'items': items
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
this.observe('scrollY', debounce((scrollY) => {
|
document.body.querySelector('.container').addEventListener('scroll', debounce((e) => {
|
||||||
console.log('setting scrollY', scrollY)
|
|
||||||
this.store.set({
|
this.store.set({
|
||||||
scrollTop: scrollY
|
scrollTop: e.target.scrollTop
|
||||||
})
|
})
|
||||||
}, DEBOUNCE_TIME))
|
}, DEBOUNCE_TIME, {
|
||||||
|
leading: true,
|
||||||
|
trailing: true
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
ondestroy () {
|
||||||
},
|
},
|
||||||
data: () => ({
|
data: () => ({
|
||||||
component: null
|
component: null
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
.virtual-list-item {
|
.virtual-list-item {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
will-change: transform;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import { Store } from 'svelte/store.js'
|
import { Store } from 'svelte/store.js'
|
||||||
|
|
||||||
const RENDER_BUFFER = 1000
|
|
||||||
|
|
||||||
class VirtualListStore extends Store {
|
class VirtualListStore extends Store {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +12,7 @@ const virtualListStore = new VirtualListStore({
|
||||||
virtualListStore.compute('visibleItems',
|
virtualListStore.compute('visibleItems',
|
||||||
['items', 'scrollTop', 'height', 'itemHeights', 'innerHeight'],
|
['items', 'scrollTop', 'height', 'itemHeights', 'innerHeight'],
|
||||||
(items, scrollTop, height, itemHeights, innerHeight) => {
|
(items, scrollTop, height, itemHeights, innerHeight) => {
|
||||||
|
let renderBuffer = 2 * innerHeight
|
||||||
let visibleItems = []
|
let visibleItems = []
|
||||||
let totalOffset = 0
|
let totalOffset = 0
|
||||||
let len = items.length
|
let len = items.length
|
||||||
|
@ -26,11 +25,11 @@ virtualListStore.compute('visibleItems',
|
||||||
//console.log(key, 'scrollTop', scrollTop, 'currentOffset', currentOffset, 'innerHeight', innerHeight)
|
//console.log(key, 'scrollTop', scrollTop, 'currentOffset', currentOffset, 'innerHeight', innerHeight)
|
||||||
let isBelowViewport = (currentOffset < scrollTop)
|
let isBelowViewport = (currentOffset < scrollTop)
|
||||||
if (isBelowViewport) {
|
if (isBelowViewport) {
|
||||||
if (scrollTop - RENDER_BUFFER > currentOffset) {
|
if (scrollTop - renderBuffer > currentOffset) {
|
||||||
continue // below the area we want to render
|
continue // below the area we want to render
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (currentOffset > (scrollTop + innerHeight + RENDER_BUFFER)) {
|
if (currentOffset > (scrollTop + innerHeight + renderBuffer)) {
|
||||||
break // above the area we want to render
|
break // above the area we want to render
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,11 @@ body {
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
color: var(--body-text-color);
|
color: var(--body-text-color);
|
||||||
background: var(--body-bg);
|
background: var(--body-bg);
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#svelte {
|
#svelte {
|
||||||
|
@ -12,21 +17,30 @@ body {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
main {
|
.container {
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
|
position: absolute;
|
||||||
|
top: 72px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
will-change: transform; /* avoids "repaint on scroll" in Chrome */
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
position: relative;
|
position: relative;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
padding: 15px 15px;
|
padding: 15px 15px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin: 85px auto 15px;
|
margin: 15px auto 15px;
|
||||||
background: var(--main-bg);
|
background: var(--main-bg);
|
||||||
border: 1px solid var(--main-border);
|
border: 1px solid var(--main-border);
|
||||||
border-radius: 1px;
|
border-radius: 1px;
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
padding: 5px 5px;
|
padding: 5px 5px;
|
||||||
margin: 75px auto 15px;
|
margin: 5px auto 15px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<style>
|
<style>
|
||||||
/* auto-generated w/ build-sass.js */
|
/* auto-generated w/ build-sass.js */
|
||||||
:root{--button-primary-bg:#6081e6;--button-primary-text:#fff;--button-primary-border:#132c76;--button-primary-bg-active:#456ce2;--button-primary-bg-hover:#6988e7;--button-bg:#e6e6e6;--button-text:#333;--button-border:#a7a7a7;--button-bg-active:#bfbfbf;--button-bg-hover:#f2f2f2;--input-border:#dadada;--anchor-text:#4169e1;--main-bg:#fff;--body-bg:#e8edfb;--body-text-color:#333;--main-border:#dadada;--svg-fill:#4169e1;--form-bg:#f7f7f7;--form-border:#c1c1c1;--nav-bg:#4169e1;--nav-border:#214cce;--nav-a-border:#4169e1;--nav-a-selected-border:#fff;--nav-a-selected-bg:#6d8ce8;--nav-svg-fill:#fff;--nav-text-color:#fff;--nav-a-selected-border-hover:#fff;--nav-a-selected-bg-hover:#839deb;--nav-a-bg-hover:#577ae4;--nav-a-border-hover:#4169e1;--nav-svg-fill-hover:#fff;--nav-text-color-hover:#fff;--action-button-fill-color:#839deb;--action-button-fill-color-hover:#99afef;--action-button-fill-color-active:#577ae4;--settings-list-item-bg:#fff;--settings-list-item-text:#4169e1;--settings-list-item-text-hover:#4169e1;--settings-list-item-border:#dadada;--settings-list-item-bg-active:#e6e6e6;--settings-list-item-bg-hover:#fafafa;--toast-bg:#333;--toast-border:#fafafa;--toast-text:#fff;--mask-bg:#333;--mask-svg-fill:#fff;--deemphasized-text-color:#666}
|
:root{--button-primary-bg:#6081e6;--button-primary-text:#fff;--button-primary-border:#132c76;--button-primary-bg-active:#456ce2;--button-primary-bg-hover:#6988e7;--button-bg:#e6e6e6;--button-text:#333;--button-border:#a7a7a7;--button-bg-active:#bfbfbf;--button-bg-hover:#f2f2f2;--input-border:#dadada;--anchor-text:#4169e1;--main-bg:#fff;--body-bg:#e8edfb;--body-text-color:#333;--main-border:#dadada;--svg-fill:#4169e1;--form-bg:#f7f7f7;--form-border:#c1c1c1;--nav-bg:#4169e1;--nav-border:#214cce;--nav-a-border:#4169e1;--nav-a-selected-border:#fff;--nav-a-selected-bg:#6d8ce8;--nav-svg-fill:#fff;--nav-text-color:#fff;--nav-a-selected-border-hover:#fff;--nav-a-selected-bg-hover:#839deb;--nav-a-bg-hover:#577ae4;--nav-a-border-hover:#4169e1;--nav-svg-fill-hover:#fff;--nav-text-color-hover:#fff;--action-button-fill-color:#839deb;--action-button-fill-color-hover:#99afef;--action-button-fill-color-active:#577ae4;--settings-list-item-bg:#fff;--settings-list-item-text:#4169e1;--settings-list-item-text-hover:#4169e1;--settings-list-item-border:#dadada;--settings-list-item-bg-active:#e6e6e6;--settings-list-item-bg-hover:#fafafa;--toast-bg:#333;--toast-border:#fafafa;--toast-text:#fff;--mask-bg:#333;--mask-svg-fill:#fff;--deemphasized-text-color:#666}
|
||||||
body{margin:0;font-family:system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue;font-size:14px;line-height:1.3;color:var(--body-text-color);background:var(--body-bg)}#svelte{display:flex;flex-direction:column}main{overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch;position:relative;max-width:600px;padding:15px 15px;box-sizing:border-box;margin:85px auto 15px;background:var(--main-bg);border:1px solid var(--main-border);border-radius:1px}@media (max-width: 767px){main{padding:5px 5px;margin:75px auto 15px}}h1,h2,h3,h4,h5,h6{margin:0 0 0.5em 0;font-weight:400;line-height:1.2}h1{font-size:2em}a{color:var(--anchor-text);text-decoration:none}a:visited{color:var(--anchor-text)}a:hover{text-decoration:underline}input{border:1px solid var(--input-border);padding:5px}button{font-size:1.2em;background:var(--button-bg);border-radius:2px;padding:10px 15px;border:1px solid var(--button-border);cursor:pointer;color:var(--button-text)}button:hover{background:var(--button-bg-hover)}button:active{background:var(--button-bg-active)}button[disabled]{opacity:0.35;pointer-events:none;cursor:not-allowed}button.primary{border:1px solid var(--button-primary-border);background:var(--button-primary-bg);color:var(--button-primary-text)}button.primary:hover{background:var(--button-primary-bg-hover)}button.primary:active{background:var(--button-primary-bg-active)}p,label,input{font-size:1.3em}ul,li,p{padding:0;margin:0}.hidden{opacity:0}
|
body{margin:0;font-family:system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue;font-size:14px;line-height:1.3;color:var(--body-text-color);background:var(--body-bg);position:fixed;left:0;right:0;bottom:0;top:0}#svelte{display:flex;flex-direction:column}.container{overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;position:absolute;top:72px;left:0;right:0;bottom:0;will-change:transform}main{position:relative;max-width:600px;padding:15px 15px;box-sizing:border-box;margin:15px auto 15px;background:var(--main-bg);border:1px solid var(--main-border);border-radius:1px}@media (max-width: 767px){main{padding:5px 5px;margin:5px auto 15px}}h1,h2,h3,h4,h5,h6{margin:0 0 0.5em 0;font-weight:400;line-height:1.2}h1{font-size:2em}a{color:var(--anchor-text);text-decoration:none}a:visited{color:var(--anchor-text)}a:hover{text-decoration:underline}input{border:1px solid var(--input-border);padding:5px}button{font-size:1.2em;background:var(--button-bg);border-radius:2px;padding:10px 15px;border:1px solid var(--button-border);cursor:pointer;color:var(--button-text)}button:hover{background:var(--button-bg-hover)}button:active{background:var(--button-bg-active)}button[disabled]{opacity:0.35;pointer-events:none;cursor:not-allowed}button.primary{border:1px solid var(--button-primary-border);background:var(--button-primary-bg);color:var(--button-primary-text)}button.primary:hover{background:var(--button-primary-bg-hover)}button.primary:active{background:var(--button-primary-bg-active)}p,label,input{font-size:1.3em}ul,li,p{padding:0;margin:0}.hidden{opacity:0}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue