ResizeObserver - un nouvel outil puissant pour travailler avec l'adaptabilité

Bonjour mes amis!

Responsive est l'une des normes de développement Web. Il existe un grand nombre de résolutions d'écran, et ce nombre augmente tout le temps. Nous nous efforçons de prendre en charge toutes les tailles d'écran possibles tout en conservant une interface utilisateur conviviale. Une excellente solution à ce problème sont les requêtes multimédias (requêtes multimédias). Mais qu'en est-il des composants Web? Le développement Web moderne est basé sur des composants, et nous avons besoin d'un moyen de les rendre réactifs. Aujourd'hui, je veux parler de l'API ResizeObserver, qui vous permet de surveiller (observer) les changements de taille d'un élément particulier, et non de la fenêtre entière, comme c'est le cas avec les requêtes multimédias.

Un peu d'histoire


Auparavant, nous n'avions que des requêtes multimédias à notre disposition - une solution CSS basée sur la taille, le type et la résolution de l'écran d'un périphérique multimédia (par un périphérique multimédia, je veux dire un ordinateur, un téléphone ou une tablette). Les requêtes multimédias sont assez flexibles et faciles à utiliser. Pendant longtemps, les requêtes multimédias n'étaient disponibles qu'en CSS, maintenant elles sont également disponibles en JS via window.matchMedia (mediaQueryString). Nous pouvons maintenant vérifier à partir de quel appareil la page est consultée, et également surveiller le changement de la taille de la zone de visualisation (nous parlons de la méthode MediaQueryList.addListener () - env.

Requêtes d'élément


Ce qui nous manquait, c'était la possibilité de surveiller la taille d'un seul élément DOM, et pas seulement la fenêtre entière. Les développeurs s'en plaignent depuis de nombreuses années. C'est l'une des fonctionnalités les plus attendues. En 2015, même une proposition a été présentée - demandes de tailles de conteneurs ( Container Queries ):
Les développeurs ont souvent besoin de pouvoir styliser des éléments lorsqu'ils redimensionnent leur conteneur parent, quelle que soit la zone d'affichage. Les demandes de tailles de conteneurs leur donnent cette opportunité. Exemple d'utilisation CSS:
écran .element: media (min-width: 30em) {***}
Cela semble génial, mais les fournisseurs de navigateurs avaient une bonne raison de rejeter cette proposition - la dépendance circulaire (dépendance circulaire) (lorsqu'une taille en définit une autre, cela conduit à une boucle infinie (plus d'informations à ce sujet peuvent être trouvées ici ). Quelles autres options existe-t-il? Nous pouvons utiliser window.resize (rappel), mais c'est un «plaisir coûteux» - un rappel sera appelé chaque fois qu'un événement se produit, et nous aurons besoin de beaucoup de calculs pour déterminer que la taille de notre composant a vraiment changé ...

Surveillance du redimensionnement des éléments à l'aide de l'API ResizeObserver


Rencontrez l' API ResizeObserver de Chrome:
L'API ResizeObserver est une interface de suivi du redimensionnement des éléments. Il s'agit d'une sorte d'analogue de l'événement window.resize pour un élément.

L'API ResizeObserver est un brouillon en direct. Il est déjà implémenté dans Chrome, Firefox et Safari pour PC. La prise en charge mobile est moins impressionnante - uniquement Chrome sur Android et Samsung Internet. Malheureusement, un polyphile à part entière n'existe pas. Les polyphiles disponibles contiennent certaines limitations (par exemple, une réponse lente au redimensionnement ou un manque de support pour une transition en douceur). Cependant, cela ne devrait pas nous empêcher de tester cette API. Alors faisons-le!

Exemple: changement de texte lors du redimensionnement d'un élément


Imaginez la situation suivante - le texte à l'intérieur de l'élément devrait changer en fonction de la taille de l'élément. L'API ResizeObserver fournit deux outils - ResizeObserver et ResizeObserverEntry. ResizeObserver est utilisé pour suivre la taille d'un élément et ResizeObserverEntry contient des informations sur l'élément qui a été redimensionné.
Le code est très simple:

<h1> size </h1>
<h2> boring text </h2>

const ro = new ResizeObserver(entries => {
    for(let entry of entries){
        const width = entry.contentBoxSize
        ? entry.contentBoxSize.inlineSize
        : entry.contentRect.width

        if(entry.target.tagName === 'H1'){
            entry.target.textContent = width < 1000 'small' : 'big'
        }

        if(entry.target.tagName === 'H2' && width < 500){
            entry.target.textContent = `I won't change anymore`
            ro.unobserve(entry.target) //  ,     500px
        }
    }
})

//       
ro.observe(document.querySelector('h1'))
ro.observe(document.querySelector('h2'))

Créez d'abord un objet ResizeObserver et passez-lui une fonction de rappel en tant que paramètre:

const resizeObserver = new ResizeObserver((entries, observer) => {
    for(let entry of entries){
        // 
    }
})

La fonction est appelée à chaque fois que l'un des éléments contenus dans ResizeObserverEntries est redimensionné. Le deuxième paramètre de la fonction de rappel est l'observateur lui-même. Nous pouvons l'utiliser, par exemple, pour arrêter le suivi lorsqu'une certaine condition est remplie.

Le rappel obtient un tableau de ResizeObserverEntry. Chaque entrée contient les dimensions de l'élément observé (cible).

for(let entry of entries){
    const width = entry.contentBoxSize
    ? entry.contentBoxSize.inlineSize
    : entry.contentRect.width

    if(entry.target.tagName === 'H1'){
        entry.target.textContent = width < 1000 ? 'small' : 'big'
    }
    ...
}

Nous avons trois propriétés qui décrivent la taille d'un élément - borderBoxSize, contentBoxSize et contentRect. Ils représentent le modèle de boîte de l'élément, dont nous parlerons plus tard. Maintenant, quelques mots sur le support. La plupart des navigateurs prennent en charge contentRect, cependant, apparemment, cette propriété sera obsolète:
contentRect est apparu au stade de développement préliminaire de ResizeObserver et n'a été ajouté que dans l'intérêt de la compatibilité actuelle. À l'avenir, il sera probablement considéré comme obsolète.


Par conséquent, je recommande fortement d'utiliser contentRect en conjonction avec bordeBoxSize et contentBoxSize. ResizeObserverSize comprend deux propriétés: inlineSize et blockSize, qui peuvent être interprétées comme largeur et hauteur (à condition que nous travaillions dans l'orientation horizontale du texte - mode d'écriture: horizontal).

Observation d'élément


La dernière chose à faire est de commencer à suivre l'article. Pour ce faire, nous appelons ResizeObserver.observe (). Cette méthode ajoute une nouvelle cible à la liste des éléments observés. On peut ajouter à cette liste un ou plusieurs éléments à la fois:

// resizeObserver(target, options)
ro.observe(document.querySelector('h1'))
ro.observe(document.querySelector('h2'))

Le deuxième paramètre est «facultatif». À ce jour, la seule option disponible est box, qui définit un modèle de bloc. Les valeurs possibles sont content-box (par défaut), border-box et device-pixel-content-box (Chrome uniquement). Un seul modèle de bloc peut être défini dans un ResizeObserver.

Pour arrêter la surveillance, utilisez ResizeObserver.unobserve (cible). Pour arrêter le suivi de tous les éléments, utilisez ResizeObserver.disconnect ().

Modèle de bloc


La zone de contenu est le contenu du bloc sans remplissage, bordure et marge. La boîte de bordure comprend un rembourrage et une bordure (pas de marge).



La zone de contenu des pixels de l'appareil est le contenu de l'élément en pixels physiques. Je n'ai pas vu d'exemples d'utilisation de ce modèle, mais il semble que cela puisse être utile lorsque vous travaillez avec du canevas. Voici une discussion intéressante sur ce sujet sur Github.

Quand un observateur est-il informé des changements?


Un rappel est appelé chaque fois que l'élément cible est redimensionné. Voici ce que la spécification en dit:

  • L'observation est déclenchée lorsqu'un élément observé est ajouté / supprimé du DOM.
  • L'observation est déclenchée lorsque la propriété d'affichage de l'élément observé est définie sur aucune.
  • L'observation ne fonctionne pas pour les éléments de ligne «non substitués».
  • L'observation ne fonctionne pas dans la transformation CSS.
  • , , .. , 0,0.

Selon le premier paragraphe, nous pouvons déterminer la modification du conteneur parent lors du changement de ses enfants. Un bon exemple d'une telle utilisation de l'API ResizeObserver est de faire défiler la fenêtre de discussion lors de l'ajout d'un nouveau message. Un exemple peut être vu ici .

Rappelez-vous les requêtes de taille de conteneur que j'ai mentionnées plus tôt? A propos de son problème de dépendance circulaire? Ainsi, l'API ResizeObserver a une solution intégrée pour empêcher une boucle sans fin de «redimensionnement». Lisez à ce sujet ici .

Merci de votre attention.

Liens utiles:

Spécification
MDN
CanIUse
Premier article de l'équipe de développement Polyfil le
plus populaire

Source: https://habr.com/ru/post/undefined/


All Articles