Créer un composant "Tabs"

Découvrez comment créer un composant d'onglet semblable à celui des applications iOS et Android.

Dans ce message, je vais vous expliquer comment créer un composant "Onglets" pour le Web. réactif, compatible avec plusieurs entrées d'appareils et compatible avec tous les navigateurs. Essayez la démonstration.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Démonstration

Si vous préférez la vidéo, voici une version YouTube de cet article:

Présentation

Les onglets sont un composant courant des systèmes de conception, mais ils peuvent prendre de nombreuses formes et formulaires. Au début, nous avons eu des onglets pour ordinateur basés sur l'élément <frame>, et nous avons maintenant pour animer du contenu basé sur des propriétés physiques. Ils essaient tous de faire la même chose: économiser de l'espace.

Aujourd'hui, l'essentiel de l'expérience utilisateur des onglets est une zone de navigation à boutons qui active ou désactive la visibilité du contenu dans un cadre d'affichage. Nombreuses zones de contenu partagent le même espace, mais sont présentées de manière conditionnelle en fonction de la sélectionné dans la navigation.

<ph type="x-smartling-placeholder">
</ph> le montage est assez chaotique en raison de l&#39;immense diversité de styles que le Web a appliqués au concept de composant. <ph type="x-smartling-placeholder">
</ph> Montage de styles de conception Web de composants d'onglet datant des 10 dernières années
.

Tactiques Web

Dans l'ensemble, j'ai trouvé ce composant assez simple à créer, grâce à quelques fonctionnalités essentielles de la plate-forme Web:

  • scroll-snap-points pour des interactions élégantes avec le clavier et le balayage les positions d'arrêt appropriées du défilement
  • Liens profonds via des hachages d'URL pour ancrage de défilement sur la page géré par le navigateur et prise en charge du partage
  • Compatibilité du lecteur d'écran avec le balisage des éléments <a> et id="#hash"
  • prefers-reduced-motion pour activer des transitions en fondu enchaîné et des défilement dans la page
  • La fonctionnalité Web @scroll-timeline In-draft permettant de souligner et de modification de la couleur de l'onglet sélectionné

Le code HTML

Fondamentalement, l'expérience utilisateur est ici: cliquez sur un lien, faites en sorte que l'URL représente le l'état de la page, puis la zone de contenu est mise à jour à mesure que le navigateur correspondant.

Il contient des éléments de contenu structurel: des liens et des :target. Mer vous avez besoin d'une liste de liens, ce qui est idéal pour <nav>, et d'une liste de <article>. ce qui est idéal pour <section>. Chaque hachage de lien correspond à une section, permettant au navigateur de faire défiler les éléments grâce à l'ancrage.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Clic sur le bouton d'un lien qui glisse vers le contenu sélectionné

Par exemple, si vous cliquez sur un lien, l'article :target dans Chrome 89, aucun JS requis. L'utilisateur peut alors faire défiler le contenu de l'article leur périphérique d'entrée, comme toujours. Il s'agit d'un contenu sans frais, comme indiqué dans les le balisage.

J'ai utilisé le balisage suivant pour organiser les onglets:

<snap-tabs>
  <header>
    <nav>
      <a></a>
      <a></a>
      <a></a>
      <a></a>
    </nav>
  </header>
  <section>
    <article></article>
    <article></article>
    <article></article>
    <article></article>
  </section>
</snap-tabs>

Je peux établir des connexions entre les éléments <a> et <article> avec href et id, par exemple:

<snap-tabs>
  <header>
    <nav>
      <a href="#responsive"></a>
      <a href="#accessible"></a>
      <a href="#overscroll"></a>
      <a href="#more"></a>
    </nav>
  </header>
  <section>
    <article id="responsive"></article>
    <article id="accessible"></article>
    <article id="overscroll"></article>
    <article id="more"></article>
  </section>
</snap-tabs>

J'ai ensuite rempli les articles avec des quantités mélangées de lorem, et les liens avec un des titres de longueur mixte et d'images. Avec le contenu avec lequel travailler, nous pouvons commencer mise en page.

Mises en page défilantes

Il existe trois types de zones de défilement dans ce composant:

  • La navigation (rose) est horizontale. à faire défiler
  • La zone de contenu (bleu) est placée horizontalement. à faire défiler
  • Chaque article (vert) se trouve verticalement que l'on peut faire défiler.
Trois cadres colorés avec des flèches directionnelles assorties de couleurs qui délimitent les zones de défilement et indiquent leur direction.

Le défilement repose sur deux types d'éléments:

  1. Une fenêtre
    Boîte avec des dimensions définies et contenant le overflow du style de propriété.
  2. Une surface surdimensionnée
    Dans cette mise en page, il s'agit des conteneurs de liste: nav les liens, les articles de section et le contenu des articles.

Mise en page <snap-tabs>

La mise en page de premier niveau que j'ai choisie était Flex (Flexbox). je définis la direction sur column : l'en-tête et la section sont organisés verticalement. C'est notre premier fenêtre de défilement, et il masque tout avec le débordement masqué. L'en-tête et utilisera bientôt le défilement hors limites, en tant que zones individuelles.

HTML
<snap-tabs>
  <header></header>
  <section></section>
</snap-tabs>
CSS
  snap-tabs {
  display: flex;
  flex-direction: column;

  /* establish primary containing box */
  overflow: hidden;
  position: relative;

  & > section {
    /* be pushy about consuming all space */
    block-size: 100%;
  }

  & > header {
    /* defend against 
needing 100% */ flex-shrink: 0; /* fixes cross browser quarks */ min-block-size: fit-content; } }

Revenons au diagramme coloré à trois défilements:

  • <header> est maintenant prêt à devenir la (rose) conteneur de défilement.
  • <section> est prêt à être le défilement (bleu). conteneur.

Les cadres que j'ai mis en évidence ci-dessous avec VisBug permet de visualiser les fenêtres que les conteneurs de défilement ont été créés.

Les éléments d&#39;en-tête et de section comportent des superpositions en rose qui décrivent l&#39;espace qu&#39;ils occupent dans le composant.

Mise en page des onglets <header>

La mise en page suivante est presque la même: j'utilise le format Flex pour créer un ordre vertical.

HTML
<snap-tabs>
  <header>
    <nav></nav>
    <span class="snap-indicator"></span>
  </header>
  <section></section>
</snap-tabs>
CSS
header {
  display: flex;
  flex-direction: column;
}

Le .snap-indicator doit se déplacer horizontalement avec le groupe de liens. cette mise en page d'en-tête aide à préparer cette scène. Aucun élément positionné absolu.

Les éléments nav et span.indicator comportent des superpositions en rose qui décrivent l&#39;espace qu&#39;ils occupent dans le composant.

Ensuite, les styles de défilement. Il s'avère que nous pouvons partager les styles de défilement entre nos 2 zones de défilement horizontal (en-tête et section). J'ai donc créé un utilitaire .scroll-snap-x.

.scroll-snap-x {
  /* browser decide if x is ok to scroll and show bars on, y hidden */
  overflow: auto hidden;
  /* prevent scroll chaining on x scroll */
  overscroll-behavior-x: contain;
  /* scrolling should snap children on x */
  scroll-snap-type: x mandatory;

  @media (hover: none) {
    scrollbar-width: none;

    &::-webkit-scrollbar {
      width: 0;
      height: 0;
    }
  }
}

Chacun doit dépasser sur l'axe X, contenir le défilement pour piéger le défilement hors limites, masqué Barres de défilement pour appareils tactiles et appui sur l'écran pour verrouiller le contenu zones de présentation. L'ordre de tabulation de notre clavier est accessible et le guide des interactions se concentrer naturellement. Les conteneurs d'ancrage de défilement bénéficient également d'un joli style de carrousel à partir de leur clavier.

Mise en page de l'en-tête des onglets <nav>

Les liens de navigation doivent être disposés verticalement, sans saut de ligne. centré, et chaque élément du lien doit s'aligner sur le conteneur d'ancrage de défilement. Swift pour les CSS 2021 !

HTML
<nav>
  <a></a>
  <a></a>
  <a></a>
  <a></a>
</nav>
CSS
  nav {
  display: flex;

  & a {
    scroll-snap-align: start;

    display: inline-flex;
    align-items: center;
    white-space: nowrap;
  }
}

Le style et la taille de chaque lien sont définis de lui-même. Il suffit donc de spécifier la mise en page la direction et le flux. Les largeurs uniques des éléments de navigation facilitent la transition entre les onglets amusant, car l'indicateur adapte sa largeur à la nouvelle cible. En fonction du nombre sont affichées, le navigateur affiche ou non une barre de défilement.

Les éléments A de la navigation comportent des superpositions en rose qui décrivent l&#39;espace qu&#39;ils occupent dans le composant, ainsi que les endroits où ils débordent.

Mise en page des onglets <section>

Cette section est un article flexible qui doit être le consommateur dominant de l'espace. Il doit également créer des colonnes dans lesquelles les articles seront placés. Encore une fois, pour CSS 2021 ! block-size: 100% étire cet élément pour remplir parent autant que possible, puis, pour sa propre mise en page, crée une série colonnes dont la largeur est égale à 100% du parent. Les pourcentages sont très efficaces dans ce cas de figure. car nous avons écrit des contraintes fortes sur le parent.

HTML
<section>
  <article></article>
  <article></article>
  <article></article>
  <article></article>
</section>
CSS
  section {
  block-size: 100%;

  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
}

C'est comme si nous voulions dire "développer verticalement le plus possible le tout en accentuant l'intensité". (retenez l'en-tête que nous avons défini sur flex-shrink: 0: il s'agit d'une défense contre cette push de l'expansion), qui définit la hauteur des lignes pour un ensemble de colonnes sur toute la hauteur. La Le style auto-flow indique à la grille de toujours disposer les enfants à l'horizontale sans retour à la ligne, exactement ce que nous voulons, pour faire déborder la fenêtre parente.

Les éléments de l&#39;article comportent des superpositions roses indiquant l&#39;espace qu&#39;ils occupent dans le composant et l&#39;endroit où ils débordent.

J'ai parfois du mal à me comprendre. Cet élément de section est s'emboîtent dans une boîte, mais a également créé un jeu de boîtes. J'espère que les visuels et les explications sont utiles.

Mise en page des onglets <article>

L'utilisateur doit pouvoir faire défiler le contenu de l'article, et les barres de défilement doivent ne s'affichent que s'il y a un débordement. Ces éléments d'article sont présentés de façon la position de votre annonce. Ils sont à la fois un parent de défilement et un enfant de défilement. La le navigateur gère certaines interactions délicates au toucher, à la souris et au clavier. pour nous ici.

HTML
<article>
  <h2></h2>
  <p></p>
  <p></p>
  <h2></h2>
  <p></p>
  <p></p>
  ...
</article>
CSS
article {
  scroll-snap-align: start;

  overflow-y: auto;
  overscroll-behavior-y: contain;
}

J'ai choisi d'ancrer les articles dans le conteneur de défilement parent. J'aime beaucoup comment les éléments du lien de navigation et ceux de l'article s'alignent sur le démarrage intégré ; de leurs conteneurs de défilement respectifs. Le rendu est harmonieux relation.

L&#39;élément article et ses éléments enfants comportent des superpositions en rose qui décrivent l&#39;espace qu&#39;ils occupent dans le composant et la direction dans laquelle ils débordent.

L'article est un élément enfant de la grille, dont la taille est prédéterminée par rapport à la fenêtre d'affichage dans lequel nous voulons fournir une expérience utilisateur de défilement. Cela signifie que je n'ai pas besoin de hauteur ni de largeur ici, il me suffit de définir comment il déborde. Je définis overflow-y sur auto, et piéger les interactions de défilement avec le comportement pratique de défilement hors limites. .

Résumé des trois zones de défilement

Ci-dessous, j'ai choisi dans mes paramètres système l'option "Toujours afficher les barres de défilement". Je pense il est deux fois important que la mise en page fonctionne avec ce paramètre activé, car il est de revoir la mise en page et l'orchestration du défilement.

Les 3 barres de défilement sont configurées pour s&#39;afficher, ce qui occupe désormais de l&#39;espace dans la mise en page et notre composant reste esthétique.

Je pense que le fait de voir la marge de la barre de défilement dans ce composant permet de montrer clairement où les zones de défilement, la direction qu'elles prennent en charge et la façon dont elles interagissent avec les uns les autres. Réfléchissez au fait que chacun de ces cadres de fenêtre de défilement est également flexible ou les parents de grille à une mise en page.

Les outils de développement peuvent nous aider à visualiser cela:

<ph type="x-smartling-placeholder">
</ph> Les zones de défilement comportent des superpositions d&#39;outil de grille et Flexbox, qui indiquent l&#39;espace qu&#39;elles occupent dans le composant et la direction dans laquelle elles débordent. <ph type="x-smartling-placeholder">
</ph> Outils pour les développeurs Chromium, affichant la mise en page d'élément de navigation Flexbox remplie d'éléments d'ancrage la mise en page sous forme de grille, remplie d'éléments d'article, et l'article contenant des paragraphes et un élément de titre.

Mises en page de défilement terminées: ancrage, lien profond et clavier accessibles. Base solide pour l'amélioration de l'expérience utilisateur, le style et la satisfaction.

Fonctionnalité mise en avant

Les enfants bloqués lors du défilement conservent leur position verrouillée pendant le redimensionnement. Cela signifie JavaScript n'a pas besoin d'afficher quoi que ce soit lors de la rotation de l'appareil ou du navigateur. redimensionner. Faites un essai dans les outils pour les développeurs Chromium Appareil Mode par en sélectionnant un mode autre que Responsive, puis en redimensionnant le cadre de l'appareil. Notez que l'élément reste affiché et verrouillé avec son contenu. Cela a été disponibles, car Chromium a mis à jour leur implémentation pour répondre aux spécifications. Voici un article de blog à ce sujet.

Animation

L'objectif de l'animation est ici de lier clairement les interactions avec l'UI commentaires. Cela permet de guider ou d'aider l'utilisateur jusqu'à sa la découverte de tous les contenus. Je vais ajouter du mouvement avec un but et sous certaines conditions. Les utilisateurs peuvent désormais spécifier leurs mouvements préférences dans leur système d'exploitation, et j’aime beaucoup répondre à leurs préférences dans mes interfaces.

Je vais lier une tabulation soulignée à la position de défilement de l'article. L'ancrage n'est pas un alignement correct, c'est aussi ancrer le début et la fin d'une animation. Cela permet de conserver le <nav>, qui agit comme mini-carte associée au contenu. Nous allons vérifier la préférence de mouvement de l'utilisateur à partir du CSS et de JS. Il y a un quelques excellents endroits à prendre en considération !

Comportement du défilement

Vous pouvez améliorer le comportement de mouvement de :target et element.scrollIntoView() Par défaut, l'action est instantanée. Le navigateur définit simplement la position de défilement. Que se passe-t-il si nous voulons passer à cette position de défilement ? au lieu de cligner des yeux là ?

@media (prefers-reduced-motion: no-preference) {
  .scroll-snap-x {
    scroll-behavior: smooth;
  }
}

Puisque nous introduisons du mouvement ici, et un mouvement que l'utilisateur ne contrôle pas (comme le défilement), nous n'appliquons ce style que si l'utilisateur n'a aucune préférence leur système d’exploitation autour d’une réduction des mouvements. De cette façon, nous n'introduisons que le défilement du mouvement pour les personnes qui sont d’accord.

Indicateur d'onglets

Le but de cette animation est d'associer l'indicateur à l'état du contenu. J'ai décidé d'appliquer un fondu enchaîné aux styles border-bottom de couleur pour les utilisateurs qui préfèrent réduire les mouvements et associer le défilement avec une animation glissante et un fondu en couleur pour les utilisateurs qui acceptent les mouvements.

Dans les outils pour les développeurs Chromium, je peux activer/désactiver la préférence et montrer les deux différents styles de transition. J'ai pris beaucoup de plaisir à construire ça.

@media (prefers-reduced-motion: reduce) {
  snap-tabs > header a {
    border-block-end: var(--indicator-size) solid hsl(var(--accent) / 0%);
    transition: color .7s ease, border-color .5s ease;

    &:is(:target,:active,[active]) {
      color: var(--text-active-color);
      border-block-end-color: hsl(var(--accent));
    }
  }

  snap-tabs .snap-indicator {
    visibility: hidden;
  }
}

Je masque .snap-indicator lorsque l'utilisateur préfère réduire les mouvements, car je ne n'en ont plus besoin. Je le remplace ensuite par border-block-end styles et transition Notez également dans l'interaction avec les onglets que l'élément de navigation actif n'est pas la marque est surlignée uniquement, mais la couleur du texte est également plus sombre. La l'élément actif présente un contraste des couleurs du texte plus élevé et un fort accent sur la luminosité.

Quelques lignes de CSS suffisent pour donner l'impression nous respectons scrupuleusement leurs préférences de mouvement). J'adore.

@scroll-timeline

Dans la section ci-dessus, je vous ai montré comment gérer le fondu enchaîné en mouvement réduit. et, dans cette section, je vais vous montrer comment j'ai associé l'indicateur dans la zone de défilement. Voici quelques nouveautés expérimentales à venir. J’espère que vous aussi excité que moi.

const { matches:motionOK } = window.matchMedia(
  '(prefers-reduced-motion: no-preference)'
);

Je vérifie d'abord les préférences de mouvement de l'utilisateur dans JavaScript. Si le résultat de il s'agit de false, ce qui signifie que l'utilisateur préfère les mouvements réduits, alors nous n'exécuterons des effets de mouvement de lien de défilement.

if (motionOK) {
  // motion based animation code
}

Au moment de la rédaction de ce document, la compatibilité des navigateurs @scroll-timeline est vide. Il s'agit d'un spécification brouillon contenant uniquement des mises en œuvre expérimentales. Il dispose cependant d'un polyfill, que j'utilise dans ce la démo.

ScrollTimeline

Même si les langages CSS et JavaScript permettent tous les deux de créer des timelines de défilement, du code JavaScript pour pouvoir utiliser les mesures des éléments actifs dans l'animation.

const sectionScrollTimeline = new ScrollTimeline({
  scrollSource: tabsection,  // snap-tabs > section
  orientation: 'inline',     // scroll in the direction letters flow
  fill: 'both',              // bi-directional linking
});

Je veux qu'un élément suive la position de défilement d'un autre, et en créant une ScrollTimeline Je définis le pilote du lien de défilement, scrollSource. Normalement, une animation sur le Web s'exécute par rapport à un intervalle de temps global, mais avec un sectionScrollTimeline personnalisé en mémoire, je peux tout changer.

tabindicator.animate({
    transform: ...,
    width: ...,
  }, {
    duration: 1000,
    fill: 'both',
    timeline: sectionScrollTimeline,
  }
);

Avant d'entrer dans les images clés de l'animation, indiquer que le followers du défilement, tabindicator, sera animé en fonction sur une timeline personnalisée, le défilement de notre section. L'association est alors terminée, mais il manque l'ingrédient final, les points avec état à animer, également appelés et des images clés.

Images clés dynamiques

Il existe une méthode d'animation CSS déclarative pure et très efficace @scroll-timeline, mais l'animation que j'ai choisie est trop dynamique Il n'y a aucun permettant d'effectuer une transition entre la largeur auto. De plus, il n'existe aucun moyen de créer dynamiquement un certain nombre d'images clés selon la longueur des enfants.

Toutefois, JavaScript sait comment obtenir ces informations. Nous allons donc itérer sur le nous-mêmes et récupère les valeurs calculées au moment de l'exécution:

tabindicator.animate({
    transform: [...tabnavitems].map(({offsetLeft}) =>
      `translateX(${offsetLeft}px)`),
    width: [...tabnavitems].map(({offsetWidth}) =>
      `${offsetWidth}px`)
  }, {
    duration: 1000,
    fill: 'both',
    timeline: sectionScrollTimeline,
  }
);

Pour chaque tabnavitem, déstructurez la position offsetLeft et renvoyez une chaîne qui l'utilise comme valeur translateX. Cela crée quatre images clés de transformation pour de l'animation. La même chose est faite pour la largeur, on demande à chacun quelle est sa largeur dynamique Elle est ensuite utilisée comme valeur d'image clé.

Voici un exemple de résultat basé sur mes polices et mes préférences de navigateur:

Images clés TranslateX:

[...tabnavitems].map(({offsetLeft}) =>
  `translateX(${offsetLeft}px)`)

// results in 4 array items, which represent 4 keyframe states
// ["translateX(0px)", "translateX(121px)", "translateX(238px)", "translateX(464px)"]

Images clés en largeur:

[...tabnavitems].map(({offsetWidth}) =>
  `${offsetWidth}px`)

// results in 4 array items, which represent 4 keyframe states
// ["121px", "117px", "226px", "67px"]

Pour résumer la stratégie, l'indicateur d'onglet s'anime désormais sur quatre images clés. en fonction de la position d'ancrage du défilement du conteneur de défilement. Les points d'ancrage de façon claire et nette entre les images clés, synchronisée de l'animation.

l&#39;onglet actif et l&#39;onglet inactif sont affichés avec des superpositions VisBug qui indiquent les scores de contraste acceptables pour les deux

L'utilisateur pilote l'animation avec son interaction, en voyant la largeur et la position du changement d'indicateur d'une section à l'autre, le suivi parfaitement avec le défilement.

Vous ne l’avez peut-être pas remarqué, mais je suis très fier de la transition des couleurs l'élément de navigation en surbrillance est sélectionné.

Le gris clair non sélectionné est encore plus repoussé lorsque la case en surbrillance a plus de contraste. Il est courant d'avoir une couleur de transition pour le texte, comme lors d'un survol et lorsqu'il est sélectionné, mais c'est le niveau suivant pour passer à cette couleur lors du défilement, synchronisé avec l'indicateur de soulignement.

Voici comment j'ai fait:

tabnavitems.forEach(navitem => {
  navitem.animate({
      color: [...tabnavitems].map(item =>
        item === navitem
          ? `var(--text-active-color)`
          : `var(--text-color)`)
    }, {
      duration: 1000,
      fill: 'both',
      timeline: sectionScrollTimeline,
    }
  );
});

Chaque lien de navigation de l'onglet nécessite cette nouvelle animation en couleur, qui suit le même défilement chronologie comme indicateur de soulignement. J'utilise le même calendrier qu'avant: puisque son rôle est d'émettre un tick lors du défilement, nous pouvons l'utiliser dans n'importe quel type l'animation souhaitée. Comme je l'ai fait précédemment, je crée quatre images clés dans la boucle, puis je reviens couleurs.

[...tabnavitems].map(item =>
  item === navitem
    ? `var(--text-active-color)`
    : `var(--text-color)`)

// results in 4 array items, which represent 4 keyframe states
// [
  "var(--text-active-color)",
  "var(--text-color)",
  "var(--text-color)",
  "var(--text-color)",
]

L'image clé avec la couleur var(--text-active-color) met en surbrillance le lien, puis il s'agit sinon d'une couleur de texte standard. La boucle imbriquée ici rend relativement simple, car la boucle externe correspond à chaque élément de navigation, tandis que la boucle interne les images clés personnelles de navitem. Je vérifie si l'élément de la boucle externe est identique à la boucle interne 1, et l’utiliser pour savoir quand elle est sélectionnée.

J'ai pris beaucoup de plaisir à écrire ce texte. Vraiment.

Encore plus d'améliorations JavaScript

Sachez que l'essentiel de ce que je vous montre ici fonctionne sans JavaScript. Cela étant dit, voyons comment nous pouvons l'améliorer lorsque JS est disponibles.

Les liens profonds sont davantage un terme mobile, mais je pense qu'ils ont pour but vous permet de partager une URL directement vers le contenu d'un onglet. La navigateur accède à l'ID correspondant dans le hachage de l'URL. J'ai trouvé ce gestionnaire onload a eu l'effet sur toutes les plates-formes.

window.onload = () => {
  if (location.hash) {
    tabsection.scrollLeft = document
      .querySelector(location.hash)
      .offsetLeft;
  }
}

Faire défiler et terminer la synchronisation

Nos utilisateurs n'utilisent pas toujours le clavier ou cliquent dessus. Parfois, ils ne font que défilement libre, comme ils devraient pouvoir le faire. Lorsque la barre de défilement de la section s'arrête le défilement, quel que soit l'endroit où il se trouve doit être mis en correspondance dans la barre de navigation supérieure.

Voici comment j'attends la fin du défilement: js tabsection.addEventListener('scroll', () => { clearTimeout(tabsection.scrollEndTimer); tabsection.scrollEndTimer = setTimeout(determineActiveTabSection, 100); });

À chaque fois que vous faites défiler les sections, effacez le délai avant expiration de la section, le cas échéant. et en démarrer un nouveau. N'effacez pas le délai avant expiration lorsque les sections ne font plus défiler l'écran. et se déclenche 100 ms après le repos. Lorsqu'elle se déclenche, appelez la fonction qui cherche à déterminer là où l’utilisateur s’est arrêté.

const determineActiveTabSection = () => {
  const i = tabsection.scrollLeft / tabsection.clientWidth;
  const matchingNavItem = tabnavitems[i];

  matchingNavItem && setActiveTab(matchingNavItem);
};

En supposant que le défilement est aligné, en divisant la position de défilement actuelle de la largeur de la zone de défilement doit renvoyer un nombre entier et non un nombre décimal. J'essaie ensuite de récupère un élément navitem de notre cache via cet index calculé, et s'il trouve quelque chose, j'envoie la correspondance pour qu'elle soit active.

const setActiveTab = tabbtn => {
  tabnav
    .querySelector(':scope a[active]')
    .removeAttribute('active');

  tabbtn.setAttribute('active', '');
  tabbtn.scrollIntoView();
};

Pour définir un onglet actif, commencez par effacer tout onglet actif, puis pour l'élément de navigation entrant l'attribut d'état actif. Appel à scrollIntoView() offre une interaction amusante avec le CSS.

.scroll-snap-x {
  overflow: auto hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;

  @media (prefers-reduced-motion: no-preference) {
    scroll-behavior: smooth;
  }
}

Dans l'utilitaire CSS de l'utilitaire de défilement horizontal, nous avons imbriqué, une requête média qui s'applique Défilement smooth si l'utilisateur tolère les mouvements JavaScript peut librement créer pour faire défiler les éléments, et CSS peut gérer l'expérience utilisateur de manière déclarative. Les plus plaisants qu'on trouve parfois.

Conclusion

Maintenant que tu sais comment j'ai fait, comment faire ?! Cela permet de s'amuser une architecture de composants. Qui va créer la 1re version avec des emplacements dans sa votre framework préféré ? 🙂

Diversifiez nos approches et découvrons toutes les manières de créer des applications sur le Web. Créer un Glitch, me envoyer un tweet votre version, et je l'ajouterai à la section Remix de la communauté ci-dessous.

Remix de la communauté