Background Animation Wordpress web development Development

Hello All,
New to wordpress and working with wordpress and PHP. One of my clients is needs background animation on hero section like this website. Just wondering if there is any plugin available to achieve this or any way to code this.

Any suggestions welcome

Is this the kind of thing you are after?

1 Like

I dont know that CSS alone could handle the changing text?
In my head, you could do it fairly simply by combining that effect with a JS trigger on animationend to swap classes out on stacked spans?
IE:

HTML:

DivHolder contains:
  Span1 has class `typing`.
  Span2, 3, and 4 do not.
DivBlink has class `blinking`.

CSS:
typing has defined animation iterations 2 direction alternate.
blinking has defined animation infinite.

JS:
Spans1,2,3,4 have an eventListener for animationend that {
Removes typing from all spans.
Adds typing to the event target’s nextSibling or null coalesces to the first span.
}

1 Like

If you are just talking about the text typing effect then you can do that with CSS alone (although it would be more usable with JS to take care of counting characters).

This was an old demo where I have just updated the text content.

https://codepen.io/paulobrien/pen/bNGQBRJ

If the OP is talking about the background joined dot to do moving effect then that would seem to be particle js.

1 Like

Just been having a play, JS included to count characters :slight_smile:

https://codepen.io/rpg2019/pen/WbNLyvg

1 Like

Nice demo and thanks for the JS start :slight_smile:

I have now created a new demo to automatically generate the keyframes based on the content and character count. Turned out to be harder than I expected but eventually got there :slight_smile:

https://codepen.io/paulobrien/pen/zxYymEr

Thanks all, for your suggestions! I am still working on it will update screenshot what it looked like but above served as good starting point.

2 Likes

@PaulOB,

This was definitely on my mind. Might take that off you :slight_smile:

h1:after {
  content: "|";
  margin-left: 10px;
  animation: caret 0.3s infinite;
  opacity: 0;
}

This is obviously important too.

/* Disable animations if user prefers reduced motion and just show first span*/
@media (prefers-reduced-motion: reduce) {
  .type span {
    animation: none !important;
  }
  .type span:first-child {
    width: auto;
  }
  .type::after {
    animation: none;
  }
}
1 Like

I have gone off on my own little project here, but hopefully there is something to dig out of it.

Paul was setting at least some properties on the stylesheet as far I can tell. I have opted for just adding the variables to an inline style on each text line. I do want to look into Paul’s approach though, there might be a more elegant solution using setProperties.

Code

HTML
To make the pseudo :after cursors work the text spans need a parent element to attach that to.

I am also making use of datasets to add a pause before the typing starts on certain lines — just to add a bit of suspense :biggrin:

<div class='container'>
    <div class='typewriter cursor-active'>
        <span class='typewriter-text' data-delay='2'>GREETINGS PROFESSOR FALKEN</span>
    </div>
    <br>
    <div class='typewriter'>
        <span class='typewriter-text' data-delay='2'>HELLO</span>
    </div>
    <div class='typewriter'>
        <span class='typewriter-text'>A STRANGE GAME</span>
    </div>
    <div class='typewriter'>
        <span class='typewriter-text'>THE ONLY WINNING MOVE IS</span>
    </div>
    <div class='typewriter'>
        <span class='typewriter-text'>NOT TO PLAY.</span>
    </div>
    <br>
    <div class='typewriter'>
        <span class='typewriter-text' data-delay='4'>HOW ABOUT A NICE GAME OF CHESS?</span>
    </div>
</div>

CSS
The variables will be populated from the inline style properties, which are added in Javascript

e.g.

<span 
    class="typewriter-text" 
    style="--char-count: 24; --line-duration: 3s; --line-delay: 9.625s; --line-width: 24ch; animation-play-state: running;"
>THE ONLY WINNING MOVE IS</span>
.typewriter {
    display: flex;
    align-items: center;
    
    .typewriter-text {
        display: inline-flex;
        width: 0;
        overflow: hidden;
        white-space: nowrap;
        line-height: 1.2;
        
        animation: 
            typing 
            var(--line-duration) 
            steps(var(--char-count))
            forwards;
        animation-delay: var(--line-delay);
        animation-play-state: paused;
    }
    
    &.cursor-active:after {
        content: '_';
        margin-bottom: -2px;
        align-self: end;

        animation: blink 1s step-end infinite;
    }
    
    @keyframes blink {
        50% {
            opacity: 0;
        }
    }
    
    @keyframes typing {
        to {
            width: var(--line-width);
        }
    }
}

JS
I have commented the code, but if there are any questions, do feel free to ask.

const ANIM_CONFIG = {
    speed: 8
}

// Helper functions - not necessary, but I think help for more readable code
function addClass(elem, className = '') {
    elem.classList.add(className)
}

function removeClass(elem, className = '') {
    elem.classList.remove(className)
}

function onAnimationStart(elem, fn) {
    elem.addEventListener('animationstart', fn);
}

function onAnimationEnd(elem, fn) {
    elem.addEventListener('animationend', fn);
}

/**
 * Adds inline animation properties to the text element.
 * @param {HTMLElement} textElem - The text element to add the properties to.
 * @param {number} initDelay - line's delay in seconds before animation starts.
 * @param {number} sumDelays - sum of all previous lines delays.
 * @returns {number} duration - the duration time of the animation.
 */
function setlineProps(textElem, initDelay=0, sumDelays=0, config=ANIM_CONFIG) {
    const charCount = textElem.textContent.length;
    const duration = charCount / config.speed;
    
    textElem.style = `
        --char-count: ${charCount};
        --line-duration: ${duration}s;
        --line-delay: ${initDelay + sumDelays}s;
        --line-width: ${charCount}ch;
        animation-play-state: running
    `;
    
    // to be added to previous delays
    return initDelay + duration;
}

window.addEventListener('DOMContentLoaded', () => {
    const lines = document.querySelectorAll('.typewriter');
    let sumDelays = 0;
    
    for (const [i, line] of lines.entries()) {
        const text = line.querySelector('.typewriter-text');
        const initDelay = Number(text.dataset.delay || 0);
        
        // setLineProps returns initDelay + duration
        // this is added to previous delays
        sumDelays += (setlineProps(text, initDelay, sumDelays));
        
        // add cursor to new line and remove from previous line
        onAnimationStart(text, () => {
            // remove cursor from previous line if there is one
            if (i > 0)
                removeClass(lines[i-1], 'cursor-active');
            // add cursor to new line
            addClass(line, 'cursor-active');
        });
    } 
})

Full example here
https://codepen.io/rpg2019/pen/azbXdeo

My css is a bit limited. It would be nice to do away with a lot of this JS and do something clever in CSS instead.

I would say these are good exercises to do. A bit frustrating at times, but that’s how you learn :slight_smile:

edit: One thing I will share, don’t round up numbers when setting durations, delays etc.

e.g. after a calculation like duration = charCount / config.speed

don’t then try and round to 2 decimal places like I did.
--line-duration: ${duration.toFixed(2)}s;

instead just pass in as is
--line-duration: ${duration}s;

Albeit milliseconds difference the ‘e’ on ‘game’ wouldn’t show up if I added an initial delay of 1 or 2 seconds. It took quite a bit of debugging to try and figure out why I only had the issue with that particular line.

1 Like

Quibble:
Joshua punctuates the third line too. :wink:

(For those that somehow have managed to miss the reference, the lines being used here are the final lines from “Joshua”/WOPR and Stephen Falken in the movie WarGames. GREETINGS PROFESSOR FALKEN - YouTube )

[Irony: All of the lines here are spoken by John Wood, who portrays Falken. The synthesized lines from “Joshua” are also voiced by Wood, spoken backwards and modulated.]

2 Likes