|
11 | 11 | authors: [fabrizio_duroni] |
12 | 12 | --- |
13 | 13 |
|
14 | | -*Implementing a pull to refresh component in vanilla js for your progressive web app (PWA) it's really easy. Let's do it now!* |
| 14 | +*Implementing a pull to refresh component in vanilla js for your progressive web app (PWA) it's really easy using cutting edge web technology (service worker, CSS new properties). Let's do it now!* |
15 | 15 |
|
16 | 16 | --- |
17 | 17 |
|
18 | | -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 responsability 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 choise 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* capability with `postMessage` and `MessageChannel` class. |
| 18 | +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* capability with `postMessage` and `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 | 19 | Let's start from the implementation of the UI (HTML and CSS) |
20 | 20 |
|
21 | 21 | #### UI: HTML and CSS |
22 | 22 |
|
| 23 | +You already know what we would like to achieve. The pull to refresh UI component should be something that appears at the top of the page when the user scroll beyond the page borders. At some point during the drag gesture the pull to refresh should stop itself from scrolling and show a loader that explain to the user that the content is reloading. |
| 24 | +Let's start from the HTML. I added to the page structure a new div that will act as the container of the pull to refresh. |
| 25 | +Inside it I added two other divs: |
| 26 | + |
| 27 | +* one is used to show a loader/activity indicator that will start to rotate as soon as the user scroll to the maximum pull to refresh point (and as already explained above, at this point the reload of the content should have been started). |
| 28 | + |
| 29 | +* the other one is used to show a message to the user that explaing to him/her what it is happening (this is a nice to have that I added because I liked it! :XXXXXX:) |
| 30 | + |
| 31 | +Below you can find the entire html code snippet. |
| 32 | + |
| 33 | +```html |
| 34 | +<div id="pull-to-refresh" class="pull-to-refresh start-pull hidden-pull"> |
| 35 | + <div id="pull-to-refresh-loader" class="pull-to-refresh-loader"></div> |
| 36 | + <div id="pull-to-refresh-status" class="pull-to-refresh-status"> |
| 37 | + Pull down to refresh |
| 38 | + </div> |
| 39 | +</div> |
| 40 | +``` |
| 41 | + |
| 42 | +Let's see what I did on the CSS side. ..... |
| 43 | + |
| 44 | +```scss |
| 45 | +html { |
| 46 | + overscroll-behavior-y: contain; |
| 47 | +} |
| 48 | + |
| 49 | +.pullable-content { |
| 50 | + margin-top: 10px |
| 51 | +} |
| 52 | + |
| 53 | +.pull-to-refresh { |
| 54 | + height: 100px; |
| 55 | + background-color: $general-background; |
| 56 | + margin-top: 55px; |
| 57 | + margin-bottom: 10px; |
| 58 | + box-shadow: inset 0px -2px 6px 1px $divider-color; |
| 59 | + display: flex; |
| 60 | + flex-direction: column; |
| 61 | + justify-content: flex-end; |
| 62 | + align-items: center; |
| 63 | + padding: 10px; |
| 64 | + |
| 65 | + &.visible-pull { |
| 66 | + visibility: visible; |
| 67 | + } |
| 68 | + |
| 69 | + &.hidden-pull { |
| 70 | + visibility: hidden; |
| 71 | + } |
| 72 | + |
| 73 | + .pull-to-refresh-status { |
| 74 | + font-weight: bold; |
| 75 | + font-size: 14px; |
| 76 | + } |
| 77 | + |
| 78 | + .pull-to-refresh-loader { |
| 79 | + border: 3px solid $primary-color-dark; |
| 80 | + border-top: 3px solid $primary-color-light; |
| 81 | + border-radius: 50%; |
| 82 | + width: 30px; |
| 83 | + height: 30px; |
| 84 | + margin-bottom: 10px; |
| 85 | + opacity: 0; |
| 86 | + |
| 87 | + &.animate { |
| 88 | + animation: spin 1.25s linear infinite; |
| 89 | + } |
| 90 | + |
| 91 | + @keyframes spin { |
| 92 | + 0% { transform: rotate(0deg); } |
| 93 | + 100% { transform: rotate(360deg); } |
| 94 | + } |
| 95 | + } |
| 96 | +} |
| 97 | + |
| 98 | +.start-pull { |
| 99 | + transform: translateY(-100px); |
| 100 | +} |
| 101 | + |
| 102 | +.end-pull { |
| 103 | + transform: translateY(-100px) !important; |
| 104 | + transition: 0.4s ease-in-out; |
| 105 | +} |
| 106 | +``` |
23 | 107 |
|
24 | 108 | #### JavaScript |
25 | 109 |
|
|
0 commit comments