Mise en page de type magazine pour le Web avec des régions et des exclusions CSS

Christian Cantrell
Christian Cantrell

Introduction

Le Web est une plate-forme extrêmement puissante pour le texte, un domaine dans lequel Adobe possède une grande expérience et une grande expertise. Alors qu'Adobe cherchait des moyens de faire progresser le Web, il semblait donc évident pour nous d'aller encore plus loin dans l'amélioration des capacités textuelles du Web. Le Web part généralement du principe que le texte comporte une seule colonne et une orientation verticale. Bien qu'il soit possible d'ajouter du texte autour d'éléments graphiques, et même de formater du texte en plusieurs colonnes à l'aide du code CSS, il reste très difficile d'obtenir une mise en page semblable à celle d'un magazine sur le Web. Avec les régions CSS et les exclusions CSS, Adobe se concentre sur l'intégration de la puissance de la PAO aux navigateurs modernes. Par exemple, dans la capture d'écran ci-dessous, des exclusions CSS sont utilisées pour afficher le texte le long du contour de la montagne:

Exemple d'exclusions CSS
Exemple d'exclusions CSS en action

Dans la capture d'écran ci-dessous, le document utilise également des exclusions CSS pour permettre au texte d'entourer des formes dans les images, et des régions CSS pour mettre en forme le texte en colonnes et autour d'un guillemet d'extraction:

Exemple de région CSS en action
Exemple de régions CSS en action

Régions CSS

Avant d'étudier plus en détail les régions CSS, j'aimerais vous expliquer comment les régions peuvent être activées dans Google Chrome. Une fois les régions CSS activées, vous pouvez tester certains des exemples référencés dans cet article et créer les vôtres.

Activer les régions CSS dans Google Chrome

Depuis la version 20 de Chrome (version 20.0.1132.57, pour être précis), les régions CSS sont activées via l'interface chrome://flags. Pour activer les régions CSS, procédez comme suit:

  1. Ouvrez un nouvel onglet ou une nouvelle fenêtre dans Chrome.
  2. Saisissez chrome://flags dans la barre d'adresse.
  3. Utilisez l'option Rechercher sur la page (Ctrl/Commande+f) et recherchez la section Fonctionnalités expérimentales de la plate-forme Web.
  4. Cliquez sur le lien Activer.
  5. Cliquez sur le bouton Relancer maintenant en bas de l'écran.

Pour en savoir plus sur les indicateurs de Chrome, consultez mon article de blog sur les indicateurs Chrome.

Une fois que vous avez relancé votre navigateur, vous pouvez commencer à tester les régions CSS.

Présentation des régions CSS

Les régions CSS permettent à un bloc de texte balisé sémantiquement de s'insérer automatiquement dans des "cases" (actuellement des éléments). Le schéma ci-dessous illustre la séparation du texte (le flux) et des zones (les régions dans lesquelles le texte s'affiche):

Le contenu circule dans certaines régions
Le contenu transite par certaines régions

Examinons un cas d'utilisation réel des régions CSS. En plus d'être développeur chez Adobe, je suis également écrivain de science-fiction. Je publie fréquemment mon travail en ligne sous une licence Creative Commons et afin qu'elle puisse fonctionner sur le plus grand nombre d'appareils et de navigateurs possible, j'utilise souvent un format extrêmement simple similaire à celui-ci:

Exemple de projet sans style pour l'héritage humain
Exemple d'un projet Human Legacy sans style

Grâce aux régions CSS, j'ai pu créer une expérience à la fois plus intéressante visuellement et beaucoup plus fonctionnelle, car elle est plus facile à parcourir et plus lisible:

Projet Human Legacy montrant la région
Human Legacy Project with Regions

À titre de démonstration, j'ai ajouté la possibilité d'afficher les régions CSS dans ce prototype. La capture d'écran ci-dessous montre comment les régions sont organisées de sorte qu'elles donnent l'impression d'être des colonnes qui entourent un graphique et une citation au centre:

Projet Human Legacy avec des régions
Human Legacy Project montrant les régions

Vous pouvez tester ce prototype (et voir le code source) sur cette page. Utilisez les touches fléchées pour naviguer et appuyez sur la touche Esc pour afficher les régions. Les prototypes antérieurs sont également disponibles sur cette page.

Créer un flux nommé

Le code CSS requis pour faire passer un bloc de texte à travers les régions est extrêmement simple. L'extrait de code ci-dessous attribue un flux nommé "article" à un élément div associé à l'ID "content" et attribue ce même flux nommé "article" à tout élément ayant la classe "region". Résultat : le texte contenu dans l'élément "content" passe automatiquement par tout élément ayant la classe "region".

<!DOCTYPE html>
<html>
<head>
    <style>
    #content {
        { % mixin flow-into: article; % }
    }

    .region {
        { % mixin flow-from: article; % }
        box-sizing: border-box;
        position: absolute;
        width: 200px;
        height: 200px;
        padding: 10px;
    }

    #box-a {
        border: 1px solid red;
        top: 10px;
        left: 10px;
    }

    #box-b {
        border: 1px solid green;
        top: 210px;
        left: 210px;
    }

    #box-c {
        border: 1px solid blue;
        top: 410px;
        left: 410px;
    }
    </style>
</head>
<body>
    <div id="box-a" class="region"></div>
    <div id="box-b" class="region"></div>
    <div id="box-c" class="region"></div>
    <div id="content">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent eleifend dapibus felis, a consectetur nisl aliquam at. Aliquam quam augue, molestie a scelerisque nec, accumsan non metus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin cursus euismod nisi, a egestas sem rhoncus eget. Mauris non tortor arcu. Pellentesque in odio at leo volutpat consequat....
    </div>
</body>
</html>

Le résultat ressemble à ceci :

Résultat du code ci-dessus
Résultat du code ci-dessus

Notez que le texte de l'élément div"content" ne connaît pas sa présentation. En d'autres termes, elle peut rester intacte d'un point de vue sémantique, même lorsqu'elle transite par différentes régions. De plus, comme les régions ne sont que des éléments, elles sont positionnées et dimensionnées à l'aide de CSS comme n'importe quel autre élément. Elles sont donc parfaitement compatibles avec les principes du responsive design. Lorsque des éléments font partie d'un flux nommé, cela signifie simplement que le texte spécifié les traverse automatiquement.

Modèle d'objet CSS

Le modèle CSS Object Model, ou CSSOM, définit les API JavaScript à utiliser avec les CSS. Vous trouverez ci-dessous la liste des nouvelles API associées aux régions CSS:

  • document.webkitGetNamedFlows(): fonction qui renvoie la collection de flux nommés disponibles dans le document.
  • document.webkitGetNamedFlows().namedItem("article"): fonction qui renvoie une référence à un flux nommé spécifique. L'argument correspond au nom spécifié comme valeur des propriétés CSS flow-into et from-from. Pour obtenir une référence au flux nommé spécifié dans l'extrait de code ci-dessus, vous devez transmettre la chaîne "article".
  • WebKitNamedFlow: représentation d'objet d'un floe nommé avec les propriétés et fonctions suivantes :
    • firstEmptyRegionIndex: valeur entière qui pointe vers l'index de la première région vide associée au flux nommé. Consultez getRegions() ci-dessous pour savoir comment obtenir la collection de régions.
    • name: valeur de chaîne avec le nom du flux.
    • overset: une propriété booléenne qui est :
      • false lorsque le contenu du flux nommé correspond aux régions associées
      • true lorsque le contenu ne convient pas et que la totalité du contenu doit être incluse dans d'autres régions.
    • getContent(): fonction qui renvoie une collection avec des références aux nœuds qui entrent dans le flux nommé.
    • getRegions(): fonction qui renvoie une collection avec des références à des régions hébergeant le contenu du flux nommé.
    • getRegionsByContentNode(node): fonction qui renvoie une référence à la région contenant le nœud spécifié. Ceci est particulièrement utile pour trouver des régions contenant des éléments tels que des ancres nommées.
  • webkitregionoversetchange. Cet événement est déclenché sur WebkitNamedFlow chaque fois que la mise en page du contenu associé change pour une raison quelconque (contenu ajouté ou supprimé, modification de la taille de la police, modification de la forme de la région, etc.) et entraînant la modification de la propriété webkitRegionOverset d'une région. Cet événement est utile pour écouter les modifications grossières de la mise en page. Elle indique qu'un événement important s'est produit et que la mise en page peut nécessiter votre attention. Par exemple: davantage de régions sont requises, certaines régions peuvent être vides, etc.
  • webkitregionfragmentchange. Non mis en œuvre au moment de cette modification. Cet événement est déclenché sur WebkitNamedFlow chaque fois que la mise en page du contenu associé change pour une raison quelconque (comme webkitregionoversetchange), mais indépendamment des modifications apportées aux propriétés webkitRegionOverset. Cet événement est utile pour écouter des modifications de mise en page ultraprécises qui n'affectent pas nécessairement l'ensemble de la mise en page du flux nommé. Par exemple, le contenu est déplacé d'une région à une autre, mais le contenu global s'adapte toujours à toutes les régions.
  • Element.webkitRegionOverset: les éléments deviennent des régions lorsque la propriété CSS flow-from leur est attribuée. Ces éléments ont une propriété webkitRegionOverset qui, s'ils font partie d'un flux nommé, indique si le contenu d'un flux déborde de la région. Les valeurs possibles de webkitRegionOverset sont :
    • "overflow" si le contenu dépasse la limite autorisée par la région
    • "fit" si le contenu s'arrête avant la fin de la région
    • "vide" si le contenu n'a pas atteint la région ;

L'une des principales utilisations du CSSOM consiste à écouter les événements webkitregionoversetchange et à ajouter ou supprimer dynamiquement des régions afin de prendre en charge différentes quantités de texte. Par exemple, si la quantité de texte à mettre en forme est imprévisible (peut-être générée par l'utilisateur), si la fenêtre du navigateur est redimensionnée ou si la taille de la police change, il peut être nécessaire d'ajouter ou de supprimer des régions pour s'adapter au changement du flux. De plus, si vous souhaitez organiser votre contenu en pages, vous aurez besoin d'un mécanisme permettant de modifier de façon dynamique le DOM ainsi que vos régions.

L'extrait de code JavaScript suivant illustre l'utilisation de CSSOM pour ajouter des régions de manière dynamique, si nécessaire. Notez que, par souci de simplicité, elle ne permet pas de supprimer des régions ni de définir la taille et les positions des régions. Elle n'est fournie qu'à titre de démonstration.

var flow = document.webkitGetNamedFlows().namedItem("article")
flow.addEventListener("webkitregionoversetchange", onLayoutUpdate);

function onLayoutUpdate(event) {
    var flow = event.target;
    
    // The content does not fit
    if (flow.overset === true) {
    addRegion();
    } else {
    regionLayoutComplete();
    }
}

function addRegion() {
    var region = document.createElement("div");
    region.style = "flow-from: article";
    document.body.appendChild(region);
}

function regionLayoutComplete() {
    // Finish up your layout.
}

D'autres démonstrations sont disponibles sur la page d'exemples des régions CSS.

Modèles de page CSS

L'utilisation de CSSOM est probablement le moyen le plus efficace et le plus flexible d'implémenter des éléments tels que la pagination et la mise en page responsive, mais Adobe travaille depuis suffisamment longtemps avec des outils de publication assistée par ordinateur pour savoir que les concepteurs et les développeurs veulent également un moyen plus simple d'obtenir des fonctionnalités de pagination relativement génériques. Par conséquent, nous travaillons sur une proposition appelée Modèles de page CSS, qui permet de définir le comportement de pagination de manière entièrement déclarative.

Examinons un cas d'utilisation courant des modèles de page CSS. L'extrait de code ci-dessous montre comment utiliser CSS pour créer deux flux nommés: "article-flow" et "timeline-flow". Il définit également un troisième sélecteur appelé "articles combinés", dans lequel les deux flux seront contenus. Le simple fait d'inclure la propriété overflow-style dans le sélecteur "combined-articles" indique que le contenu doit être paginé automatiquement selon l'axe X ou horizontalement:

<style>
    #article {
    { % mixin flow-into: article-flow; % }
    }

    #timeline {
    { % mixin flow-into: timeline-flow; % }
    }

    #combined-articles {
    overflow-style: paged-x;
    }
</style>

Maintenant que les flux ont été définis et que le comportement de dépassement souhaité a été spécifié, nous pouvons créer le modèle de page lui-même:

@template {
    @slot left {
    width: 35%;
    float: left;
    { % mixin flow-from: article-flow; % }
    }

    @slot time {
    width: 25%;
    float: left;
    { % mixin flow-from: timeline-flow; % }
    }

    @slot right {
    width: 35%;
    float: left;
    { % mixin flow-from: article-flow; % }
    }
}

Les modèles de page sont définis à l'aide de la nouvelle syntaxe "at". Dans l'extrait de code ci-dessus, nous définissons trois espaces, chacun correspondant à une colonne. Le texte du flux d'articles passera à travers les colonnes à gauche et à droite, et le texte du flux de la chronologie s'affichera dans la colonne du milieu. Le résultat devrait ressembler à ceci:

Exemple de modèles de page
Exemple de modèles de page

Notez que le texte de l'article (dans les colonnes de gauche et de droite) est en anglais et que la chronologie au centre est en allemand. En outre, les documents sont affichés horizontalement, sans code JavaScript. Tout a été entièrement réalisé de manière déclarative en CSS.

Les modèles de page CSS sont toujours une proposition, mais nous disposons d'un prototype qui utilise un "shim" JavaScript (également appelé polyfill) pour vous permettre de les tester dès maintenant.

Pour en savoir plus sur les régions CSS en général, consultez la page Régions CSS sur html.adobe.com.

Exclusions CSS

Pour obtenir une véritable mise en page de type magazine, il ne suffit pas de faire circuler le texte d'une région à l'autre. La possibilité de faire circuler le texte autour ou à l'intérieur de graphiques et de formes irrégulières est un élément essentiel d'une publication assistée par ordinateur de haute qualité et visuellement attrayante. Avec les exclusions CSS, vous profitez d'une qualité de production équivalente sur le Web.

La capture d'écran ci-dessous provient d'un prototype d'exclusions CSS. Elle montre du texte circulant de façon dynamique autour d'un tracé qui correspond au contour d'une grande formation rocheuse:

Exemple d&#39;exclusions CSS
Exemple d'exclusions CSS en action

L'inverse est illustré dans la capture d'écran suivante: le texte s'écoule à l'intérieur de polygones de forme irrégulière:

Texte qui s&#39;écoule dans des polygones de forme irrégulière
Texte se déversant dans des polygones de forme irrégulière

La première étape pour pouvoir insérer du texte autour ou à l'intérieur de formes arbitraires consiste à développer et à optimiser les algorithmes requis. Adobe travaille actuellement sur des implémentations qui seront directement ajoutées à WebKit. Une fois ces algorithmes optimisés, ils serviront de base sur le reste des exclusions CSS.

Pour en savoir plus sur les exclusions CSS, consultez la page des exclusions CSS sur html.adobe.com. Pour en savoir plus sur le travail d'Adobe sur la technologie sous-jacente des exclusions CSS, consultez l'article de blog d'Hans Muller intitulé Horizontal Box: Polygon Intersection for CSS Exclusions (Boîte horizontale : intersection de polygones pour les exclusions CSS).

État actuel des régions CSS et des exclusions CSS

La première fois que j'ai parlé publiquement des régions CSS et des exclusions CSS, c'était lors d'une session Adobe Developer lors de la conférence Google I/O 2011. À l'époque, je montais des démonstrations dans notre propre navigateur de prototype personnalisé. L'accueil a été extrêmement enthousiaste, mais les visiteurs ont eu un sentiment de déception lorsqu'ils découvraient qu'aucune des fonctionnalités que je montrais n'était encore disponible dans les principaux navigateurs.

J'ai de nouveau assisté à la conférence Google I/O cette année (2012), en tant que présentateur, aux côtés de mon collègue Vincent Hardy et Alex Danilo de Google (vous pouvez regarder la présentation ici). Un an plus tard, environ 80% de la spécification CSS Regions a été implémentée dans WebKit et figure déjà dans la version la plus récente de Google Chrome (notez que les régions CSS doivent actuellement être activées via chrome://flags). La prise en charge préliminaire des régions CSS est même disponible dans Chrome pour Android:

Régions sur Chrome pour Android
Régions sur Chrome pour Android

De plus, les régions CSS et les exclusions CSS sont implémentées dans l'aperçu d'Internet Explorer 10 et figurent actuellement dans la feuille de route 2012 de Mozilla pour Firefox. La prochaine version majeure de Safari devrait être compatible avec la majorité des spécifications CSS Regions, et les mises à jour ultérieures devraient inclure le reste.

Vous trouverez ci-dessous un calendrier détaillé des progrès que nous avons réalisés avec les régions CSS et les exclusions CSS depuis notre proposition initiale envoyée au W3C en avril 2011:

Progression de la région et de l&#39;exclusion
Région et progression de l'exclusion

Conclusion

Adobe possède une grande expérience dans le domaine du texte, des polices et de la publication assistée par ordinateur via des outils tels qu'InDesign. Même si le Web est déjà une plate-forme très puissante pour le texte, nous souhaitons mettre à profit nos connaissances et notre expérience pour repousser les limites de la présentation. Les régions CSS et les exclusions CSS permettent au contenu de conserver une structure sémantique tout en offrant une véritable mise en page de type magazine, et en fin de compte, un Web beaucoup plus expressif.