はじめに
以前の投稿からの iOS15 への対応となりますので、こちらもご参照ください。
また、参考にさせていただいてるkrpanoがバージョンアップし、iOS15でのフルスクリーン表示に対応されました。
やってみるしかない
サンプルコード
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, viewport-fit=cover" />
<style >
:root { --sat: env(safe-area-inset-top); --sar: env(safe-area-inset-right); --sab: env(safe-area-inset-bottom); --sal: env(safe-area-inset-left); }
* { margin:0; padding:0 }
html, body { height:calc(100% + var(--sab)) }
body { font-family:sans-serif; color:#fff }
#fs { position:absolute; display:none; justify-content:center; align-items:center; width:100%; height:100%; background-color:RGBA(0,0,0,0.8) }
#fsd { position:absolute; z-index:-2; width:100%; height:100vw; touch-action:pan-y }
#container { position:fixed; z-index:1; width:100%; height:100%; background-color:#b1dff7; touch-action:none; transform:translateZ(0) }
#container p { position:absolute; width:40px; height:40px; background-color:#fff }
#container p:nth-child(1) { left:5px; top:5px; margin-left:var(--sal) }
#container p:nth-child(2) { top:5px; right:5px; margin-right:var(--sar) }
#container p:nth-child(3) { right:5px; bottom:5px; margin-right:var(--sar); margin-bottom:var(--sab) }
#container p:nth-child(4) { bottom:5px; left:5px; margin-bottom:var(--sab); margin-left:var(--sal) }
@media ( orientation:landscape ){
#container p:nth-child(n+3) { margin-bottom:0 }
}
</style>
</head>
<body>
<div id="container">
<p></p>
<p></p>
<p></p>
<p></p>
</div>
<script>
let _ua = navigator.userAgent.toLowerCase(),
_container = document.querySelector('#container');
if ( (/iphone/.test(_ua)) && !(/crios|edgios/.test(_ua)) ){
var _fs = document.createElement('div'),
_fsd = document.createElement('div');
_fs.id = 'fs';
_fs.innerHTML = '↑ SWIPE';
_container.appendChild(_fs);
_fsd.id = 'fsd';
document.body.insertBefore(_fsd, _container);
document.addEventListener( 'DOMContentLoaded', fs_display );
window.addEventListener( 'resize', fs_display );
function fs_display() {
if ( window.orientation == 0 ) {
_container.style.height = '100%';
_fs.style.display = 'none';
} else {
_container.style.height = '100vh';
if ( screen.width - window.innerHeight <= 20 ) {
_fs.style.display = 'none';
_fsd.style.zIndex = '-2';
} else if ( screen.width - window.innerHeight > 20 ) {
_fs.style.display = 'flex';
_fsd.style.zIndex = '2';
window.scrollTo(0, 0);
}
}
}
}
</script>
</body>
</html>
> 構造(変更箇所)
<body>
<div id="fsd"></div>
<div id="container">
// Your contents.
<div id="fs">↑ SWIPE</div>
</div>
</body>
↑ SWIPE
を表示するdiv#fs
をdiv#container
内に、スワイプする為の空要素としてdiv#fsd
をdiv#container
外に分けた構造とします。
html, body { height:calc(100% + env(safe-area-inset-bottom)) }
#fs { position:absolute; display:none; justify-content:center; align-items:center; width:100%; height:100%; background-color:RGBA(0,0,0,0.8) }
#fsd { position:absolute; z-index:-2; width:100%; height:100vw; touch-action:pan-y }
#container { position:fixed; z-index:1; width:100%; height:100%; background-color:#b1dff7; touch-action:none; transform:translateZ(0) }
div#container
をposition:fixed
とし、html,body
にはheight:calc(100% + env(safe-area-inset-bottom))
、div#fsd
はheight:100vw
を設定します。
div#fsd
はtouch-action:pan-y
、div#contaner
はtouch-action:none
とし制限をかけるのは変わりません。
div#fsd
をheight:100vw
とすることで、portrait時には邪魔にならずlandscape時にはスワイプする為の要素となります。
div#container
にtransform:translateZ(0)
を設定することで、position:fixed
でも非表示領域をレンダリングしてくれます。
設定からの文字サイズ変更には対応しておりますが、ブラウザ側での文字サイズ変更には対応しておりません。
> 制御(変更箇所)
let _ua = navigator.userAgent.toLowerCase(),
_container = document.querySelector('#container');
if ( (/iphone/.test(_ua)) && !(/crios|edgios/.test(_ua)) ){
var _fs = document.createElement('div'),
+ _fsd = document.createElement('div');
_fs.id = 'fs';
_fs.innerHTML = '↑ SWIPE';
_container.appendChild(_fs);
+ _fsd.id = 'fsd';
+ document.body.insertBefore(_fsd, _container);
document.addEventListener( 'DOMContentLoaded', fs_display );
window.addEventListener( 'resize', fs_display );
function fs_display() {
if ( window.orientation == 0 ) {
+ _container.style.height = '100%';
_fs.style.display = 'none';
} else {
+ _container.style.height = '100vh';
if ( screen.width - window.innerHeight <= 20 ) {
_fs.style.display = 'none';
+ _fsd.style.zIndex = '-2';
} else if ( screen.width - window.innerHeight > 20 ) {
_fs.style.display = 'flex';
+ _fsd.style.zIndex = '2';
+ window.scrollTo(0, 0);
}
}
}
}
div#container
はportrait時height:100%
、landscape時height:100vh
となるよう制御し、div#fsd
の表示・非表示をz-index
で制御しコンテンツの高さを保つことで上部バーの再表示を防ぎます。
window.scrollTo(0, 0)
でスクロール状態をリセットすることで、上方向スワイプのみの操作でバーを隠せるようになりました。
まとめ
下部セーフエリア周りの仕様が、、safe-area-inset-bottom
のサイズと実際のタップ範囲が違う、、のか、、ツールバーのサイズは1rem + env(safe-area-inset-bottom)
ということらしく、タップ範囲となるっぽいのだが、、下のタブバー表示でツールバー非表示にするとタップ範囲は併せて狭くなってくれるの、、、だが、上部アドレスバー表示の時は変わらない、、、んだ。