Design, ordre de focus et Accessibilité
Objectif
Afficher un bloc (image, texte, etc…) à différents endroits au sein d'une page selon le viewport sans dupliquer n fois le contenu et conserver le flux « logique » de navigation, notamment pour la navigation au clavier.
La gestion visible/invisible est gérée par une classique feuille de styles (flex ou autre).
Les blocs porteurs doivent avoir un attribut égal (par défaut data-responsive). De cette
manière, il est possible de gérer plusieurs contenus au sein de la même page.
Au moins 1 de ces éléments doit contenir le markup à déplacer.
Exemple
Les 5 blocs suivants se déplacent selon le viewport (tester en affichant la console et la vue adaptative).
Bloc numéro 1
Bloc numéro 2
Bloc numéro 4
Bloc numéro 5
En utilisant le clavier pour naviguer avec Touche clavier Tabulation ⇥ , l'ordre d'affichage respecte l'ordre de tabulation.
La partie code HTML
<div class="flex half-gutter no-fit text-align-center margin-top-gutter" id="items-list">
 <!-- bloc vide ID data-slot="plop" -->
 <div class="xs-hide s-hide m-hide l-7 xl-8 flex" data-slot="plop"></div>
 <!-- bloc rempli qui sera déplacé selon le viewport ID data-responsive="foo" -->
 <div class="xs-4 s-12 m-hide l-5 xl-12 xl-hide flex" data-responsive="foo">
 <p tabindex="0" class="items-list-item border-radius font-family-traverse font-size-50 s-12 black background-color-limegreen box-shadow-under" id="foo">
 <span class="screen-readers">Bloc numéro </span>1
 </p>
 </div>
 <p tabindex="0" class="items-list-item border-radius xs-8 s-4 m-4 l-5 xl-4 font-family-traverse font-size-50 black background-color-orange box-shadow-under">
 <span class="screen-readers">Bloc numéro </span>2
 </p>
 <div class="xs-hide s-hide m-4 l-hide xl-5">
 <!-- bloc vide ID data-responsive="foo" -->
 <div class="flex" data-responsive="foo"></div>
 <!-- bloc vide ID data-responsive="bar" -->
 <div class="margin-top-half-gutter flex" data-responsive="bar"></div>
 </div>
 <div tabindex="0" class="items-list-item border-radius xs-6 s-8 m-4 l-7 xl-7 font-family-traverse font-size-50 black background-color-antigua box-shadow-under">
 <span class="screen-readers">Bloc numéro </span>3
 </div>
 <!-- bloc rempli qui sera déplacé selon le viewport ID data-responsive="bar" -->
 <div class="xs-3 s-8 m-hide l-12 xl-hide flex" data-responsive="bar">
 <p tabindex="0" class="items-list-item border-radius font-family-traverse font-size-50 s-12 black background-color-lightgray box-shadow-under" id="bar">
 <span class="screen-readers">Bloc numéro </span>4
 </p>
 </div>
 
 <!-- bloc rempli qui sera déplacé selon le viewport ID data-responsive="plop" -->
 <div class="xs-3 s-4 m-12 l-hide xl-hide flex" data-slot="plop">
 <p tabindex="0" class="items-list-item border-radius font-family-traverse font-size-50 s-12 black background-color-yellow box-shadow-under" id="plop">
 <span class="screen-readers">Bloc numéro </span>5
 </p>
 </div>
</div>
Et enfin la fonction…
/*
 * Copyright © 2006 2024. Kortic (URL : https://www.kortic.com/ordre-de-focus-et-presentation-mobile-versus-desktop.html)
 * licence Creative Commons CC BY-NC-SA 4.0
 * https://creativecommons.org/licenses/by-nc-sa/4.0/deed.fr
 */
 
;((__) => {
 'use strict';
 __.fn.responsiveLayout = function(opts) {
 let settings = __.extend({
 'attribute': 'data-responsive',
 'enableResize': false
 }, opts);
 this.each(function() {
 let this_ = __(this),
 attribute_ = settings.attribute,
 set_ = __( '[' + attribute_ + '="' + this_.parent().attr( attribute_ ) + '"]' ),
 cloned = this_.clone();
 let init = () => {
 set_.each(function() {
 let this__ = __(this);
 if(this__.is(':visible')) {
 if(!this__.html().length) {
 this__.append(cloned.clone());
 }
 /*
 callback de ce site
 */
 try {
 this__.find('[data-calculate="true"]').doOnce( function() {
 this.deduct();
 });
 __.material_labels();
 __.targeting(this__);
 __.lazyLoadingAttributesObserver(this__);
 } catch(e){
 console.warn(e);
 }
 /*
 end callback
 */
 } else {
 this__.empty();
 }
 });
 };
 !settings.enableResize && init();
 if(settings.enableResize) {
 const resizeObserver = new ResizeObserver((entries) => {
 entries[0].contentBoxSize && init();
 });
 resizeObserver.observe(document.documentElement);
 }
 return this;
 });
 };
})(jQuery);
Appel de fonction
<script nonce="419cf8f52fcd7151dc5b69b902c4ee20d4b1be01">
 /* 
 l'attribut nonce n'est utilisé que pour ce site.
 Pour en savoir plus : https://content-security-policy.com 
 */
 (function () {
 'use strict';
 jQuery(document).ready(() => {
 jQuery('#bar, #foo').responsiveLayout({
 enableResize: true
 });
 // avec attribut spécifique
 jQuery('#plop').responsiveLayout({
 enableResize: true,
 attribute: 'data-slot'
 });
 })
 })();
</script>
Vous aimez cette page ?
Dites-le !
Utilisation des sources
Les sources proposées sur Kortic Anthony Ladeuil sont mises à disposition selon les termes suivants :
Licence Creative commons CC BY-NC-SA 4.0
- Attribution
-
Détails
Vous devez créditer l'Œuvre, intégrer un lien vers la licence et indiquer si des modifications ont été effectuées à l'Oeuvre. Vous devez indiquer ces informations par tous les moyens raisonnables, sans toutefois suggérer que l'Offrant vous soutient ou soutient la façon dont vous avez utilisé son Oeuvre.
- Pas d’utilisation commerciale
-
Détails
Vous n'êtes pas autorisé à faire un usage commercial de cette Oeuvre, tout ou partie du matériel la composant.
Bien entendu, la probabilité est faible pour que ce point soit respecté. En cas de sursaut d'honnêteté, vous pouvez payer un café, cette page soulagera votre conscience. - Partage dans les mêmes conditions
-
Détails
Dans le cas où vous effectuez un remix, que vous transformez, ou créez à partir du matériel composant l'Oeuvre originale, vous devez diffuser l'Oeuvre modifiée dans les même conditions, c'est à dire avec la même licence avec laquelle l'Oeuvre originale a été diffusée.
À défaut de tout ça, un petit message et une référence à ce site restent les bienvenus.
Limitation de responsabilité
Le code est fourni « tel quel », sans garantie d'aucune sorte, expresse ou implicite. En aucun cas l’auteur ou les détenteurs du copyright ne seront responsables de toute réclamation, dommage ou autre responsabilité, que ce soit dans une action contractuelle, délictuelle ou autre, résultant de, en dehors ou en relation avec le logiciel ou l'utilisation ou d'autres transactions.