• LeBron James

  • Tim Duncan

  • Stephen Curry

  • Kareem Abdul-Jabbar

  • Kevin Durant

  • Giannis Antetokounmpo

  • Luka Dončić

  • Michael Jordan

🔁 Los Mejores Jugadores del Momento ¡en Loop! 🏀

Este es un interesante efecto de «looping words» utilizando GSAP (GreenSock Animation Platform) para un listado de jugadores de la NBA.
 
La animación simula un desplazamiento continuo de palabras (nombres de jugadores en este caso) hacia arriba, dando un efecto de presentación cíclica que podría usarse de forma atractiva en muchos proyectos

HTML+JS

				
					<section class="cloneable">
    <div class="looping-words">
      <div class="looping-words__containers">
        <ul data-looping-words-list="" class="looping-words__list">
<li class="nba-intro__item"><p class="nba-intro__name">LeBron James</p></li>
<li class="nba-intro__item"><p class="nba-intro__name">Stephen Curry</p></li>
<li class="nba-intro__item"><p class="nba-intro__name">Kevin Durant</p></li>
<li class="nba-intro__item"><p class="nba-intro__name">Giannis Antetokounmpo</p></li>
<li class="nba-intro__item"><p class="nba-intro__name">Luka Dončić</p></li>

        </ul>
      </div>
      <div class="looping-words__fade"></div>
      <div data-looping-words-selector="" class="looping-words__selector">
        <div class="looping-words__edge"></div>
        <div class="looping-words__edge is--2"></div>
        <div class="looping-words__edge is--3"></div>
        <div class="looping-words__edge is--4"></div>
      </div>
    </div>
</section>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
<script>
    
    // ------- Osmo [https://osmo.supply/] ------- //

document.addEventListener('DOMContentLoaded', function() {
  const wordList = document.querySelector('[data-looping-words-list]');
  const words = Array.from(wordList.children);
  const totalWords = words.length;
  const wordHeight = 100 / totalWords; // Offset as a percentage
  const edgeElement = document.querySelector('[data-looping-words-selector]');
  let currentIndex = 0;
  function updateEdgeWidth() {
    const centerIndex = (currentIndex + 1) % totalWords;
    const centerWord = words[centerIndex];
    const centerWordWidth = centerWord.getBoundingClientRect().width;
    const listWidth = wordList.getBoundingClientRect().width;
    const percentageWidth = (centerWordWidth / listWidth) * 100;
    gsap.to(edgeElement, {
      width: `${percentageWidth}%`,
      duration: 0.5,
      ease: 'Expo.easeOut',
    });
  }
  function moveWords() {
    currentIndex++;
    gsap.to(wordList, {
      yPercent: -wordHeight * currentIndex,
      duration: 1.2,
      ease: 'elastic.out(1, 0.85)',
      onStart: updateEdgeWidth,
      onComplete: function() {
        if (currentIndex >= totalWords - 3) {
          wordList.appendChild(wordList.children[0]);
          currentIndex--;
          gsap.set(wordList, { yPercent: -wordHeight * currentIndex });
          words.push(words.shift());
        }
      }
    });
  }
  updateEdgeWidth();
  gsap.timeline({ repeat: -1, delay: 1 })
    .call(moveWords)
    .to({}, { duration: 2 })
    .repeat(-1);
});
    
</script>
				
			

CSS

				
					/* ------- Osmo [https://osmo.supply/] ------- */
/* Osmo UI: https://slater.app/10324/23333.css */


.cloneable {
  padding:5rem;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  display: flex;
  position: relative;
}

.looping-words {
  height: 2.7em;
  padding-left: .1em;
  padding-right: .1em;
  font-size: 11vw;
  line-height: .9;
  position: relative;
}

.looping-words__list {
  text-align: center;
  text-transform: uppercase;
  white-space: nowrap;
  flex-flow: column;
  align-items: center;
  margin: 0;
  padding: 0;
  font-family: PP Neue Corp, sans-serif;
  font-weight: 700;
  list-style: none;
  display: flex;
  position: relative;
}

.looping-words__list.is--primary {
  color:gray;
}

.looping-words__list.is--gray {
  color:red;
}

.looping-words__fade {
  background-image: linear-gradient(180deg, var(--color-neutral-300) 5%, transparent 40%, transparent 60%, var(--color-neutral-300) 95%);
  pointer-events: none;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}

.looping-words__fade.is--radial {
  background-image: radial-gradient(circle closest-side at 50% 50%, transparent 64%, var(--color-neutral-400) 93%);
  width: 140%;
  display: block;
  left: -20%;
}

.looping-words__selector {
  pointer-events: none;
  width: 100%;
  height: .9em;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.looping-words__edge {
  border-top: .035em solid;
  border-left: .035em solid;
  border-color:red;
  width: .125em;
  height: .125em;
  position: absolute;
  top: 0;
  left: 0;
}

.looping-words__edge.is--2 {
  left: auto;
  right: 0;
  transform: rotate(90deg);
}

.looping-words__edge.is--3 {
  inset: auto 0 0 auto;
  transform: rotate(180deg);
}

.looping-words__edge.is--4 {
  top: auto;
  bottom: 0;
  transform: rotate(270deg);
}

.looping-words__containers {
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
}

.looping-words__p {
  margin: 0;
}

@font-face {
  font-family: 'PP Neue Corp';
  src: url('https://cdn.prod.website-files.com/6717aac16c9ea22eeef1e79e/6717de2d56e40b921572d2d9_PPNeueCorp-TightUltrabold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
				
			
view transitions

¿Qué es View Transitions?

View Transitions es una API moderna del navegador que permite crear transiciones fluidas entre diferentes vistas o estados de una página web.

WordPress con React y Gutenberg

Crear una landing page con React y Gutenberg en WordPress es una combinación poderosa para lograr una experiencia de usuario moderna y un control total sobre el desarrollo.