<div class="page">
<div class="marquee">
<div class="marquee__track">
<ul class="marquee__line">
<li class="marquee__text">Lorem</li>
<li class="marquee__text">ipsum</li>
<li class="marquee__text">dolor</li>
<li class="marquee__text">sit</li>
<li class="marquee__text">amet</li>
<li class="marquee__text">consectetur</li>
</ul>
<ul class="marquee__line marquee__line--copy">
<li class="marquee__text">Lorem</li>
<li class="marquee__text">ipsum</li>
<li class="marquee__text">dolor</li>
<li class="marquee__text">sit</li>
<li class="marquee__text">amet</li>
<li class="marquee__text">consectetur</li>
</ul>
</div>
</div>
</div>
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: sans-serif;
}
.page {
display: flex;
flex-direction: column;
background-color: #212429;
min-height: 100vh;
}
.marquee {
margin-top: 50px;
overflow: hidden;
}
.marquee__track {
position: relative;
display: inline-flex;
animation: marqueeAnimation 10s linear infinite;
}
.marquee:hover .marquee__track {
animation-play-state: paused;
}
@keyframes marqueeAnimation {
to { transform: translateX(-50%); }
}
.marquee__line {
display: inline-flex;
padding: 0;
margin: 0;
list-style: none;
}
.marquee__line--copy {
}
.marquee__text {
position: relative;
margin-right: 10px;
text-transform: uppercase;
font-weight: 600;
font-size: 3em;
background-image:
none,
linear-gradient(to bottom right, #2c2e31, #22252a);
background-repeat: no-repeat;
background-clip: text;
text-fill-color: transparent;
filter: drop-shadow(3px 3px 3px rgba(0, 0, 0, 0.25));
user-select: none;
}
.marquee:hover .marquee__text {
background-image:
radial-gradient(circle at 50% 50%, #1ca6fe, #e03f8e 25%, transparent 50%),
linear-gradient(to bottom right, #2c2e31, #22252a);
}
.marquee__text::before {
content: '*';
margin-right: 10px;
vertical-align: middle;
}
const marquee = document.querySelector('.marquee');
let marqueeRect = null;
const marqueeTexts = Array.from(
marquee.querySelectorAll('.marquee__text'),
(el) => ({ el, rect: null })
);
function onMouseMove(event) {
const size = Math.max(marqueeRect.width, marqueeRect.height);
marqueeTexts.forEach(text => {
const gx = -text.rect.left - size * 0.5 + event.clientX;
const gy = -text.rect.top - size * 0.5 + event.clientY;
text.el.style.backgroundPosition = `${gx}px ${gy}px, 0 0`;
});
}
marquee.addEventListener('mouseenter', () => {
marqueeRect = marquee.getBoundingClientRect();
const size = Math.max(marqueeRect.width, marqueeRect.height);
marqueeTexts.forEach(text => {
text.rect = text.el.getBoundingClientRect();
text.el.style.backgroundSize = `${size}px ${size}px, 100% 100%`;
});
marquee.addEventListener('mousemove', onMouseMove);
});
marquee.addEventListener('mouseleave', () => {
marquee.removeEventListener('mousemove', onMouseMove);
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.