You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Jan 19, 2025. It is now read-only.
Copy file name to clipboardExpand all lines: _posts/2019-11-16-pull-to-refresh-web.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,7 +16,7 @@ authors: [fabrizio_duroni]
16
16
17
17
---
18
18
19
-
Some months ago I [transformed my website into a Progressive Web App]() (yes, the one you're reading now). By leveraging the power of service workers (and other some cool tricks that I will discuss in other posts :stuck_out_tongue_winking_eye:) my website page load time is below 50 milliseconds :open_mouth:. But with "the great power of service workers comes also great responsibility" (you remember [uncle Ben quote](https://www.google.com/search?q=from+great+power+comes+great+responsibility), right?), and one of this responsibility is let the user be able to refresh all the content whenever it wants (to check new/update stuff). Which is a mechanism/UX pattern that every user in the world already know for this kind of functionality? The [pull to refresh](https://en.wikipedia.org/wiki/Pull-to-refresh). The choice of this pattern is also a natural consequence of the fact that, as [I already told you previously in another post](), Progressive Web App are the technology that fill the gap between web and mobile native app. Unfortunately in the web development world there's not yet a standard component for pull to refresh. This is way in this post I will show you how to implement it from scratch without any JavaScript library/framework. I will only use vanilla JavaScript, HTML, CSS and the service worker *message* capabilities in combination with the `MessageChannel` class. The pull to refresh described in this article is available on this site in all the blog pages (including this one, try it now!!! :smirk:)
19
+
Some months ago I [transformed my website into a Progressive Web App](https://www.fabrizioduroni.it/2019/03/03/github-pages-progressive-web-app.html "pwa") (yes, the one you're reading now). By leveraging the power of service workers (and other some cool tricks that I will discuss in other posts :stuck_out_tongue_winking_eye:) my website page load time is below 50 milliseconds :open_mouth:. But with "the great power of service workers comes also great responsibility" (you remember [uncle Ben quote](https://www.google.com/search?q=from+great+power+comes+great+responsibility), right?), and one of this responsibility is let the user be able to refresh all the content whenever it wants (to check new/update stuff). Which is a mechanism/UX pattern that every user in the world already know for this kind of functionality? The [pull to refresh](https://en.wikipedia.org/wiki/Pull-to-refresh). The choice of this pattern is also a natural consequence of the fact that, as [I already told you previously in another post](), Progressive Web App are the technology that fill the gap between web and mobile native app. Unfortunately in the web development world there's not yet a standard component for pull to refresh. This is way in this post I will show you how to implement it from scratch without any JavaScript library/framework. I will only use vanilla JavaScript, HTML, CSS and the service worker *message* capabilities in combination with the `MessageChannel` class. The pull to refresh described in this article is available on this site in all the blog pages (including this one, try it now!!! :smirk:).
20
20
Let's start from the implementation of the UI (HTML and CSS)
21
21
22
22
#### UI: HTML and CSS
@@ -40,7 +40,7 @@ Below you can find the entire html code snippet.
40
40
</div>
41
41
```
42
42
43
-
Let's see what I did on the CSS side. The code reported below here is written in [SASS](https://en.wikipedia.org/wiki/Sass_(stylesheet_language)) (the preprocessor scripting language that is interpreted or compiled into Cascading Style Sheets (CSS)), but you can easily transform it in plain CSS if you need. First of I used a new CSS property in the `html` rule: `overscroll-behavior-y`. This property let the developers change the browser behaviour when the user researches the edge of the page with a scroll gesture. This is a property supported by Chrome, Firefox and Opera (fuck you Safari!!! :rage:). By setting it's value to `contains`, we can for example disable the native browser pull to refresh on Chrome and avoid the page bounce effect when the user starts to overflow the borders while dragging. Then I defined a property `pullable-content` that I used on the entire content of the page that I want to move in parallel with the pull to refresh. The next class is `pull-to-refresh` and contains all the styles needed to layout the pull to refresh in all its states. As you can see I defined all the animation I needed for this UI component here except for the translation applied while dragging that will be computed on the JavaScript side (because this are simple animation and [CSS is performant enough for this kind of animations](https://medium.com/outsystems-experts/how-to-achieve-60-fps-animations-with-css3-db7b98610108)). Last but not least I defined 2 classes to reset the pull to refresh layout status when the pull to refresh is started or has reached the end and starts the refresh of the content (they will be applied, like other contained here, with JavaScript DOM API).
43
+
Let's see what I did on the CSS side. The code reported below here is written in [SASS](https://en.wikipedia.org/wiki/Sass_(stylesheet_language)) (the preprocessor scripting language that is interpreted or compiled into Cascading Style Sheets (CSS)), but you can easily transform it in plain CSS if you need. First of all I used a new CSS property in the `html` rule: `overscroll-behavior-y`. This property let the developers change the browser behaviour when the user researches the edge of the page with a scroll gesture. This is a property supported by Chrome, Firefox and Opera (fuck you Safari!!! :rage:). By setting it's value to `contains`, we can for example disable the native browser pull to refresh on Chrome and avoid the page bounce effect when the user starts to overflow the borders while dragging. Then I defined a property `pullable-content` that I used on the entire content of the page that I want to move in parallel with the pull to refresh. The next class is `pull-to-refresh` and contains all the styles needed to layout the pull to refresh in all its states. As you can see I defined all the animation I needed for this UI component here except for the translation applied while dragging that will be computed on the JavaScript side (because this are simple animation and [CSS is performant enough for this kind of animations](https://medium.com/outsystems-experts/how-to-achieve-60-fps-animations-with-css3-db7b98610108)). Last but not least I defined 2 classes to reset the pull to refresh layout status when the pull to refresh is started or has reached the end and starts the refresh of the content (they will be applied, like other contained here, with JavaScript DOM API).
Then In the service worker I added a new `message` listener that receive all the messages sent with the function above. At the moment I have only the `refresh` message. This is why all the code to manage this message is contained inside it (just to explain the reason to the [clean code fluffy evangelist](https://twitter.com/dan_abramov/status/1190762799338790913):sweat_smile:). In the listener I check for the correctnes of the event label, and then I start to clean up the cache from all the assets and pages of the blog with (this is why for example the `createDeleteOperationsForImages` checks that the url contains the `posts` path, in order to avoid the deletion of home images). This delete cache function are all execute in a `Promise.all` call. When this function completes the execution of all the delete operation, I call `sendRefreshCompletedMessageToClient()` to warn the original JavaScript code (the `port1.onmessage` listener we saw above) that the refresh operation has been completed.
325
+
Then In the service worker I added a new `message` listener that receive all the messages sent with the function above. At the moment I have only the `refresh` message. This is why all the code to manage this message is contained inside it (just to explain the reason to the [clean code fluffy evangelist](https://twitter.com/dan_abramov/status/1190762799338790913):sweat_smile:). In the listener I check for the correctness of the event label, and then I start to clean up the cache from all the assets and pages of the blog with (this is why for example the `createDeleteOperationsForImages` checks that the url contains the `posts` path, in order to avoid the deletion of home images). This delete cache function are all execute in a `Promise.all` call. When this function completes the execution of all the delete operation, I call `sendRefreshCompletedMessageToClient()` to warn the original JavaScript code (the `port1.onmessage` listener we saw above) that the refresh operation has been completed.
0 commit comments