|
1 | | -<div class="async-iframe-wrapper"> |
2 | | - <div class="loader-container"> |
3 | | - <div class="loader"></div> |
| 1 | +<div class="async-iframe__wrapper"> |
| 2 | + <div class="async-iframe__loader-container"> |
| 3 | + <div class="async-iframe__loader"></div> |
4 | 4 | </div> |
5 | 5 |
|
6 | | - <div class="iframe-container"> |
| 6 | + <div class="async-iframe__container"> |
7 | 7 | <slot /> |
8 | 8 | </div> |
9 | 9 | </div> |
10 | 10 |
|
11 | 11 | <script> |
12 | | - function setupIframe() { |
13 | | - const wrapper = document.getElementsByClassName('async-iframe-wrapper')[0]; |
14 | | - const loaderContainer = wrapper.getElementsByClassName('loader-container')[0]; |
15 | | - const iframe = wrapper.querySelector('iframe'); |
16 | | - |
17 | | - if (iframe && loaderContainer) { |
18 | | - const handleLoad = () => { |
19 | | - loaderContainer.classList.add('hidden'); |
20 | | - iframe.removeEventListener('load', handleLoad); |
21 | | - }; |
22 | | - |
23 | | - iframe.addEventListener('load', handleLoad); |
| 12 | + function setupIframes() { |
| 13 | + const wrappers = document.getElementsByClassName('async-iframe__wrapper'); |
| 14 | + |
| 15 | + for (let i = 0; i < wrappers.length; i++) { |
| 16 | + const wrapper = wrappers[i]; |
| 17 | + const loaderContainer = wrapper.getElementsByClassName('async-iframe__loader-container')[0]; |
| 18 | + const iframe = wrapper.getElementsByTagName('iframe')[0]; |
| 19 | + |
| 20 | + if (iframe && loaderContainer) { |
| 21 | + const handleLoad = () => { |
| 22 | + loaderContainer.classList.add('async-iframe__hidden'); |
| 23 | + iframe.removeEventListener('load', handleLoad); |
| 24 | + }; |
| 25 | + |
| 26 | + iframe.addEventListener('load', handleLoad); |
| 27 | + } |
24 | 28 | } |
25 | 29 | } |
26 | 30 |
|
27 | 31 | if (document.readyState === 'loading') { |
28 | 32 | const handleDOMContentLoaded = () => { |
29 | | - setupIframe(); |
| 33 | + setupIframes(); |
30 | 34 | document.removeEventListener('DOMContentLoaded', handleDOMContentLoaded); |
31 | 35 | }; |
32 | 36 |
|
33 | 37 | document.addEventListener('DOMContentLoaded', handleDOMContentLoaded); |
34 | 38 | } else { |
35 | | - setupIframe(); |
| 39 | + setupIframes(); |
36 | 40 | } |
37 | 41 | </script> |
38 | 42 |
|
39 | 43 | <style> |
40 | | - .async-iframe-wrapper { |
| 44 | + .async-iframe__wrapper { |
41 | 45 | position: relative; |
42 | 46 | padding-top: 85%; |
43 | 47 | height: 0; |
44 | 48 | overflow: hidden; |
45 | 49 | } |
46 | 50 |
|
47 | | - .loader-container { |
| 51 | + .async-iframe__loader-container { |
48 | 52 | position: absolute; |
49 | | - top: 0; |
50 | | - left: 0; |
51 | | - right: 0; |
52 | | - bottom: 0; |
53 | | - display: flex; |
54 | | - align-items: center; |
55 | | - justify-content: center; |
56 | | - z-index: 10; |
| 53 | + inset: 0; |
| 54 | + display: grid; |
| 55 | + place-items: center; |
| 56 | + z-index: 5; |
| 57 | + background: rgba(255, 255, 255, 0.9); |
57 | 58 | } |
58 | 59 |
|
59 | | - .loader { |
| 60 | + .async-iframe__loader { |
60 | 61 | width: 2rem; |
61 | 62 | height: 2rem; |
62 | 63 | border-radius: 50%; |
63 | 64 | border: 0.125rem solid transparent; |
64 | 65 | border-top-color: #3b82f6; |
65 | | - animation: spin 1s linear infinite; |
| 66 | + animation: async-iframe__spin 1s linear infinite; |
66 | 67 | } |
67 | 68 |
|
68 | | - @keyframes spin { |
| 69 | + @keyframes async-iframe__spin { |
69 | 70 | 0% { transform: rotate(0deg); } |
70 | 71 | 100% { transform: rotate(360deg); } |
71 | 72 | } |
72 | 73 |
|
73 | | - .iframe-container { |
| 74 | + .async-iframe__container { |
74 | 75 | position: absolute; |
75 | | - top: 0px; |
76 | | - left: 0px; |
77 | | - right: 0px; |
78 | | - bottom: 0px; |
| 76 | + inset: 0; |
79 | 77 | } |
80 | 78 |
|
81 | 79 | :global(iframe) { |
82 | 80 | position: absolute; |
83 | | - top: 0px; |
84 | | - left: 0px; |
| 81 | + inset: 0; |
85 | 82 | width: 100%; |
86 | 83 | height: 100%; |
87 | | - border: 0px; |
| 84 | + border: 0; |
| 85 | + opacity: 0; |
| 86 | + transition: opacity 0.3s ease-in-out; |
88 | 87 | } |
89 | 88 |
|
90 | | - .hidden { |
| 89 | + .async-iframe__hidden { |
91 | 90 | display: none !important; |
92 | 91 | } |
| 92 | + |
| 93 | + .async-iframe__hidden + .async-iframe__container :global(iframe) { |
| 94 | + opacity: 1; |
| 95 | + } |
93 | 96 | </style> |
0 commit comments