Skip to content

Instantly share code, notes, and snippets.

@andregivenchy
Last active January 11, 2020 15:10
Show Gist options
  • Save andregivenchy/bff79280cff34481825cf6ce870935a0 to your computer and use it in GitHub Desktop.
Save andregivenchy/bff79280cff34481825cf6ce870935a0 to your computer and use it in GitHub Desktop.
Rotating Headline
<div class="PageBackToWork">
<h1 id="rotater-text" class="PageBackToWork-heading">
<span id="we-are-text" class="PageBackToWork-heading-itText">We are</span>
<span class="PageBackToWork-heading-rotationTextContainer">
<span data-rotater-text class="PageBackToWork-heading-rotationText">Listeners</span>
<span data-rotater-text class="PageBackToWork-heading-rotationText is-hidden is-inactive">Thinkers</span>
<span data-rotater-text class="PageBackToWork-heading-rotationText is-hidden is-inactive">Solvers</span>
<span data-rotater-text class="PageBackToWork-heading-rotationText is-hidden is-inactive">Partners</span>
<span data-rotater-text class="PageBackToWork-heading-rotationText is-hidden is-inactive">Visionaries</span>
<span data-rotater-text class="PageBackToWork-heading-rotationText is-hidden is-inactive">Leaders</span>
<span data-rotater-text class="PageBackToWork-heading-rotationText is-hidden is-inactive">Innovators</span>
<span data-rotater-text class="PageBackToWork-heading-rotationText is-hidden is-inactive">Visionaries</span>
<span data-rotater-text class="PageBackToWork-heading-rotationText is-hidden is-inactive">Storytellers</span>
<span data-rotater-text class="PageBackToWork-heading-rotationText is-hidden is-inactive">Rebels</span>
<span data-rotater-text class="PageBackToWork-heading-rotationText is-hidden is-inactive">Misfits</span>
<span data-rotater-text class="PageBackToWork-heading-rotationText is-hidden is-inactive">Creators</span>
<span data-rotater-text class="PageBackToWork-heading-rotationText is-hidden is-inactive">Dreamers</span>
<span data-rotater-text class="PageBackToWork-heading-rotationText is-hidden is-inactive">Lovers</span>
<span data-rotater-text class="PageBackToWork-heading-rotationText is-hidden is-inactive">Mentors</span>
<span data-rotater-text class="PageBackToWork-heading-rotationText is-hidden is-inactive">Authentic</span>
</span>
</div>

Rotating Headline

This animation uses a simple fade-in and fade-out animation to move the first word of the text (consisting of “Word 001”, “Word 002”, “Word 003” etc.) alongside moving the “We Are” text to align with the rest of the text. We used the FLIP principle by Paul Lewis to achieve 60fps while managing to calculate where to move the text from and to, so it's smooth as butter.

const containerEl = document.getElementById('rotater-text');
const itTextEl = document.getElementById('we-are-text');
const textEls =
Array.from(containerEl.querySelectorAll('[data-rotater-text]'));
const interval = 900;
let activeElement = 0;
function rotateText() {
setTimeout(rotateText, interval);
const oldTextEl = textEls[activeElement];
activeElement += 1;
if (activeElement === textEls.length) {
activeElement = 0;
}
const newTextEl = textEls[activeElement];
const oldTextBeforeBoundingRect = oldTextEl.getBoundingClientRect();
const itTextBeforeBoundingRect = itTextEl.getBoundingClientRect();
oldTextEl.classList.add('is-inactive');
newTextEl.classList.remove('is-inactive');
newTextEl.classList.remove('is-hidden');
const oldTextAfterBoundingRect = oldTextEl.getBoundingClientRect();
const itTextAfterBoundingRect = itTextEl.getBoundingClientRect();
const oldTextLeftPosition =
oldTextBeforeBoundingRect.left - oldTextAfterBoundingRect.left;
const oldTextTopPosition =
oldTextBeforeBoundingRect.top - oldTextAfterBoundingRect.top;
const itTextLeftPosition =
itTextBeforeBoundingRect.left - itTextAfterBoundingRect.left;
const oldTextAnimationPlayer = oldTextEl.animate([{
opacity: 1,
transform: `translateX(${oldTextLeftPosition}px)
translateY(${oldTextTopPosition}px)`,
}, {
opacity: 0,
transform: `translateX(${oldTextLeftPosition}px) translateY(0)`,
}], {
duration: 300,
fill: 'forwards',
easing: 'ease-in-out',
});
oldTextAnimationPlayer.onfinish = () => {
oldTextEl.classList.add('is-hidden');
};
newTextEl.animate([{
opacity: 0,
transform: 'translateY(100%)',
}, {
opacity: 1,
transform: 'translateY(0)',
}], {
duration: 300,
fill: 'both',
easing: 'ease-in-out',
});
itTextEl.animate([{
transform: `translateX(${itTextLeftPosition}px)`,
}, {
transform: 'translateX(0)',
}], {
duration: 300,
fill: 'both',
easing: 'ease-in-out',
});
}
rotateText();
<script src="https://cdnjs.cloudflare.com/ajax/libs/web-animations/2.2.2/web-animations.min.js"></script>
@breakpoint-mobile: 480px;
@breakpoint-desktop-large: 1200px;
.is-hidden {
display: none !important;
}
.PageBackToWork {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
color: white;
background: #000;
font-family: 'Roboto', sans-serif;
font-weight: bold;
&-heading {
text-transform: uppercase;
letter-spacing: 0.05em;
@breakpoint-desktop-large-unitless: unit(@breakpoint-desktop-large);
@breakpoint-mobile-unitless: unit(@breakpoint-mobile);
font-size: ~"calc(56px + (72 - 56) * ((100vw - @{breakpoint-mobile}) / (@{breakpoint-desktop-large-unitless} - @{breakpoint-mobile-unitless})))";
@media (min-width: @breakpoint-desktop-large) {
font-size: 72px;
}
&-rotationTextContainer {
position: relative;
}
&-rotationText {
display: inline-block;
position: relative;
&.is-inactive {
position: absolute;
right: 0;
bottom: 100%;
}
}
&-itText {
display: inline-block;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment