react-marquee-slider
Demo and playground

Have a look through the various usecases and their code. At the end is a demo with adjustable settings.

Star
Take me to the project site

Note: The flickering ("jumping") of the items in the Marquee is not a bug. When you want to position items inside the slider randomly, the slider needs to actually render them, to see if the random positioning will fit inside the given area. If it doesn't (e.g. items are overlapping), it tries to find another place for the overlapping item. Depending on the number and size of items, and the size of the available space, overlapping items are more or less likely.

You can hide the flickering by overlaying the slider with a loading div, until it finishes. The slider provides an onFinish callback for this very reason. You can see an example with an overlaying loading div further down.

Reviews

The above Marquee is still rendering.

Here is the essential code for the above example, or you can have a more in depth look at the original, full code:

import React from "react";
import Marquee from "react-marquee-slider";
import times from "lodash/times";

const Reviews = () => (
  <Marquee key={key} velocity={25} scatterRandomly minScale={0.7}>
    {times(5, String).map(id => (
      <Box key={`marquee-example-review-${id}`} scale={scale}>
        <Review scale={scale}>
          <Avatar scale={scale}>
            <img src="https://randomuser.me/api/portraits/women/68.jpg" />
          </Avatar>
          <Content scale={scale}>
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
              incididunt ut labore et dolore magna aliqua.
            </p>
          </Content>
        </Review>
      </Box>
    ))}
  </Marquee>
);

Companies

The above Marquee is still rendering.

Here is the essential code for the above example, or you can have a more in depth look at the original, full code:

import React from "react";
import Marquee, { Motion } from "react-marquee-slider";
import times from "lodash/times";

const Reviews = () => (
  <FullWidth>
    <Height height={500}>
      <Marquee key={key} velocity={12} scatterRandomly minScale={0.7} resetAfterTries={200}>
        {_.times(8, Number).map(id => (
          <Motion
            key={`marquee-example-company-${id}`}
            initDeg={randomIntFromInterval(0, 360)}
            direction={Math.random() > 0.5 ? "clockwise" : "counterclockwise"}
            velocity={10}
            radius={scale * 100}
          >
            <Company scale={scale}>
              <Circle scale={scale}>
                <Logo src={icons[id]} />
              </Circle>
            </Company>
          </Motion>
        ))}
      </Marquee>
    </Height>
  </FullWidth>
);

People

The above Marquee shows instantly and doesn't require computation time, because the child elements are not positioned (scattered) randomly.

Here is the essential code for the above example, or you can have a more in depth look at the original, full code:

import React from "react";
import Marquee from "react-marquee-slider";
import styled from "styled-components";
import times from "lodash/times";

const Photo = styled.img`
  width: 368px;
  height: 200px;
  border-radius: 4px;
  box-shadow: 0 7px 20px 0 rgba(0, 0, 0, 0.12);
  object-fit: cover;
  object-position: top;
`;

const Reviews = () => (
  <div>
    <div style={{ height: 200 }}>
      <Marquee key={key} velocity={25}>
        {times(7, Number).map(id => (
          <Photo src={photos[id]} key={`marquee-example-people-${id}`} style={{ 
            marginLeft: "87px",
          }} />
        ))}
      </Marquee>
    </div>

    <div style={{ height: scale * 60 }} />
    
    <div style={{ height: 200 }}>
      <Marquee key={key} velocity={25}>
        {times(7, Number).map(id => (
          <Photo
            src={photos[id + 7]}
            key={`marquee-example-people-${id + 7}`}
            style={{ 
              marginLeft: "7px",
              marginRight: "80px",
            }}
          />
        ))}
      </Marquee>
    </div>
  </div>
);

Playground

8
How many icons to show. The less icons, the easier it is to find space for icons. The higher you put this, the higher you should set the container height, too. Wide screens also help.
8
500
The higher the more space, the easier the component will find space to position the children if `scatter randomly` is activated
500
200
200
15px / s
15
This is a shortcut to toggling velocity to 0 and back, without going through all the other values of the slider that come before 0.
15px / s
15
100px
The icons each are encapsuled in another `div`, which rotates (hence the circular motion). However, these motion containers are the actual children and larger than the icons (play around with `SolarSystem` color palette to make the visible). Therefore: Don't make the radius too large, because it will cloak up the available space and slow down computation.
100
min(0.7) max(1)
0.71

The above Marquee is still rendering.

Have a look at the original, full code for this example or just the basic, simplified gist:

import React, { useState } from "react";
import Marquee, { 
  Scale, 
  Motion,
  randomIntFromInterval, 
  randomFloatFromInterval 
} from "react-marquee-slider";
import styled from "styled-components";
import times from "lodash/times";

const icons = [
  "https://url.com/to/some/icon1.png",
  "https://url.com/to/some/icon2.png",
  // ... more of those paths
];

const Loading = styled.div`
  display: flex;
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  left: 0;
  width: 100%;
  height: 100%;
  transition: all 1s linear;
  background: #fff;
  justify-content: center;
  align-items: center;
`;

const Reviews = () => {
  const [loading, setLoading] = useState(true);

  const iconsMeta = [];
  for (let i = 0; i < icons.length; i++) {
    iconsMeta.push({
      initDeg: randomIntFromInterval(0, 360),
      direction: Math.random() > 0.5 ? "clockwise" : "counterclockwise",
      scale: randomFloatFromInterval(0.7, 1),
    });
  }
  
  return (
    <div style={{
      position: "relative",
      width: "100%",
      height: "500px";
      background: "transparent"
    }}>
      <Marquee
        direction={ltr}
        velocity={15}
        scatterRandomly={true}
        minScale={0.7}
        maxScale={1}
        resetAfterTries={200}
        onFinish={() => setLoading(false)}
      >
        {times(8, Number).map(index => (
          <Scale scale={iconsMeta[index].scale} key={`marquee-example-playground-${index}`}>
            <Motion
              {...iconsMeta[index]}
              velocity={15}
              radius={100}
              backgroundColors={{
                "container": "transparent",
                "buffer": "transparent",
                "earth": "transparent",
                "solarSystem": "transparent"
              }}
            >
              <Company>
                <Circle>
                  <Logo src={icons[index]} />
                </Circle>
              </Company>
            </Motion>
          </Scale>
        ))}
      </Marquee>
      <Loading style={{ opacity: 1; }}>
        <LoadingIcon />
      </Loading>
    </div>
  );
};