├── test.html ├── style.css └── main.js /test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Multiple windows view 7 | 8 | 9 | 10 |
11 |
12 |
13 |
14 |

Drag the resizers to change width and height of the windows.

15 |

😊😉

16 |
17 |
18 |
19 | 24 |
25 |
26 |
27 |
28 |
29 | 30 |
31 |
32 |
33 | 34 |
35 |
36 |
37 |
38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | width: 100vw; 4 | height: 100vh; 5 | margin: 0; 6 | border: 0; 7 | padding: 0; 8 | -webkit-box-sizing: border-box; 9 | -moz-box-sizing: border-box; 10 | box-sizing: border-box; 11 | } 12 | 13 | *, 14 | *::before, 15 | *::after { 16 | -webkit-box-sizing: inherit; 17 | -moz-box-sizing: inherit; 18 | box-sizing: inherit; 19 | } 20 | 21 | #app { 22 | width: 100%; 23 | height: 100%; 24 | 25 | font-family: Arial, Helvetica, sans-serif; 26 | } 27 | 28 | .resizable-x, 29 | .resizable-y { 30 | display: flex; 31 | overflow: hidden; 32 | } 33 | 34 | .resizable-x { 35 | height: 100%; 36 | } 37 | 38 | .resizable-y { 39 | flex-direction: column; 40 | } 41 | 42 | .resizer-x, 43 | .resizer-y { 44 | position: relative; 45 | display: flex; 46 | justify-content: center; 47 | align-items: center; 48 | background: black; 49 | padding: 4px; 50 | } 51 | 52 | .resizer-x { 53 | z-index: 2; 54 | cursor: col-resize; 55 | } 56 | .resizer-x::before, 57 | .resizer-x::after { 58 | content: ''; 59 | width: 1px; 60 | height: 16px; 61 | margin: 2px; 62 | background: lightgray; 63 | } 64 | 65 | .resizer-y { 66 | z-index: 1; 67 | cursor: row-resize; 68 | flex-direction: column; 69 | } 70 | .resizer-y::before, 71 | .resizer-y::after { 72 | content: ''; 73 | width: 16px; 74 | height: 1px; 75 | margin: 2px; 76 | background: lightgray; 77 | } 78 | 79 | .img-container { 80 | overflow: hidden; 81 | height: 100%; 82 | width: 100%; 83 | display: flex; 84 | justify-content: center; 85 | align-items: center; 86 | } 87 | .img-container img { 88 | overflow: hidden; 89 | height: 100%; 90 | width: 100%; 91 | } 92 | .img-container iframe { 93 | overflow: hidden; 94 | height: 100%; 95 | width: 100%; 96 | /* z-index: -1; */ 97 | } 98 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | // horizontal direction 3 | (function resizableX() { 4 | const resizers = document.querySelectorAll('.resizer-x'); 5 | resizers.forEach((resizer) => { 6 | resizer.addEventListener('mousedown', onmousedown); 7 | resizer.addEventListener('touchstart', ontouchstart); 8 | 9 | // for mobile 10 | function ontouchstart(e) { 11 | e.preventDefault(); 12 | document.querySelectorAll('iframe').forEach((item) => (item.style.zIndex = -1)); 13 | resizer.addEventListener('touchmove', ontouchmove); 14 | resizer.addEventListener('touchend', ontouchend); 15 | } 16 | function ontouchmove(e) { 17 | e.preventDefault(); 18 | const clientX = e.touches[0].clientX; 19 | const deltaX = clientX - (resizer._clientX || clientX); 20 | resizer._clientX = clientX; 21 | const l = resizer.previousElementSibling; 22 | const r = resizer.nextElementSibling; 23 | // LEFT 24 | if (deltaX < 0) { 25 | const w = Math.round(parseInt(getComputedStyle(l).width) + deltaX); 26 | l.style.flex = `0 ${w < 10 ? 0 : w}px`; 27 | r.style.flex = '1 0'; 28 | } 29 | // RIGHT 30 | if (deltaX > 0) { 31 | const w = Math.round(parseInt(getComputedStyle(r).width) - deltaX); 32 | r.style.flex = `0 ${w < 10 ? 0 : w}px`; 33 | l.style.flex = '1 0'; 34 | } 35 | } 36 | function ontouchend(e) { 37 | e.preventDefault(); 38 | document.querySelectorAll('iframe').forEach((item) => (item.style.zIndex = 1)); 39 | resizer.removeEventListener('touchmove', ontouchmove); 40 | resizer.removeEventListener('touchend', ontouchend); 41 | delete e._clientX; 42 | } 43 | 44 | // for desktop 45 | function onmousedown(e) { 46 | e.preventDefault(); 47 | document.querySelectorAll('iframe').forEach((item) => (item.style.zIndex = -1)); 48 | document.addEventListener('mousemove', onmousemove); 49 | document.addEventListener('mouseup', onmouseup); 50 | } 51 | function onmousemove(e) { 52 | e.preventDefault(); 53 | const clientX = e.clientX; 54 | const deltaX = clientX - (resizer._clientX || clientX); 55 | resizer._clientX = clientX; 56 | const l = resizer.previousElementSibling; 57 | const r = resizer.nextElementSibling; 58 | // LEFT 59 | if (deltaX < 0) { 60 | const w = Math.round(parseInt(getComputedStyle(l).width) + deltaX); 61 | l.style.flex = `0 ${w < 10 ? 0 : w}px`; 62 | r.style.flex = '1 0'; 63 | } 64 | // RIGHT 65 | if (deltaX > 0) { 66 | const w = Math.round(parseInt(getComputedStyle(r).width) - deltaX); 67 | r.style.flex = `0 ${w < 10 ? 0 : w}px`; 68 | l.style.flex = '1 0'; 69 | } 70 | } 71 | function onmouseup(e) { 72 | e.preventDefault(); 73 | document.querySelectorAll('iframe').forEach((item) => (item.style.zIndex = 1)); 74 | document.removeEventListener('mousemove', onmousemove); 75 | document.removeEventListener('mouseup', onmouseup); 76 | delete e._clientX; 77 | } 78 | }); 79 | })(); 80 | 81 | // vertical direction 82 | (function resizableY() { 83 | const resizers = document.querySelectorAll('.resizer-y'); 84 | resizers.forEach((resizer) => { 85 | resizer.addEventListener('mousedown', onmousedown); 86 | resizer.addEventListener('touchstart', ontouchstart); 87 | 88 | // for mobile 89 | function ontouchstart(e) { 90 | e.preventDefault(); 91 | document.querySelectorAll('iframe').forEach((item) => (item.style.zIndex = -1)); 92 | resizer.addEventListener('touchmove', ontouchmove); 93 | resizer.addEventListener('touchend', ontouchend); 94 | } 95 | function ontouchmove(e) { 96 | e.preventDefault(); 97 | const clientY = e.touches[0].clientY; 98 | const deltaY = clientY - (resizer._clientY || clientY); 99 | resizer._clientY = clientY; 100 | const t = resizer.previousElementSibling; 101 | const b = resizer.nextElementSibling; 102 | // UP 103 | if (deltaY < 0) { 104 | const h = Math.round(parseInt(getComputedStyle(t).height) + deltaY); 105 | t.style.flex = `0 ${h < 10 ? 0 : h}px`; 106 | b.style.flex = '1 0'; 107 | } 108 | // DOWN 109 | if (deltaY > 0) { 110 | const h = Math.round(parseInt(getComputedStyle(b).height) - deltaY); 111 | b.style.flex = `0 ${h < 10 ? 0 : h}px`; 112 | t.style.flex = '1 0'; 113 | } 114 | } 115 | function ontouchend(e) { 116 | e.preventDefault(); 117 | document.querySelectorAll('iframe').forEach((item) => (item.style.zIndex = 1)); 118 | resizer.removeEventListener('touchmove', ontouchmove); 119 | resizer.removeEventListener('touchend', ontouchend); 120 | delete e._clientY; 121 | } 122 | 123 | // for desktop 124 | function onmousedown(e) { 125 | e.preventDefault(); 126 | document.querySelectorAll('iframe').forEach((item) => (item.style.zIndex = -1)); 127 | document.addEventListener('mousemove', onmousemove); 128 | document.addEventListener('mouseup', onmouseup); 129 | } 130 | function onmousemove(e) { 131 | e.preventDefault(); 132 | const clientY = e.clientY; 133 | const deltaY = clientY - (resizer._clientY || clientY); 134 | resizer._clientY = clientY; 135 | const t = resizer.previousElementSibling; 136 | const b = resizer.nextElementSibling; 137 | // UP 138 | if (deltaY < 0) { 139 | const h = Math.round(parseInt(getComputedStyle(t).height) + deltaY); 140 | t.style.flex = `0 ${h < 10 ? 0 : h}px`; 141 | b.style.flex = '1 0'; 142 | } 143 | // DOWN 144 | if (deltaY > 0) { 145 | const h = Math.round(parseInt(getComputedStyle(b).height) - deltaY); 146 | b.style.flex = `0 ${h < 10 ? 0 : h}px`; 147 | t.style.flex = '1 0'; 148 | } 149 | } 150 | function onmouseup(e) { 151 | e.preventDefault(); 152 | document.querySelectorAll('iframe').forEach((item) => (item.style.zIndex = 1)); 153 | document.removeEventListener('mousemove', onmousemove); 154 | document.removeEventListener('mouseup', onmouseup); 155 | delete e._clientY; 156 | } 157 | }); 158 | })(); 159 | })(); 160 | --------------------------------------------------------------------------------