Retour au Centre de connaissances
Plateforme

API VirtualKeyboard : limites du viewport et des insets

Coordonnez geometrychange, visualViewport et les insets du clavier pour garder les actions fixes accessibles pendant les transitions de formulaire mobile.

BotBrowser Team

Documentation

Vous voulez la documentation structurée pour Plateforme ?

Cet article fait partie de la bibliothèque éditoriale. Pour les étapes de configuration, la référence et les mises à jour continues, passez directement à la section docs.

BotBrowser peut répéter un fixture mobile autorisé avec une politique de clavier, un profil et un viewport déclarés, mais il ne reproduit pas toutes les animations d’un clavier natif et ne certifie pas un appareil physique. La question utile est plus précise : lorsqu’un champ éditable reçoit le focus et ouvre le clavier virtuel, quelle surface change, quel inset est disponible et quelle action reste accessible ? Ce guide sépare l’API VirtualKeyboard du redimensionnement générique et des choix de profil décrits dans les tests de profils d’appareil et le guide de mesure du viewport.

Résumé

  • navigator.virtualKeyboard.overlaysContent est une politique facultative : le clavier peut recouvrir le contenu au lieu de réduire le layout viewport.
  • geometrychange fournit un DOMRect de la géométrie actuelle ; regroupez-le avec les changements de visualViewport avant d’écrire le layout.
  • env(keyboard-inset-*) expose les insets CSS seulement si le navigateur et la politique les fournissent. Gardez un padding de repli 0px.
  • Le layout viewport, le visual viewport et le rectangle du clavier répondent à des questions différentes. Ne remplacez pas les trois par innerHeight.
  • Testez le focus, le défilement, la rotation, le zoom et la fermeture comme des transitions. Une capture du clavier ouvert ne suffit pas.

Sommaire

Trois surfaces et politique

Le layout viewport est l’espace de coordonnées utilisé pour disposer le document. Le visual viewport est la portion visible après l’interface du navigateur, le zoom par pincement ou l’arrivée du clavier virtuel. L’API VirtualKeyboard ajoute un rectangle de clavier lorsque la page choisit le mode de recouvrement. Ces surfaces peuvent bouger séparément ; une seule valeur window.innerHeight ne décrit donc pas un formulaire focalisé.

Flux de VirtualKeyboard geometrychange vers les insets du clavier et une action fixe accessible

SurfaceQuestion répondueChamp d’exemple
Layout viewportQuelle est la taille de la zone de layout ?window.innerHeight
Visual viewportQue peut voir l’utilisateur maintenant ?visualViewport.height
Rectangle clavierQuels pixels sont couverts par le clavier ?virtualKeyboard.boundingRect

Quand le clavier redimensionne la page, le layout viewport peut rétrécir et le rectangle du clavier peut être nul ou absent de la zone utilisable. En mode de recouvrement, le layout viewport peut rester stable alors que le clavier couvre son bord inférieur. Le guide de redimensionnement du viewport décrit l’ordre des événements associé ; cet article ajoute le contrat explicite de politique et d’inset CSS.

Ne déduisez pas la hauteur du clavier uniquement de innerHeight - visualViewport.height sans relever l’interface du navigateur et le zoom. Cette différence est une estimation, pas une garantie d’API. Préférez virtualKeyboard.boundingRect en mode recouvrement et utilisez visualViewport.height, offsetTop et scale pour la zone réellement visible.

navigator.virtualKeyboard.overlaysContent = true indique à un navigateur compatible que la page gère la zone couverte. Le navigateur ne déplace pas automatiquement tous les pieds de page fixes. La page doit utiliser la géométrie ou les variables d’environnement CSS et garder un chemin de fermeture et de focus utilisable. Attribuez la politique avant l’ouverture du clavier plutôt qu’à chaque focus.

Relevez la présence de l’API, le résultat de l’affectation à overlaysContent, l’étiquette du profil actif et le chemin CSS utilisé. Un profil de bureau peut ignorer l’option : c’est une limite de capacité, pas un signal sur l’utilisateur.

Fixture et implémentation des insets

Le fixture conserve l’action d’envoi fixe, fournit une zone défilable et écrit un relevé de géométrie expurgé. Il ne collecte ni texte, ni identifiants de compte, ni événements de touches, ni contenu du clavier. Gardez le balisage stable et changez une seule ligne de matrice à la fois.

<main class="screen">
  <form class="card" id="checkout">
    <label>Email <input name="email" type="email" autocomplete="email" /></label>
    <label>Address <input name="address" autocomplete="street-address" /></label>
    <p class="status" role="status" aria-live="polite"></p>
    <button class="submit" type="submit">Continue</button>
  </form>
</main>
<script>
  const vk = navigator.virtualKeyboard;
  if (vk) {
    vk.overlaysContent = true;
    vk.addEventListener('geometrychange', () => {
      const r = vk.boundingRect;
      document.documentElement.style.setProperty('--vk-bottom', `${r.height}px`);
      console.log(JSON.stringify({ type: 'keyboard', height: r.height, top: r.top }));
    });
  }
</script>
:root {
  --vk-bottom: 0px;
}
.screen {
  min-block-size: 100dvh;
  padding: 1rem;
}
.card {
  min-block-size: 140vh;
  padding-block-end: calc(5rem + var(--vk-bottom));
}
.submit {
  position: fixed;
  inset-inline: 1rem;
  inset-block-end: calc(1rem + var(--vk-bottom) + env(safe-area-inset-bottom, 0px));
}
@supports (padding: env(keyboard-inset-bottom)) {
  .card {
    padding-block-end: calc(5rem + env(keyboard-inset-bottom));
  }
  .submit {
    inset-block-end: calc(1rem + env(keyboard-inset-bottom) + env(safe-area-inset-bottom, 0px));
  }
}

La propriété personnalisée JavaScript sert aux moteurs qui exposent la géométrie mais pas la variable d’environnement CSS. @supports prouve seulement que la syntaxe est analysée ; il ne prouve pas que keyboard-inset-bottom est non nul. Vérifiez le padding calculé après le focus et après la fermeture. 0px est valable si le clavier est masqué, si le recouvrement est désactivé ou si le navigateur n’expose pas la fonction.

Les variables keyboard-inset-top, keyboard-inset-right, keyboard-inset-bottom et keyboard-inset-left, ainsi que leurs variantes de largeur et de hauteur, décrivent le bord obstrué. Elles servent à dégager une action fixe ou à réserver une zone dans un conteneur défilable, mais ne remplacent pas safe-area-inset-*. Un appareil peut avoir à la fois un clavier et une zone sûre pour l’indicateur d’accueil. Combinez les contraintes avec max() ou calc() et préférez les propriétés logiques en écriture RTL ou verticale.

Si le repli conserve trop d’espace après la fermeture, effacez la propriété personnalisée au prochain événement de géométrie plutôt que de masquer l’action avec un décalage négatif. Le flux normal doit rester utilisable pendant le démarrage de JavaScript, une restauration de navigation et un profil sans navigator.virtualKeyboard.

Ordre des événements et propriétaire du défilement

geometrychange peut survenir près de visualViewport.resize et visualViewport.scroll. Ces événements décrivent une transition liée, mais leur ordre n’est pas garanti. Utilisez un planificateur commun et lisez les valeurs une fois par frame d’animation :

let pending = false;
function scheduleLayout() {
  if (pending) return;
  pending = true;
  requestAnimationFrame(() => {
    pending = false;
    const vv = window.visualViewport;
    const k = navigator.virtualKeyboard?.boundingRect;
    document.documentElement.dataset.keyboard = k && k.height > 0 ? 'open' : 'closed';
    console.log(
      JSON.stringify({
        layoutHeight: window.innerHeight,
        visualHeight: vv?.height ?? null,
        visualOffsetTop: vv?.offsetTop ?? null,
        keyboardHeight: k?.height ?? 0,
      })
    );
  });
}
window.visualViewport?.addEventListener('resize', scheduleLayout);
window.visualViewport?.addEventListener('scroll', scheduleLayout);
navigator.virtualKeyboard?.addEventListener('geometrychange', scheduleLayout);

Le relevé distingue une transition du clavier de l’interface du navigateur ou du zoom. Une ligne avec keyboardHeight: 0 et un visualHeight inférieur ne prouve pas la fermeture : il peut s’agir d’une barre ou d’un zoom. Conservez scale, offsetTop et le rectangle de l’élément focalisé. Un relevé par frame évite que des gestionnaires concurrents appliquent un padding périmé.

Lorsque le focus arrive sur un champ hors de la zone visible, le navigateur peut faire défiler le document ou un conteneur interne overflow: auto. Un bouton fixe peut rester visible alors que le champ est caché, ou l’inverse. Vérifiez les deux rectangles après la fin du défilement. Choisissez un seul propriétaire : attendez l’ajustement du focus et corrigez seulement si le bas du champ dépasse le haut visible du clavier ; n’appelez pas scrollIntoView() à chaque événement.

La rotation et le zoom sont des transitions distinctes. La rotation peut modifier les viewports et les insets de zone sûre avant l’événement du clavier. Le zoom par pincement modifie les coordonnées visuelles sans modifier les dimensions CSS de la même façon. Conservez scale, offsetTop et la zone sûre dans des lignes séparées.

Enregistrer un résultat d’acceptation

Le relevé doit identifier la transition en échec, pas seulement signaler que le clavier était visible. Stockez l’identifiant de ligne, le contrôle focalisé, le résultat de politique, window.innerHeight, visualViewport.height, visualViewport.offsetTop, visualViewport.scale, le rectangle du clavier, le padding inférieur calculé et le rectangle final de l’action.

{
  "row": "D",
  "focused": "address",
  "overlaysContent": true,
  "layoutHeight": 844,
  "visualHeight": 512,
  "visualOffsetTop": 0,
  "keyboardTop": 512,
  "keyboardHeight": 332,
  "actionBottom": 496,
  "keyboardTopMinusActionBottom": 16,
  "actionReachable": true
}

Si keyboardHeight est positif et actionBottom dépasse keyboardTop, l’action est couverte. Si elle dégage le clavier mais que le champ reste sous keyboardTop, le propriétaire du défilement est incorrect. Si les rectangles sont sûrs alors que visualHeight est anormalement petit, vérifiez l’interface du navigateur ou le zoom avant de modifier le CSS. N’enregistrez ni valeurs de champs, ni comptes, ni touches, ni numéros de série.

Diagnostiquer la première surface divergente

Si navigator.virtualKeyboard manque, classez la ligne comme non prise en charge et gardez la voie viewport normale. Si la propriété existe mais que overlaysContent reste faux, le navigateur gère un redimensionnement ; un rectangle nul ne prouve pas la fermeture. Si geometrychange arrive mais que keyboard-inset-bottom reste nul, utilisez le rectangle JavaScript et notez l’absence d’insets CSS. Si le rectangle est correct mais l’action est couverte, examinez son bloc conteneur et le calcul de zone sûre. Si l’action dégage l’inset mais que le champ reste caché, examinez le propriétaire unique du défilement et le timing du focus.

Garder le repli testable

Rendez le même formulaire lorsque navigator.virtualKeyboard manque, lorsque l’affectation de overlaysContent est ignorée et lorsque les variables CSS sont analysées mais restent nulles. L’action doit rester accessible par le flux normal et la personne doit pouvoir fermer le clavier ou poursuivre avec une autre saisie. Utilisez un indicateur de fonction pour comparer les chemins gérés et explicites sans changer le balisage ; gardez-le dans le relevé du fixture, jamais dans une charge d’empreinte.

Matrice des limites et capacité de BotBrowser

Exécutez le même fixture avec un profil neuf par ligne. Gardez constants le texte, les polices, le zoom et le facteur d’échelle sauf si la ligne nomme le changement. Un échec utile cite la ligne et la première surface divergente, par exemple « l’action de la ligne D est restée 18px sous le haut du clavier après le défilement interne », plutôt que « clavier mobile cassé ».

LigneChangementObservation attendueSignification
APolitique clavier désactivéeRedimensionnement normal ou géré par le navigateurCompatibilité de base
BRecouvrement et champ focaliségeometrychange, height positif, action dégagéeContrat explicite du clavier
CClavier ferméHauteur à 0, sans ancien paddingTransition de nettoyage
DConteneur défilable interneChamp et action restent accessiblesPropriété du défilement
ERotation ou zoom à 200 %Viewport et zone sûre changent séparémentTransition sans clavier
FProfil non pris en charge ou bureauAPI absente ou option ignoréeLimite de capacité

Enregistrez browserVersion, l’étiquette de profil, l’affectation de politique, le contrôle focalisé, les valeurs des viewports, le rectangle du clavier, les valeurs de zone sûre et le rectangle final. Ne conservez pas le texte du formulaire ni les données de touches. Rejouez la ligne C après chaque ouverture pour repérer un --vk-bottom périmé.

Limite de capacité de BotBrowser

BotBrowser prend en charge des profils mobiles correspondants avec le support tactile défini par le profil et l’option documentée --bot-mobile-keyboard. Dans un profil pris en charge, le focus fiable d’un champ éditable peut réduire visualViewport.height tandis que le layout viewport reste stable, ce qui permet de répéter les points clavier visible et tactile. Les profils de bureau peuvent ignorer cette option. BotBrowser ne peut pas remplacer les appareils physiques, les claviers du système, leurs animations ou tous les layouts, et ne garantit pas des insets de clavier non nuls. Pour choisir les profils, consultez la revue de qualité des profils mobiles.

FAQ

overlaysContent redimensionne-t-il le layout viewport ?

Il est conçu pour que le clavier recouvre le contenu, donc un navigateur compatible peut garder le layout viewport stable. Le visual viewport et le rectangle du clavier changent néanmoins. Vérifiez innerHeight, visualViewport.height et boundingRect.height pour chaque navigateur.

Les insets du clavier sont-ils ceux de la zone sûre ?

Non. Les insets du clavier décrivent une obstruction temporaire ; ceux de la zone sûre décrivent un bord qui exige un padding permanent. Combinez-les avec calc() ou max() et testez la fermeture pour éliminer un padding périmé.

Chaque geometrychange doit-il appeler scrollIntoView() ?

Non. Laissez le navigateur terminer le défilement du focus, inspectez le contrôle et l’action dans une frame, puis corrigez uniquement si le contrôle reste derrière la limite visible du clavier. Gardez un seul propriétaire du conteneur.

Sources

Conclusion pratique

Traitez VirtualKeyboard comme un contrat de politique et de géométrie. Conservez séparément layout, visual viewport, rectangle du clavier, zone sûre et propriétaire du défilement ; regroupez leurs événements et testez ouverture, fermeture, rotation, zoom et profils non pris en charge. BotBrowser peut répéter la condition mobile déclarée et capturer une géométrie expurgée, tandis que l’appareil physique et le clavier natif restent hors de cette preuve.

#Virtual Keyboard#Viewport#Css Insets#Mobile Layout#Forms

Cet article fait partie du guide : Surfaces de la plateforme web : carte de revue

Faites passer BotBrowser de la recherche à la production

Utilisez ces guides pour comprendre le modèle, puis passez à la validation multi-plateforme, aux contextes isolés et au déploiement navigateur prêt pour l'échelle.