Панель виджета мобильного чата сжимается, а заголовок/композитор Misaligns, когда открывается клавиатура (iOS Safari & AJavascript

Форум по Javascript
Ответить
Anonymous
 Панель виджета мобильного чата сжимается, а заголовок/композитор Misaligns, когда открывается клавиатура (iOS Safari & A

Сообщение Anonymous »

Я строю пользовательский виджет чата в JavaScript (аналогично мессенджеру на странице). Виджет прикрепляет как фиксированную панель с липким заголовком, прокручиваемым потоком сообщений и композитором внизу.
Проблема возникает на мобильном телефоне, когда клавиатура открывается:
on Android Chrome:
Paneling Shroinks, когда клавиша opens opens. Pers. Pr/Pr/Prinks Paneling. Страница становится видимой за панелью.
Если адресная полоска анимирует (верхняя/внизу), высота панели прыгает. Animate.
Иногда композитор перебирает или недооценивает клавиатуру.
Что я попробовал
100 В, 100dvh, 100svh → панель по -прежнему сжимается на клавиатуре. Запасная сторона: < /p>
const vv = window.visualViewport;
const large = vv.height + (vv.offsetTop || 0);
panel.style.setProperty('--lvh', (large/100) + 'px');

Прокрутка страницы блокировки, когда виджет, открыт. /> На сафари для iOS заголовок иногда перестает быть липкой, а панель все еще дрожит. /> должен работать как на Android Chrome (Address Bar Top/снизу), так и в iOS Safari (новые и старые версии).
Вопрос
Какой самый надежный рисунок (CSS + JS), чтобы сохранить фиксированную ширину чата:
Полная высота. /> с липким заголовком и нижним композитором, которые правильно приспосабливаются, < /p>
как на Android Chrome, так и на Safari IOS, < /p>
, не полагаясь на ua-sniff chacks?
OAT Clinic






css
Copy code
:root {
/* Large viewport height (JS sets this var) */
--lvh: 1vh;
/* Keyboard overlap (JS sets this var) */
--kb: 0px;
}

/* Fullscreen panel that should NOT shrink when keyboard opens */
.panel {
position: fixed;
inset: 0;
height: calc(var(--lvh) * 100); /* prefer LVH when available */
display: flex;
flex-direction: column;
background: #f7f8fb;
overflow: hidden;
}

.head {
position: sticky;
top: 0;
z-index: 1;
padding: 9px 13px;
background: white;
border-bottom: 1px solid #e5e7eb;
}

.stream {
flex: 1 1 auto;
min-height: 0; /* critical for mobile scrolling */
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}

.composer {
position: sticky; /* stays at bottom of panel */
bottom: 0;
border-top: 1px solid #e5e7eb;
background: #f7f8fb;
/* Lift above keyboard (JS sets --kb) */
transform: translateY(calc(-1 * var(--kb)));
}

textarea {
width: 100%;
min-height: 54px;
max-height: 120px;
border: 1px solid #E1E1E1;
border-radius: 12px;
margin: 8px;
padding: 8px 10px;
resize: none;
}
js
Copy code
// Robust LVH + keyboard offset calculation
(function () {
const panel = document.getElementById('panel');
const composer = document.getElementById('composer');
const msg = document.getElementById('msg');

// Use Large Viewport Height when supported; JS fallback otherwise.
function setLVH() {
const vv = window.visualViewport;
const large = vv ? (vv.height + (vv.offsetTop || 0)) : window.innerHeight;

// Extra fallback using physical screen size for iOS quirks
const alt = (window.screen && window.screen.height && window.devicePixelRatio)
? (window.screen.height / window.devicePixelRatio)
: large;

const lvh = Math.max(large, alt) / 100; // 1% unit
panel.style.setProperty('--lvh', lvh + 'px');
}

let baseVVH = null; // visible height baseline (without keyboard)
function setBaseVVH() {
const vv = window.visualViewport;
baseVVH = vv ? vv.height : window.innerHeight;
}

function computeKeyboardOffset() {
const vv = window.visualViewport;
let kb = 0;

if (vv) {
// How much of the window is occluded by the keyboard / chrome
const occluded = Math.max(0, Math.round(window.innerHeight - vv.height - (vv.offsetTop || 0)));
// Is the composer currently below the visible bottom?
const visBottom = vv.height + (vv.offsetTop || 0);
const compBottom = composer.getBoundingClientRect().bottom;
const overlap = Math.max(0, Math.round(compBottom - visBottom));
// Visible height delta vs baseline (helps with iOS “jiggle”)
const delta = Math.max(0, Math.round((baseVVH || vv.height) - vv.height));

kb = Math.max(occluded, overlap, delta);
}

// Thresholds to ignore small URL bar animations
const IS_IOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
const THRESH = IS_IOS ? 120 : 80;
if (kb < THRESH) kb = 0;

// Cap to prevent overshoot
const maxKb = Math.max(0, Math.round(panel.getBoundingClientRect().height - 56));
kb = Math.min(kb, maxKb);

panel.style.setProperty('--kb', kb + 'px');
}

function relayout() {
setLVH();
computeKeyboardOffset();
}

// Init
setBaseVVH();
setLVH();

// Recalculate on viewport changes (keyboard / URL bar animation)
if (window.visualViewport) {
let timer = null;
const onVV = () => {
clearTimeout(timer);
// Debounce to avoid rapid jiggle
timer = setTimeout(() => {
relayout();
}, 50);
};
visualViewport.addEventListener('resize', onVV);
visualViewport.addEventListener('scroll', onVV);
}

window.addEventListener('resize', relayout);
window.addEventListener('orientationchange', () => setTimeout(relayout, 250));

// Update baseline around focus/blur to track keyboard state changes
msg.addEventListener('focus', () => { setBaseVVH(); computeKeyboardOffset(); });
msg.addEventListener('blur', () => {
panel.style.setProperty('--kb', '0px');
setBaseVVH();
});
})();


Подробнее здесь: https://stackoverflow.com/questions/797 ... yboard-ope
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Javascript»