Ein super flexibler CSS-Karussell, erweitert mit JavaScript Navigation

Avatar of Maks Akymenko
Maks Akymenko am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Ich weiß nicht, wie es Ihnen geht, aber ich frage mich oft, wie man eine Karussell-Komponente so aufbaut, dass man einfach eine Menge Elemente in die Komponente werfen kann und ein schönes, funktionierendes Karussell erhält – eines, das sanftes Scrollen, Navigation mit dynamischen Schaltflächen und Responsivität ermöglicht. Wenn das etwas ist, das Sie bauen möchten, folgen Sie mir, und wir werden es gemeinsam angehen!

Darauf arbeiten wir hin

Wir werden von nun an mit einer ganzen Menge JavaScript, React und der DOM-API arbeiten.

Zuerst, lass uns ein frisches Projekt aufsetzen

Lassen Sie uns damit beginnen, eine einfache React-Anwendung zu erstellen, bei der styled-components für das Styling hinzugefügt wird.

npx create-react-app react-easy-carousel

cd react-easy-carousel
yarn add styled-components
yarn install

yarn start

Das Styling ist eigentlich nicht der Kern dessen, was wir tun. Daher habe ich eine Reihe von vordefinierten Komponenten für uns vorbereitet, die wir sofort verwenden können.

// App.styled.js
import styled from 'styled-components'

export const H1 = styled('h1')`
  text-align: center;
  margin: 0;
  padding-bottom: 10rem;
`
export const Relative = styled('div')`
  position: relative;
`
export const Flex = styled('div')`
  display: flex;
`
export const HorizontalCenter = styled(Flex)`
  justify-content: center;
  margin-left: auto;
  margin-right: auto;
  max-width: 25rem;
`
export const Container = styled('div')`
  height: 100vh;
  width: 100%;
  background: #ecf0f1;
`
export const Item = styled('div')`
  color: white;
  font-size: 2rem;
  text-transform: capitalize;
  width: ${({size}) => `${size}rem`};
  height: ${({size}) => `${size}rem`};
  display: flex;
  align-items: center;
  justify-content: center;
`

Gehen wir nun zu unserer App-Datei, entfernen wir allen unnötigen Code und bauen wir eine grundlegende Struktur für unser Karussell auf.

// App.js
import {Carousel} from './Carousel'

function App() {
  return (
    <Container>
      <H1>Easy Carousel</H1>
      <HorizontalCenter>
        <Carousel>
        {/* Put your items here */}
        </Carousel>
      </HorizontalCenter>
    </Container>
  )
}
export default App

Ich glaube, diese Struktur ist ziemlich geradlinig. Es ist das grundlegende Layout, das das Karussell direkt in der Mitte der Seite zentriert.

Sprechen wir über die Struktur unserer Komponente. Wir benötigen den Haupt-<div>-Container als Basis. Darin werden wir das native Scrollen nutzen und einen weiteren Block einfügen, der als scrollbarer Bereich dient.

// Carousel.js 
<CarouserContainer>
  <CarouserContainerInner>
    {children}
  </CarouserContainerInner>
</CarouserContainer>

Sie können Breite und Höhe für den inneren Container festlegen, aber ich würde von strikten Abmessungen absehen und stattdessen eine größenbasierte Komponente darüber verwenden, um die Flexibilität zu wahren.

Scrollen, der CSS-Weg

Wir möchten, dass das Scrollen sanft ist, damit ein klarer Übergang zwischen den Folien erkennbar ist. Daher werden wir CSS Scroll Snapping verwenden, das Scrollen horizontal entlang der x-Achse einstellen und gleichzeitig die tatsächliche Scrollleiste ausblenden.

export const CarouserContainerInner = styled(Flex)`
  overflow-x: scroll;
  scroll-snap-type: x mandatory;
  -ms-overflow-style: none;
  scrollbar-width: none;

  &::-webkit-scrollbar {
    display: none;
  }

  & > * {
    scroll-snap-align: center;
  }
`

Fragen Sie sich, was es mit scroll-snap-type und scroll-snap-align auf sich hat? Das ist natives CSS, das es uns ermöglicht, das Scrollverhalten so zu steuern, dass ein Element während eines Scrollvorgangs an einer Stelle "rastet". In diesem Fall haben wir den Snap-Typ in horizontaler (x) Richtung eingestellt und dem Browser gesagt, dass er an einer Snap-Position stoppen muss, die sich in der Mitte des Elements befindet.

Mit anderen Worten: **Scrollen Sie zur nächsten Folie und stellen Sie sicher, dass diese Folie zentriert im Ansichtsbereich ist.** Lassen Sie uns das etwas aufschlüsseln, um zu sehen, wie es in das Gesamtbild passt.

Unser äußerer <div> ist ein flexibler Container, der seine Kinder (die Karussell-Folien) in einer horizontalen Reihe anordnet. Diese Kinder werden die Breite des Containers leicht überschreiten, daher haben wir es so eingerichtet, dass wir horizontal innerhalb des Containers scrollen können. Hier kommt scroll-snap-type ins Spiel. Von Andy Adams im CSS-Tricks Almanac

Scroll Snapping bezieht sich auf das "Sperren" der Position des Ansichtsbereichs auf bestimmte Elemente auf der Seite, während das Fenster (oder ein scrollbarer Container) gescrollt wird. Stellen Sie es sich wie einen Magneten auf einem Element vor, der am oberen Rand des Ansichtsbereichs haftet und die Seite zwingt, genau dort zu stoppen.

Besser könnte ich es nicht ausdrücken. Spielen Sie damit in Andys Demo auf CodePen.

Wir benötigen jedoch noch eine weitere CSS-Eigenschaft für die Kinder des Containers (wieder die Karussell-Folien), die dem Browser mitteilt, wo das Scrollen stoppen soll. Andy vergleicht dies mit einem Magneten, also legen wir diesen Magneten direkt in die Mitte unserer Folien. So "rastet" das Scrollen in der Mitte einer Folie ein, wodurch diese im Karussell-Container vollständig sichtbar ist.

Diese Eigenschaft? scroll-snap-align.

& > * {
  scroll-snap-align: center;
}

Wir können es bereits testen, indem wir ein zufälliges Array von Elementen erstellen.

const colors = [
  '#f1c40f',
  '#f39c12',
  '#e74c3c',
  '#16a085',
  '#2980b9',
  '#8e44ad',
  '#2c3e50',
  '#95a5a6',
]
const colorsArray = colors.map((color) => (
  <Item
    size={20}
    style={{background: color, borderRadius: '20px', opacity: 0.9}}
    key={color}
  >
    {color}
  </Item>
))

Und es direkt in unser Karussell einfügen.

// App.js
<Container>
  <H1>Easy Carousel</H1>
  <HorizontalCenter>
    <Carousel>{colorsArray}</Carousel>
  </HorizontalCenter>
</Container>

Fügen wir unseren Elementen auch etwas Abstand hinzu, damit sie nicht zu gequetscht aussehen. Möglicherweise bemerken Sie auch, dass wir am linken Rand des ersten Elements einen unnötigen Abstand haben. Wir können einen negativen Rand hinzufügen, um dies auszugleichen.

export const CarouserContainerInner = styled(Flex)`
  overflow-x: scroll;
  scroll-snap-type: x mandatory;
  -ms-overflow-style: none;
  scrollbar-width: none;
  margin-left: -1rem;

  &::-webkit-scrollbar {
    display: none;
  }

  & > * {
    scroll-snap-align: center;
    margin-left: 1rem;
  }
`

Werfen Sie einen genaueren Blick auf die Cursorposition beim Scrollen. Sie ist immer zentriert. Das ist die Eigenschaft scroll-snap-align in Aktion!

Und das war's! Wir haben ein großartiges Karussell erstellt, dem wir beliebig viele Elemente hinzufügen können und das einfach funktioniert. Beachten Sie auch, dass wir all dies in reinem CSS gemacht haben, auch wenn es als React-App erstellt wurde. Wir brauchten weder React noch styled-components, um dies zum Laufen zu bringen.

Bonus: Navigation

Wir könnten den Artikel hier beenden und weitermachen, aber ich möchte noch einen Schritt weiter gehen. Was mir an dem bisherigen Ergebnis gefällt, ist, dass es flexibel ist und die grundlegende Aufgabe des Scrollens durch eine Reihe von Elementen erfüllt.

Aber Sie haben vielleicht eine wichtige Verbesserung in der Demo am Anfang dieses Artikels bemerkt: Schaltflächen, die durch die Folien navigieren. Hier werden wir das CSS beiseitelegen und unsere JavaScript-Hüte aufsetzen, um dies zu realisieren.

Zuerst definieren wir Schaltflächen links und rechts vom Karussell-Container, die beim Klicken zur vorherigen bzw. nächsten Folie scrollen. Ich verwende einfache SVG-Pfeile als Komponenten.

// ArrowLeft
export const ArrowLeft = ({size = 30, color = '#000000'}) => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    width={size}
    height={size}
    viewBox="0 0 24 24"
    fill="none"
    stroke={color}
    strokeWidth="2"
    strokeLinecap="round"
    strokeLinejoin="round"
  >
    <path d="M19 12H6M12 5l-7 7 7 7" />
  </svg>
)

// ArrowRight
export const ArrowRight = ({size = 30, color = '#000000'}) => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    width={size}
    height={size}
    viewBox="0 0 24 24"
    fill="none"
    stroke={color}
    strokeWidth="2"
    strokeLinecap="round"
    strokeLinejoin="round"
  >
    <path d="M5 12h13M12 5l7 7-7 7" />
  </svg>
)

Nun positionieren wir sie auf beiden Seiten unseres Karussells.

// Carousel.js
<LeftCarouselButton>
  <ArrowLeft />
</LeftCarouselButton>

<RightCarouselButton>
  <ArrowRight />
</RightCarouselButton>

Wir fügen etwas Styling hinzu, das den Pfeilen absolute Positionierung verleiht, sodass der linke Pfeil am linken Rand des Karussells und der rechte Pfeil am rechten Rand positioniert ist. Einige andere Dinge werden hinzugefügt, um die Schaltflächen selbst wie Schaltflächen aussehen zu lassen. Außerdem spielen wir mit dem :hover-Zustand des Karussell-Containers, sodass die Schaltflächen nur angezeigt werden, wenn der Cursor des Benutzers über den Container fährt.

// Carousel.styled.js

// Position and style the buttons
export const CarouselButton = styled('button')`
  position: absolute;
  cursor: pointer;
  top: 50%;
  z-index: 1;
  transition: transform 0.1s ease-in-out;
  background: white;
  border-radius: 15px;
  border: none;
  padding: 0.5rem;
`

// Display buttons on hover
export const LeftCarouselButton = styled(CarouselButton)`
  left: 0;
  transform: translate(-100%, -50%);

  ${CarouserContainer}:hover & {
    transform: translate(0%, -50%);
  }
`
// Position the buttons to their respective sides
export const RightCarouselButton = styled(CarouselButton)`
  right: 0;
  transform: translate(100%, -50%);

  ${CarouserContainer}:hover & {
    transform: translate(0%, -50%);
  }
`

Das ist cool. Jetzt haben wir Schaltflächen, aber nur, wenn der Benutzer mit dem Karussell interagiert.

Aber wollen wir *immer* *beide* Schaltflächen sehen? Es wäre großartig, wenn wir den linken Pfeil ausblenden, wenn wir uns auf der ersten Folie befinden, und den rechten Pfeil ausblenden, wenn wir uns auf der letzten Folie befinden. Es ist, als ob der Benutzer nicht über diese Folien hinaus navigieren kann, warum also die Illusion erwecken, dass er es kann?

Ich schlage vor, einen Hook zu erstellen, der für alle benötigten Scroll-Funktionen zuständig ist, da wir eine ganze Menge davon haben werden. Außerdem ist es einfach gute Praxis, funktionale Belange von unserer visuellen Komponente zu trennen.

Zuerst müssen wir die Referenz zu unserer Komponente abrufen, um die Position der Folien ermitteln zu können. Das machen wir mit ref.

// Carousel.js
const ref = useRef()
const position = usePosition(ref)

<CarouserContainer>
  <CarouserContainerInner ref={ref}>
    {children}
  </CarouserContainerInner>
  <LeftCarouselButton>
    <ArrowLeft />
  </LeftCarouselButton>
  <RightCarouselButton>
    <ArrowRight />
  </RightCarouselButton>
</CarouserContainer>

Die ref-Eigenschaft befindet sich auf <CarouserContainerInner>, da sie alle unsere Elemente enthält und uns die Durchführung korrekter Berechnungen ermöglicht.

Nun implementieren wir den Hook selbst. Wir haben zwei Schaltflächen. Damit sie funktionieren, müssen wir die nächsten und vorherigen Elemente entsprechend verfolgen. Der beste Weg, dies zu tun, ist, einen Zustand für jedes zu haben.

// usePosition.js
export function usePosition(ref) {
  const [prevElement, setPrevElement] = useState(null)
  const [nextElement, setNextElement] = useState(null)
}

Der nächste Schritt ist die Erstellung einer Funktion, die die Position der Elemente erkennt und die Schaltflächen entsprechend ausblendet oder anzeigt.

Wir nennen sie die update-Funktion. Wir werden sie in den useEffect-Hook von React einfügen, da wir diese Funktion zunächst ausführen wollen, wenn das DOM zum ersten Mal gemountet wird. Wir benötigen Zugriff auf unseren scrollbaren Container, der unter der ref.current-Eigenschaft verfügbar ist. Wir werden ihn in eine separate Variable namens element stellen und zunächst die Position des Elements im DOM ermitteln.

Wir werden hier auch getBoundingClientRect() verwenden. Dies ist eine sehr hilfreiche Funktion, da sie uns die Position eines Elements im Ansichtsbereich (d. h. Fenster) liefert und uns erlaubt, mit unseren Berechnungen fortzufahren.

// usePosition.js
 useEffect(() => {
  // Our scrollable container
  const element = ref.current

  const update = () => {
    const rect = element.getBoundingClientRect()
}, [ref])

Wir haben bisher eine Menge Positionierung vorgenommen, und getBoundingClientRect() kann uns helfen, sowohl die Größe des Elements – rect in diesem Fall – als auch seine Position relativ zum Ansichtsbereich zu verstehen.

Quelle: Mozilla Developer Network

Der nächste Schritt ist etwas knifflig, da er etwas Mathematik erfordert, um zu berechnen, welche Elemente im Container sichtbar sind.

Zuerst müssen wir jedes Element filtern, indem wir seine Position im Ansichtsbereich ermitteln und sie gegen die Containergrenzen prüfen. Dann prüfen wir, ob die linke Grenze des Kindes größer ist als die linke Grenze des Containers, und das Gleiche auf der rechten Seite.

Wenn eine dieser Bedingungen erfüllt ist, bedeutet dies, dass unser Kind im Container sichtbar ist. Wandeln wir das Schritt für Schritt in Code um.

  1. Wir müssen alle Kinder des Containers durchlaufen und filtern. Wir können die children-Eigenschaft verwenden, die auf jedem Knoten verfügbar ist. Wandeln wir sie also in ein Array um und filtern wir.
const visibleElements = Array.from(element.children).filter((child) => {}
  1. Danach müssen wir die Position jedes Elements ermitteln, indem wir erneut die praktische Funktion getBoundingClientRect() verwenden.
const childRect = child.getBoundingClientRect()
  1. Jetzt lassen wir unsere Zeichnung lebendig werden.
rect.left <= childRect.left && rect.right >= childRect.right

Zusammenfassend lässt sich sagen, dass dies unser Skript ist.

// usePosition.js
const visibleElements = Array.from(element.children).filter((child) => {
  const childRect = child.getBoundingClientRect()

  return rect.left <= childRect.left && rect.right >= childRect.right
})

Nachdem wir die Elemente herausgefiltert haben, müssen wir prüfen, ob ein Element das erste oder das letzte ist, damit wir wissen, ob wir den linken oder rechten Pfeil entsprechend ausblenden müssen. Wir erstellen zwei Hilfsfunktionen, die diese Bedingung mithilfe von previousElementSibling und nextElementSibling überprüfen. Auf diese Weise können wir sehen, ob ein Geschwisterkind in der Liste vorhanden ist und ob es sich um eine HTML-Instanz handelt. Wenn ja, geben wir es zurück.

Um das erste Element zu erhalten und zurückzugeben, müssen wir das erste Element aus unserer Liste der sichtbaren Elemente nehmen und prüfen, ob es den vorherigen Knoten enthält. Wir machen dasselbe für das letzte Element in der Liste, müssen jedoch das letzte Element in der Liste nehmen und prüfen, ob es das nächste Element danach enthält.

// usePosition.js
function getPrevElement(list) {
  const sibling = list[0].previousElementSibling

  if (sibling instanceof HTMLElement) {
    return sibling
  }

  return sibling
}

function getNextElement(list) {
  const sibling = list[list.length - 1].nextElementSibling
  if (sibling instanceof HTMLElement) {
    return sibling
  }
  return null
}

Sobald wir diese Funktionen haben, können wir schließlich prüfen, ob sichtbare Elemente in der Liste vorhanden sind, und dann unsere linken und rechten Schaltflächen in den Zustand versetzen.

// usePosition.js 
if (visibleElements.length > 0) {
  setPrevElement(getPrevElement(visibleElements))
  setNextElement(getNextElement(visibleElements))
}

Nun müssen wir unsere Funktion aufrufen. Darüber hinaus wollen wir diese Funktion jedes Mal aufrufen, wenn wir durch die Liste scrollen – das ist, wenn wir die Position des Elements erkennen wollen.

// usePosition.js
export function usePosition(ref) {
  const [prevElement, setPrevElement] = useState(null)
  const [nextElement, setNextElement] = useState(null)
  useEffect(() => {
    const element = ref.current
    const update = () => {
      const rect = element.getBoundingClientRect()
      const visibleElements = Array.from(element.children).filter((child) => {
        const childRect = child.getBoundingClientRect()
        return rect.left <= childRect.left && rect.right >= childRect.right
      })
      if (visibleElements.length > 0) {
        setPrevElement(getPrevElement(visibleElements))
        setNextElement(getNextElement(visibleElements))
      }
    }

    update()
    element.addEventListener('scroll', update, {passive: true})
    return () => {
      element.removeEventListener('scroll', update, {passive: true})
    }
  }, [ref])

Hier ist eine Erklärung, warum wir {passive: true} übergeben.

Nun geben wir diese Eigenschaften aus dem Hook zurück und aktualisieren unsere Schaltflächen entsprechend.

// usePosition.js
return {
  hasItemsOnLeft: prevElement !== null,
  hasItemsOnRight: nextElement !== null,
}
// Carousel.js 
<LeftCarouselButton hasItemsOnLeft={hasItemsOnLeft}>
  <ArrowLeft />
</LeftCarouselButton>

<RightCarouselButton hasItemsOnRight={hasItemsOnRight}>
  <ArrowRight />
</RightCarouselButton>
// Carousel.styled.js
export const LeftCarouselButton = styled(CarouselButton)`
  left: 0;
  transform: translate(-100%, -50%);
  ${CarouserContainer}:hover & {
    transform: translate(0%, -50%);
  }
  visibility: ${({hasItemsOnLeft}) => (hasItemsOnLeft ? `all` : `hidden`)};
`
export const RightCarouselButton = styled(CarouselButton)`
  right: 0;
  transform: translate(100%, -50%);
  ${CarouserContainer}:hover & {
    transform: translate(0%, -50%);
  }
  visibility: ${({hasItemsOnRight}) => (hasItemsOnRight ? `all` : `hidden`)};
`

Bisher alles gut. Wie Sie sehen werden, erscheinen unsere Pfeile dynamisch, abhängig von unserer Scroll-Position in der Liste der Elemente.

Wir haben nur noch einen letzten Schritt, um die Schaltflächen funktionsfähig zu machen. Wir müssen eine Funktion erstellen, die das nächste oder vorherige Element, zu dem gescrollt werden soll, akzeptiert.

const scrollRight = useCallback(() => scrollToElement(nextElement), [
  scrollToElement,
  nextElement,
])
const scrollLeft = useCallback(() => scrollToElement(prevElement), [
  scrollToElement,
  prevElement,
])

Vergessen Sie nicht, Funktionen in den useCallback-Hook zu wickeln, um unnötige Neu-Renderings zu vermeiden.

Als nächstes implementieren wir die Funktion scrollToElement. Die Idee ist ziemlich einfach. Wir müssen die linke Grenze unseres vorherigen oder nächsten Elements (abhängig von der angeklickten Schaltfläche) nehmen, diese mit der Breite des Elements addieren, durch zwei teilen (Mittelposition) und diesen Wert um die Hälfte der Containerbreite versetzen. Das gibt uns die *exakte* scrollbare Distanz zur Mitte des nächsten/vorherigen Elements.

Hier ist das in Code.

// usePosition.js  
const scrollToElement = useCallback(
  (element) => {
    const currentNode = ref.current

    if (!currentNode || !element) return

    let newScrollPosition

    newScrollPosition =
      element.offsetLeft +
      element.getBoundingClientRect().width / 2 -
      currentNode.getBoundingClientRect().width / 2

    currentNode.scroll({
      left: newScrollPosition,
      behavior: 'smooth',
    })
  },
  [ref],
)

scroll erledigt das Scrollen für uns, während wir die genaue Distanz übergeben, zu der gescrollt werden muss. Nun hängen wir diese Funktionen an unsere Schaltflächen an.

// Carousel.js  
const {
  hasItemsOnLeft,
  hasItemsOnRight,
  scrollRight,
  scrollLeft,
} = usePosition(ref)

<LeftCarouselButton hasItemsOnLeft={hasItemsOnLeft} onClick={scrollLeft}>
  <ArrowLeft />
</LeftCarouselButton>

<RightCarouselButton hasItemsOnRight={hasItemsOnRight} onClick={scrollRight}>
  <ArrowRight />
</RightCarouselButton>

Ziemlich gut!

Als guter Staatsbürger sollten wir unseren Code etwas aufräumen. Zum einen können wir die übergebenen Elemente besser kontrollieren, indem wir einen kleinen Trick anwenden, der automatisch die benötigten Stile für jedes Kind sendet. Die Children API ist ziemlich cool und einen Blick wert.

<CarouserContainerInner ref={ref}>
  {React.Children.map(children, (child, index) => (
    <CarouselItem key={index}>{child}</CarouselItem>
  ))}
</CarouserContainerInner>

Nun müssen wir nur noch unsere styled components aktualisieren. flex: 0 0 auto behält die ursprünglichen Größen der Container bei, ist also absolut optional.

export const CarouselItem = styled('div')`
  flex: 0 0 auto;

  // Spacing between items
  margin-left: 1rem;
`
export const CarouserContainerInner = styled(Flex)`
  overflow-x: scroll;
  scroll-snap-type: x mandatory;
  -ms-overflow-style: none;
  scrollbar-width: none;
  margin-left: -1rem; // Offset for children spacing

  &::-webkit-scrollbar {
    display: none;
  }

  ${CarouselItem} & {
    scroll-snap-align: center;
  }
`

Barrierefreiheit (Accessibility)

Wir kümmern uns um unsere Benutzer, daher müssen wir unsere Komponente nicht nur funktional, sondern auch zugänglich machen, damit sich die Leute wohl fühlen, sie zu benutzen. Hier sind ein paar Vorschläge, die ich machen würde.

  • Hinzufügen von role='region' um die Bedeutung dieses Bereichs hervorzuheben.
  • Hinzufügen eines area-label als Identifikator.
  • Hinzufügen von Beschriftungen zu unseren Schaltflächen, damit Screenreader sie leicht als „Vorherige“ und „Nächste“ identifizieren können und dem Benutzer mitteilen, in welche Richtung eine Schaltfläche führt.
// Carousel.js
<CarouserContainer role="region" aria-label="Colors carousel">

  <CarouserContainerInner ref={ref}>
    {React.Children.map(children, (child, index) => (
      <CarouselItem key={index}>{child}</CarouselItem>
    ))}
  </CarouserContainerInner>
  
  <LeftCarouselButton hasItemsOnLeft={hasItemsOnLeft}
    onClick={scrollLeft}
    aria-label="Previous slide
  >
    <ArrowLeft />
  </LeftCarouselButton>
  
  <RightCarouselButton hasItemsOnRight={hasItemsOnRight}
    onClick={scrollRight}
    aria-label="Next slide"
   >
    <ArrowRight />
  </RightCarouselButton>

</CarouserContainer>

Fühlen Sie sich frei, zusätzliche Karussells hinzuzufügen, um zu sehen, wie es mit Elementen unterschiedlicher Größe funktioniert. Lassen Sie uns zum Beispiel ein zweites Karussell einfügen, das nur aus einer Reihe von Zahlen besteht.

const numbersArray = Array.from(Array(10).keys()).map((number) => (
  <Item size={5} style={{color: 'black'}} key={number}>
    {number}
  </Item>
))

function App() {
  return (
    <Container>
      <H1>Easy Carousel</H1>
      <HorizontalCenter>
        <Carousel>{colorsArray}</Carousel>
      </HorizontalCenter>

      <HorizontalCenter>
        <Carousel>{numbersArray}</Carousel>
      </HorizontalCenter>
    </Container>
  )
}

Und voilà, Magie! Werfen Sie eine Menge Elemente hinein und Sie haben ein voll funktionsfähiges Karussell, das sofort einsatzbereit ist.


Fühlen Sie sich frei, dies zu modifizieren und in Ihren Projekten zu verwenden. Ich hoffe aufrichtig, dass dies ein guter Ausgangspunkt ist, den Sie so verwenden oder sogar noch weiter für ein komplexeres Karussell verbessern können. Fragen? Ideen? Kontaktieren Sie mich auf Twitter, GitHub oder in den Kommentaren unten!