Creazione di un componente Schede

Una panoramica di base su come creare un componente per le schede simile a quello delle app per iOS e Android.

In questo post, voglio condividere i tuoi pensieri sulla creazione di un componente Schede per il web reattivo, supporta più input dei dispositivi e funziona su tutti i browser. Prova la demo.

Demo

Se preferisci i video, ecco una versione di questo post su YouTube:

Panoramica

Le schede sono un componente comune dei sistemi di progettazione, ma possono assumere molte forme e moduli. All'inizio, le schede sul desktop erano basate sull'elemento <frame> e ora abbiamo componenti mobile burrosi che animano contenuti in base alle proprietà fisiche. Stanno tutti cercando di fare la stessa cosa: risparmiare spazio.

Oggi, l'essenziale di un'esperienza utente basata sulle schede è un'area di navigazione con pulsanti che attiva/disattiva la visibilità dei contenuti in un frame. Molti modi diversi aree di contenuti condividono lo stesso spazio, ma sono presentate in modo condizionale in base al pulsante selezionato nella navigazione.

il collage è piuttosto caotico a causa dell&#39;enorme diversità di stili che il web ha applicato al concetto del componente
. Un collage di stili di web design con componenti di schede degli ultimi 10 anni

Tattiche sul web

Nel complesso ho trovato questo componente piuttosto semplice da creare, grazie a un alcune funzionalità fondamentali della piattaforma web:

  • scroll-snap-points per interazioni eleganti con scorrimento e tastiera posizioni di interruzione di scorrimento appropriate
  • Link diretti tramite hash degli URL per browser gestito per l'ancoraggio e la condivisione allo scorrimento in-page
  • Supporto per screen reader con markup degli elementi <a> e id="#hash"
  • prefers-reduced-motion per abilitare le transizioni dissolvenza incrociata e le transizioni istantanee scorrimento in-page
  • La funzionalità web @scroll-timeline in bozza per sottolineare e sottolineare in modo dinamico colore che modifica la scheda selezionata

Il codice HTML

Essenzialmente, la UX qui è: fare clic su un link, fare in modo che l'URL rappresenti i lo stato della pagina, per poi vedere l'aggiornamento dell'area dei contenuti man mano che il browser scorre fino elemento corrispondente.

Lì contiene alcuni membri strutturali dei contenuti: link e :target. Me sono necessari un elenco di link, per cui <nav> è ideale, e un elenco di <article> elementi, per i quali un <section> è ideale. Ogni hash link corrisponderà a una sezione, consentendo al browser di scorrere i contenuti tramite l'ancoraggio.

Viene fatto clic su un pulsante del link che scorre tra i contenuti selezionati

Ad esempio, se fai clic su un link, l'articolo :target viene attivato automaticamente Chrome 89, non è richiesto JS. L'utente può quindi scorrere i contenuti dell'articolo con come sempre. Si tratta di contenuti complementari, come indicato markup dei dati.

Ho utilizzato il seguente markup per organizzare le schede:

<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>

Posso stabilire connessioni tra gli elementi <a> e <article> con Proprietà href e id come questa:

<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>

Poi ho riempito gli articoli con quantità miste di lorem e i link con un di titoli con lunghezza mista e immagini. Con i contenuti con cui lavorare, possiamo iniziare layout.

Layout a scorrimento

In questo componente esistono tre diversi tipi di aree di scorrimento:

  • La barra di navigazione (rosa) è in orizzontale scorrevole
  • L'area dei contenuti (blu) è orizzontale scorrevole
  • Ogni elemento dell'articolo (verde) è in verticale. scorrevole.
3 caselle colorate con frecce direzionali corrispondenti ai colori che delineano le aree di scorrimento e indicano la direzione in cui scorreranno.

Lo scorrimento prevede due diversi tipi di elementi:

  1. Una finestra
    Un riquadro con dimensioni definite che include overflow stile della proprietà.
  2. Una superficie sovradimensionata
    In questo layout sono i container degli elenchi: nav link, articoli di sezione e contenuti degli articoli.

Layout <snap-tabs>

Il layout di primo livello che ho scelto era flessibile (Flexbox). Ho impostato la direzione su column, quindi l'intestazione e la sezione sono in ordine verticale. Questo è il nostro primo finestra di scorrimento nasconde tutti gli elementi con overflow nascosto. L'intestazione e userà presto l'overscroll come zone singole.

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; } }

Tornando al colorato diagramma a tre scorrimenti:

  • <header> ora è pronta per essere (rosa) contenitore di scorrimento.
  • <section> è preparata per essere la pergamena (blu) containerizzato.

I frame che ho evidenziato di seguito con VisBug ci aiuta a vedere le finestre del i container di scorrimento.

gli elementi dell&#39;intestazione e della sezione presentano overlay di colore hotpin, che indicano lo spazio occupato nel componente.

Layout schede <header>

Il layout successivo è quasi lo stesso: uso Flex per creare un ordinamento verticale.

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

.snap-indicator deve spostarsi in orizzontale insieme al gruppo di link e questo layout di intestazione aiuta a impostare questo scenario. Nessun elemento con posizionamento assoluto qui.

gli elementi nav e span.indicator presentano overlay di caratteri hotpink che indicano lo spazio occupato nel componente.

Ora passiamo agli stili di scorrimento. A quanto pare, possiamo condividere gli stili di scorrimento tra le due aree di scorrimento orizzontali (intestazione e sezione), quindi ho creato un'utilità corso, .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;
    }
  }
}

Ciascuno ha bisogno di overflow sull'asse x, contenimento di scorrimento per intrappolare overscroll, nascosto barre di scorrimento per dispositivi touch e infine scorri-snap per bloccare i contenuti aree di presentazione. L'ordine delle schede della tastiera è accessibile e qualsiasi guida alle interazioni concentrarsi in modo naturale. I container di tipo "Scorrimento rapido" hanno anche un piacevole stile carosello all'interazione dalla tastiera.

Layout intestazione schede <nav>

I link di navigazione devono essere disposti su una linea, senza interruzioni di riga, in verticale. al centro e ogni elemento link deve essere agganciato al contenitore scroll-snap. Swift possono lavorare per i 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;
  }
}

Ogni link ha le sue dimensioni e la sua stessa dimensione, quindi il layout di navigazione deve solo specificare direzione e flusso. Le larghezze uniche degli elementi di navigazione rendono la transizione tra le schede perché l'indicatore adatta la larghezza al nuovo target. In base al numero si trovano qui, il browser visualizzerà o meno una barra di scorrimento.

Gli elementi a della navigazione hanno overlay di colore hotpink, che delimitano lo spazio occupato nel componente e i punti in cui si riempiono

Layout schede <section>

Questa sezione è un articolo flessibile e deve essere il consumatore dominante di spazio. it deve creare delle colonne in cui inserire gli articoli. Di nuovo, Rapidità possono lavorare per CSS 2021. block-size: 100% estende questo elemento per riempire il principale il più possibile, quindi, per il proprio layout, crea una serie colonne che hanno la larghezza 100% rispetto a quella principale. In questo caso le percentuali vanno bene. perché abbiamo definito vincoli rigidi all'elemento principale.

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%;
}

È come se dicessimo "espandi il più possibile verticalmente, in modo invadente" (ricorda l'intestazione che abbiamo impostato su flex-shrink: 0: è una difesa contro push di espansione), che imposta l'altezza della riga per un insieme di colonne a altezza intera. La Lo stile auto-flow indica alla griglia di disporre sempre i bambini in orizzontale riga, senza wrapping, esattamente ciò che vogliamo: per fare l'overflow della finestra principale.

Gli elementi dell&#39;articolo hanno overlay di colore rosa acceso, che indicano lo spazio occupato nel componente e i punti in cui finiscono

A volte faccio fatica ad arrossire la testa. Questo elemento della sezione è in una scatola, ma anche un insieme di scatole. Spero che le immagini e le spiegazioni sono d'aiuto.

Layout schede <article>

L'utente deve essere in grado di scorrere i contenuti dell'articolo e le barre di scorrimento devono vengono visualizzate solo in caso di overflow. Questi elementi dell'articolo sono in una posizione posizione. Sono contemporaneamente un publisher principale e uno secondario. La il browser gestisce alcune interazioni complesse con il tocco e con il mouse e la tastiera per noi.

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;
}

Ho scelto di fare in modo che gli articoli vengano agganciati nello scorrimento principale. Mi piace molto il modo in cui gli elementi dei link di navigazione e gli elementi dell'articolo si agganciano al dei rispettivi container di scorrimento. Ha l'aspetto e la sensazione di una relazione tra utenti.

l&#39;elemento dell&#39;articolo e i relativi elementi secondari hanno overlay di colore hotpink, che indicano lo spazio occupato nel componente e la direzione in cui si riempiono

L'articolo è un elemento secondario della griglia e le sue dimensioni sono predeterminate come area visibile in cui vogliamo fornire UX con scorrimento. Ciò significa che non mi servono altezza o larghezza stili, devo solo definire l'overflow. Ho impostato overflow-y su automatico e anche le interazioni di scorrimento con il pratico comportamento overscroll proprietà.

Riepilogo delle 3 aree di scorrimento

Di seguito ho scelto l'opzione "Mostra sempre le barre di scorrimento" nelle impostazioni di sistema. Credo è doppiamente importante che il layout funzioni con questa impostazione attivata, in quanto riguarda la revisione del layout e dell'orchestrazione dello scorrimento.

le tre barre di scorrimento sono impostate per mostrare, occupando ora spazio di layout e il nostro componente ha ancora un aspetto ottimo

Penso che vedere la grondaia della barra di scorrimento in questo componente aiuti a mostrare chiaramente dove le aree di scorrimento, la direzione in cui supportano e il modo in cui interagiscono tra loro. Considera come ciascuno di questi frame delle finestre di scorrimento è flessibile o principali in un layout.

DevTools può aiutarci a comprendere quanto segue:

le aree di scorrimento hanno overlay degli strumenti griglia e flexbox, che indicano lo spazio occupato nel componente e la direzione in cui si riempiono
. Strumenti per sviluppatori di Chromium, che mostra il layout dell'elemento di navigazione flexbox pieno di elementi di ancoraggio, il layout della sezione della griglia pieno di elementi dell'articolo e l'articolo pieni di paragrafi e un elemento di intestazione.

I layout di scorrimento sono completi: aggancio, collegamento diretto e tastiera accessibili. Nozioni di base solide per miglioramenti, stile e gioia dell'esperienza utente.

Funzionalità in evidenza

I bambini agganciati di scorrimento mantengono la loro posizione bloccata durante il ridimensionamento. Ciò significa JavaScript non deve visualizzare nulla durante la rotazione del dispositivo o il browser. ridimensionare. Provalo in Dispositivo Chromium DevTools Modalità di selezionando una modalità diversa da Adattabile e ridimensionando il frame del dispositivo. Nota che l'elemento rimane visibile e bloccato con i suoi contenuti. Questo è stato disponibile da quando Chromium ha aggiornato la sua implementazione in modo che corrisponda alle specifiche. Ecco un post del blog a riguardo.

Animazione

L'obiettivo del lavoro dell'animazione è collegare in modo chiaro le interazioni con l'UI. feedback. Questo aiuta l'utente a indirizzare (si spera) o ad assistere l'utente nel suo percorso una facile scoperta di tutti i contenuti. Aggiungo il movimento con uno scopo in modo condizionale. Ora gli utenti possono specificare il proprio movimento preferenze del loro sistema operativo, e mi piace molto rispondere alle loro preferenze nelle mie interfacce.

Collegherò una sottolineatura della scheda alla posizione di scorrimento dell'articolo. L'aggancio non è solo un allineamento discreto, fissa anche l'inizio e la fine di un'animazione. In questo modo viene mantenuto <nav>, che funge da mini-mappa, collegata ai contenuti. Controlleremo la preferenza di movimento dell'utente sia da CSS che da JS. C'è un alcuni ottimi posti in cui essere rispettosi!

Comportamento di scorrimento

È possibile migliorare il comportamento di movimento di :target e element.scrollIntoView(). Per impostazione predefinita, è istantaneo. Il browser imposta semplicemente posizione di scorrimento. E se volessimo passare a quella posizione di scorrimento, invece di battere le ciglia?

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

Poiché qui stiamo introducendo il movimento, e quello che l'utente non controlla (come lo scorrimento), applichiamo questo stile solo se l'utente non ha preferenze in la riduzione del movimento del proprio sistema operativo. In questo modo, introduciamo solo lo scorrimento per le persone che sono d'accordo.

Indicatore schede

Lo scopo di questa animazione è aiutare ad associare l'indicatore allo stato. dei contenuti. Ho deciso di applicare una dissolvenza incrociata colore a border-bottom stili per gli utenti che preferiscono un movimento ridotto e un'animazione di scorrimento collegato tramite scorrimento + dissolvenza colore per gli utenti che sono d'accordo con il movimento.

In Chromium Devtools, posso attivare/disattivare la preferenza e dimostrare il 2 stili di transizione diversi. Mi sono divertita un sacco a realizzarla.

@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;
  }
}

Nascondo .snap-indicator quando l'utente preferisce la riduzione del movimento perché ne hanno più bisogno. Poi lo sostituisco con border-block-end stili e una transition. Nota anche nell'interazione delle schede che l'elemento di navigazione attivo non ha solo un'evidenziazione di sottolineatura del brand, ma anche il colore del testo è più scuro. La elemento attivo ha un contrasto di colore del testo più elevato e un accento luminoso in condizioni di scarsa illuminazione.

Solo poche righe di CSS in più fanno sentire le persone viste (nel senso che rispettiamo scrupolosamente le loro preferenze di movimento). Mi piace un sacco.

@scroll-timeline

Nella sezione precedente ho mostrato come gestisco la dissolvenza incrociata a movimento ridotto stili. In questa sezione ti mostrerò come ho collegato l'indicatore e l'area di scorrimento. Adesso ci sono delle divertenti attività sperimentali. Spero tu stia entusiasta quanto me.

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

Innanzitutto controllo la preferenza di movimento dell'utente da JavaScript. Se il risultato si tratta di false, il che significa che l'utente preferisce la riduzione del movimento, quindi non eseguiremo dello scorrimento che collega gli effetti di movimento.

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

Al momento della stesura di questo documento, il supporto del browser per @scroll-timeline non è nessuno. È una specifiche di bozza con solo implementazioni sperimentali. Ha però un polyfill, che uso in questo demo.

ScrollTimeline

Anche se CSS e JavaScript possono creare linee temporali di scorrimento, ho attivato JavaScript in modo da poter utilizzare le misurazioni degli elementi dal vivo nell'animazione.

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

Voglio che un elemento segua la posizione di scorrimento di un'altra e creando un'immagine ScrollTimeline Definisco il driver del link di scorrimento, scrollSource. Normalmente un'animazione sul web viene eseguita in base a un intervallo di tempo globale, ma con un sectionScrollTimeline personalizzato in memoria, posso cambiare tutto.

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

Prima di passare ai fotogrammi chiave dell'animazione, penso che sia importante indica che il follower dello scorrimento, tabindicator, sarà animata in base su una sequenza temporale personalizzata, lo scorrimento della nostra sezione. Questa operazione completa il collegamento, ma in cui manca l'ingrediente finale, i punti stateful tra cui animarsi, noti anche come fotogrammi chiave.

Fotogrammi dinamici

Esiste un modo CSS dichiarativo puro molto efficace per eseguire l'animazione @scroll-timeline, ma l'animazione che ho scelto era troppo dinamica. Non sono presenti per la transizione tra una larghezza auto e l'altra e non c'è modo di creare dinamicamente una serie di fotogrammi chiave in base alla lunghezza dell'elemento secondario.

JavaScript sa come ottenere queste informazioni, quindi ripetiamo i bambini e recuperare i valori calcolati in fase di runtime:

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

Per ogni tabnavitem, destruttura la posizione offsetLeft e restituisci una stringa che lo utilizza come valore translateX. Vengono creati quattro fotogrammi chiave di trasformazione l'animazione. Lo stesso viene fatto per la larghezza, a ciascuna viene chiesto qual è la sua larghezza dinamica e poi viene utilizzato come valore per i fotogrammi chiave.

Ecco un output di esempio, basato sui miei caratteri e sulle preferenze del browser:

Fotogrammi chiave TraduttoreX:

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

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

Larghezza dei fotogrammi chiave:

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

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

Per riepilogare la strategia, l'indicatore di scheda si anima in quattro fotogrammi chiave. a seconda della posizione di aggancio dello scorrimento della sezione. I punti di agganciamento creano una chiara delineazione tra i fotogrammi chiave e si aggiungono ai un'atmosfera sincronizzata dell'animazione.

Le schede attive e non attive sono mostrate con overlay VisBug che mostrano i punteggi di contrasto di entrambi

L'utente avvia l'animazione durante l'interazione, vedendo la larghezza e dell'indicatore cambia da una sezione all'altra, il monitoraggio perfettamente con lo scorrimento.

Forse non l'hai notato, ma sono molto orgoglioso del passaggio di colore come l'elemento di navigazione evidenziato viene selezionato.

Il grigio chiaro non selezionato appare ancora più spostato all'indietro quando dell'elemento ha un contrasto maggiore. È comune colore di transizione del testo, come al passaggio del mouse e quando viene selezionato, sincronizzati con l'indicatore di sottolineatura.

Ecco come ci sono riuscito:

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

Ogni link di navigazione della scheda richiede questa nuova animazione colore, tenendo traccia dello stesso scorrimento la sequenza temporale come indicatore di sottolineatura. Utilizzo la stessa sequenza temporale di prima: dato che il suo ruolo è emettere un segno di spunta quando lo rotolo, possiamo utilizzarlo in qualsiasi tipo l'animazione desiderata. Come ho fatto prima, creo 4 fotogrammi chiave in loop e torno colori.

[...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)",
]

Il fotogramma chiave con il colore var(--text-active-color) evidenzia il link. altrimenti un colore di testo standard. Il loop nidificato lo rende relativamente diretta, poiché il loop esterno è ogni elemento di navigazione e il loop interno è fotogrammi chiave personali di navitem. Verifico se l'elemento loop esterno è uguale a il loop interno e usalo per sapere quando è selezionato.

Mi sono divertita un sacco a scriverlo. Tantissimo.

Ancora altri miglioramenti a JavaScript

È bene ricordare che l'essenza di ciò che vi mostro qui funziona senza JavaScript. Detto questo, vediamo come possiamo migliorarlo quando JS disponibili.

I link diretti sono più che altro un termine per dispositivi mobili, ma penso che lo scopo del link diretto sia con schede che consentono di condividere un URL direttamente con i contenuti di una scheda. La il browser in-page raggiungerà l'ID corrispondente nell'hash dell'URL. ho trovato questo gestore onload ha avuto effetto su tutte le piattaforme.

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

Scorrimento e fine sincronizzazione

I nostri utenti non sempre fanno clic o utilizzano una tastiera, a volte semplicemente senza dover scorrere i contenuti. Quando lo scorrimento delle sezioni si arresta scorrere la pagina, ogni volta che arriva deve essere abbinata alla barra di navigazione in alto.

Ecco come attendo la fine dello scorrimento: js tabsection.addEventListener('scroll', () => { clearTimeout(tabsection.scrollEndTimer); tabsection.scrollEndTimer = setTimeout(determineActiveTabSection, 100); });

Ogni volta che le sezioni vengono fatte scorrere, cancella il timeout della sezione, se presente. e iniziarne uno nuovo. Quando le sezioni smettono di scorrere, non cancellare il timeout, e si attivano 100 ms dopo il riposo. Quando si attiva, richiama una funzione che cerca di figurare dal punto in cui l'utente si è fermato.

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

  matchingNavItem && setActiveTab(matchingNavItem);
};

Presumendo che la scorrimento sia agganciata, dividendo la posizione di scorrimento corrente dalla larghezza dell'area di scorrimento deve restituire un numero intero e non decimale. Quindi cerco di recuperare un navitem dalla cache tramite l'indice calcolato e, se trova invio la corrispondenza in modo che sia attiva.

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

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

L'impostazione della scheda attiva inizia cancellando tutte le schede attualmente attive, quindi assegnando l'attributo di navigazione in arrivo e l'attributo stato attivo. Chiamata a scrollIntoView() ha una divertente interazione con il CSS che vale la pena notare.

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

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

Nel CSS dell'utilità di scorrimento orizzontale, abbiamo nidificare una query supporti che applica smooth se l'utente è tollerante al movimento. JavaScript può creare liberamente per visualizzare gli elementi e il CSS può gestire la UX in modo dichiarativo. Un bel fiammifero che a volte fanno.

Conclusione

Ora che sai come ci ho fatto, come lo faresti?! È un po' divertente dei componenti. Chi creerà la prima versione con slot nel proprio il tuo framework preferito? 🙂

Diversificaamo i nostri approcci e impariamo tutti i modi per creare sul web. Crea un Glitch e twittami. la tua versione e la aggiungerò ai remix della community di seguito.

Remix della community