Rendu des pixels secondaires et le modèle d'objet CSS

Avec Windows 8, vous disposez d'un choix sans précédent de périphériques pour parcourir le Web, des grands écrans d'ordinateurs de bureau aux petites tablettes. Afin de s'adapter à cette gamme de périphériques, le navigateur doit être capable d'effectuer une mise à l'échelle et de présenter le Web dans différentes dimensions et tailles d'écran. Nous avons déjà parlé de certaines des fonctionnalités d'IE qui prennent en charge ces scénarios. Le placement de pixels secondaires (du texte et de la présentation) est l'une des principales technologies de plateforme qui permet aux pages Web d'être esthétiques et cohérentes à n'importe quelle échelle.

Dans ce billet, nous décrivons les modifications apportées à IE10 dans le but d'améliorer la prise en charge du placement des pixels secondaires par le biais du modèle d'objet CSS (CSS-OM).

Les développeurs Web peuvent créer de magnifiques présentations grâce à différentes technologies de plateforme. En règle générale, les développeurs utilisent des feuilles de style CSS pour décrire la présentation d'un site Web. Dans certains cas, les développeurs Web dépendent également du code JavaScript pour mesurer, aligner ou placer les éléments d'une page Web avec une précision pixel-perfect. Par exemple, certains éditeurs en ligne placent avec précision une zone d'édition exactement par dessus un contenu existant, afin qu'elle n'apparaisse que si vous modifiez directement le contenu existant. Dans de tels cas, il est possible d'utiliser les API du modèle d'objet CSS (CSS-OM) pour lire et/ou définir la position des éléments. Le modèle d'objet CSS (CSS-OM) est un ensemble d'API JavaScript permettant de manipuler par programmation CSS.

Mesurer et aligner des éléments de présentation à l'aide des API CSS-OM peut être problématique en raison de la façon dont ces API arrondissent ou tronquent les valeurs de placement des pixels secondaires en nombres entiers de pixels.

Petite remarque sur les présentations « Pixel-perfect »

En règle générale, les présentations parfaites au pixel près (pixel-perfect) sur le Web tendent à entrer en conflit avec l'objectif d'un contenu accessible, compatible et adaptable et par conséquent, ne sont pas recommandées. Le montage suivant illustre certains des bogues pouvant survenir lorsque le concepteur Web tente de créer une conception « pixel-perfect », mais que des différences de plateforme Web inattendues provoquent l'échec de leurs conceptions.

Exemples de conceptions « pixel-perfect » ayant échoué
Exemples de conceptions « pixel-perfect » ayant échoué

Lors de l'utilisation du modèle d'objet CSS (CSS-OM) pour générer dynamiquement une présentation, les développeurs Web doivent prévoir quelques pixels d'erreur potentielle. Mieux encore, IE10 propose plusieurs nouvelles options de présentation que les développeurs peuvent utiliser pour mieux réaliser un grand nombre de ces présentations souhaitées, sans avoir à recourir à l'alignement « pixel-perfect » avec le CSS-OM.

Illustration

Pour illustrer la façon dont les API du CSS-OM peuvent entraîner des problèmes subtils de placement, voici un exemple simple. Le placement de pixels secondaires permet de répartir équitablement quatre zones à l'intérieur du conteneur, même si la taille du conteneur n'est pas parfaitement divisible en quatre.

Observez le fragment de balisage HTML suivant :

<footer>

<div>content 1</div><div>content 2</div><div>content 3</div><div>content 4</div>

</footer>

avec ce balisage CSS partiel :

footer { width: 554px; border: 1px solid black; text-align: center; }

footer div { display: inline-block; width: 25%; }

footer div:nth-child(even) { background-color: Red; }

footer div:nth-child(odd) { background-color: Orange; }

Ajoutons maintenant une fonction qui s'exécute en charge et indique la largeur de ces éléments :

onload = function () {

var footerBoxes = document.querySelectorAll("footer div");

var s = "";

var totalSize = 0;

for (var i = 0; i < footerBoxes.length; i++) {

// Reporting

var offsetWidth = footerBoxes[i].offsetWidth;

s += "content " + (i + 1) + " offsetWidth = " + offsetWidth + "px" + "<br />";

totalSize += offsetWidth;

}

s += "Total <i>calculated</i> offsetWidth = " + totalSize + "px" + "<br />";

s += "Container width = " + document.querySelector("footer").clientWidth + "px" + "<br />";

document.querySelector("#message").innerHTML = s;

}

Le résultat de l'exécution de ce balisage et du code dans IE9 ressemble à ceci :

content 1content 2content 3content 4 content 1 offsetWidth = 139content 2 offsetWidth = 139content 3 offsetWidth = 139content 4 offsetWidth = 139Total calculated offsetWidth = 556Actual container width = 554

Notez que l'ajout des valeurs renvoyées par l'API CSS-OM offsetWidth donne le total de offsetWidth calculé, qui diffère de la largeur réelle du conteneur de deux pixels, en raison de l'arrondissement qui s'est produit dans la valeur offsetWidth de chaque élément div.

Les résultats dans d'autres navigateurs montrent une différence similaire, même si parfois le total est inférieur ou supérieur au total réel.

Lorsque l'arrondi/la troncation mène à une somme totale qui dépasse la taille du conteneur (comme illustré), le contenu commence à s'enrouler ou provoque l'apparition de barres de défilement indésirables. En outre, de nombreux conteneurs sont dimensionnés en fonction du texte et de la police utilisée pour afficher le texte, et ces données de polices peuvent être différentes d'un navigateur à un autre. D'autres polices peuvent par ailleurs être sélectionnées si la police demandée n'est pas disponible.

L'API offsetWidth, ainsi que de nombreuses autres propriétés CSS-OM très utilisées (la plupart datant d'IE4 en 1997), permet d'extraire de façon rapide et pratique les valeurs entières de pixel pour un élément provenant d'une variété de systèmes de coordonnées différents. Tous les principaux navigateurs implémentent la plupart de ces API pour des raisons de compatibilité et ils font également partie du module CSS-OM View, une norme W3C en version préliminaire.

Les nouvelles fonctionnalités des navigateurs continuent à mettre en avant l'insuffisance de la limitation des propriétés CSS-OM aux pixels à valeurs entières. Par exemple, des fonctionnalités telles que SVG et CSS 2D/ Transformations 3D permettent aux dimensions d'un élément de facilement se placer entre des pixels.

Résolution du problème

En reconnaissant cette limitation (en partie), la spécification W3C CSS-OM View décrit les coordonnées renvoyées via l'API getBoundingClientRect() pour être définies en tant que floats, en d'autres termes, en valeurs pouvant représenter une précision en pixels secondaires. (getBoundingClientRect() est une autre API CSS-OM qui fournit la position et la dimension du cadre englobant d'un élément à l'aide de la même origine que celle de l'API offsetWidth.)

Dans IE10, nous avons mis à jour l'API getBoundingClientRect() pour qu'elle renvoie une résolution en pixels secondaires par défaut en mode standard d'IE10 afin d'être interopérable avec d'autres navigateurs et de se conformer à la norme W3C.

Si nous mettons à jour notre exemple ci-dessus pour indiquer le composant width du rectangle renvoyé par getBoundingClientRect(), IE10 signale maintenant ces valeurs fractionnelles :

content 1content 2content 3content 4 content 1 offsetWidth = 139, getBoundingClientRect().width = 138.5 content 2 offsetWidth = 139, getBoundingClientRect().width = 138.5 content 3 offsetWidth = 139, getBoundingClientRect().width = 138.5 content 4 offsetWidth = 139, getBoundingClientRect().width = 138.5 Total calculated offsetWidth = 556 Total calculated getBoundingClientRect().width = 554 Actual container width = 554

Utilisation généralisée des valeurs de pixels secondaires

Outre getBoundingClientRect, nous signalons également un placement de pixels secondaires pour les événements de souris/pointeur en mode standard d'IE10 par défaut. La souris/le pointeur ne peut se situer entre des pixels que lorsque le facteur de zoom est défini sur une valeur autre que 100 %. Plus particulièrement, les API de la souris/du pointeur affectées sont les suivantes :

  • MouseEvent.offsetX/Y
  • MouseEvent.layerX/Y
  • MouseEvent.clientX/Y
  • MouseEvent.pageX/Y
  • MouseEvent.x/y

Pour poursuivre notre engagement envers la compatibilité avec des pages Web héritées (pages qui ne sont peut-être pas préparées à gérer des valeurs de pixels secondaires à partir du CSS-OM en général), IE10 continue à signaler les pixels à valeurs entières par défaut pour les autres propriétés CSS-OM. Ces API sont les suivantes :

  • Element.clientHeight
  • Element.clientWidth
  • Element.clientLeft
  • Element.clientTop
  • Element.scrollTop
  • Element.scrollLeft
  • Element.scrollWidth
  • Element.scrollHeight
  • HTMLElement.offsetWidth
  • HTMLElement.offsetHeight
  • HTMLElement.offsetTop
  • HTMLElement.offsetLeft
  • TextRange.offsetLeft
  • TextRange.offsetTop

Cependant, si cela est nécessaire, IE10 autorise maintenant également les développeurs Web à activer les valeurs de placement des pixels secondaires à partir des propriétés CSS-OM répertoriées ci-dessus. L'utilisation de cette fonctionnalité spéciale nécessite le mode standard d'IE10 et implique qu'un site participe en définissant la propriété suivante sur l'objet de document :

document.msCSSOMElementFloatMetrics = true;

Lorsqu'elles sont activées en définissant document.msCSSOMElementFloatMetrics sur true, toutes les API CSS-OM de la liste précédente commencent à signaler leurs valeurs en précision de pixels secondaires qui refléteront exactement les calculs utilisés en interne par le moteur de rendu et de présentation. Notez que JavaScript convertira 1.00 en 1, de sorte que vous ne verrez peut-être pas toujours un symbole décimal dans les valeurs renvoyées.

Si nous revenons à notre exemple et que nous définissons document.msCSSOMElementFloatMetrics sur true, les résultats sont les suivants dans IE10 :

content 1content 2content 3content 4 content 1 offsetWidth = 138.5, getBoundingClientRect().width = 138.5 content 2 offsetWidth = 138.5, getBoundingClientRect().width = 138.5 content 3 offsetWidth = 138.5, getBoundingClientRect().width = 138.5 content 4 offsetWidth = 138.5, getBoundingClientRect().width = 138.5 Total calculated offsetWidth = 554 Total calculated getBoundingClientRect().width = 554 Actual container width = 554

Notez les valeurs fractionnelles renvoyées par offsetWidth et que tous les totaux correspondent maintenant.

Résumé

Il est parfois utile (et dans de rares cas, nécessaire) d'être en mesure d'utiliser les propriétés CSS-OM pour calculer une présentation parfaite au pixel près (pixel-perfect). Lorsque vous utilisez le modèle d'objet CSS (CSS-OM), gardez à l'esprit les caractéristiques de signalement des pixels entiers de ces API. Lorsque vous concevez des présentations avec les API CSS ou CSS-OM, veillez à prévoir quelques pixels de tolérance afin que votre site soit plus fiable sur différents navigateurs et/ou périphériques.

—Travis Leithead, Chef de projet, Internet Explorer