Skip to content

icon picker
Flex Animation

Here is a simple documentation on how to animate elements within a flex frame ad unit.
a few steps to follow:
drop in the loading script to load the external files in your CustomJS text area of the creative
identify the element you are animating with either unique ID or class name ( if the class name is used for other elements, please use the ID instead)
populate the code with element identifier

here are some sample code:
the code is needed to load external files:
const loadExternal=e=>new Promise((t,a)=>{try{let d=document.createElement("script");d.src=e,d.type="text/javascript",d.addEventListener("load",e=>{t({status:!0})}),d.addEventListener("error",e=>{a({status:!1})}),d.async=!0,document.body.appendChild(d)}catch(n){a(n)}});

below code will load external css and javascript files and execute the animation sequence (when the ad is viewable within the users viewport )
loadExternal("https://static01.nytimes.com/ads/tbrandcreativetech/libs/utilities/FlexTools.js")
.then(()=>{
const F = new FlexTools();
F.Animate(["#logo-2","#cta-2"],"tada","2000ms","0ms",0);
})

Understanding the :

animationCSS is a javascript function that takes in 5 parameters
parameter 1: element you’d like to animate. this can be a single item or an Array of items (required)
parameter 2: type of animation you’d like to do (”pulse”, “fadeIn” ... ) ( , you’ll find a list of all possible animation types)
parameter 3: duration / speed of the animation ( in milliseconds ) (optional)
parameter 4: delay on animation start ( in milliseconds ) parameter
parameter 5: repeat of animation parameter (0, 1, 2, ... )

here is some sample code:
const F = new FlexTools();
F.Animate(".logo","pulse","2000ms","0ms",3);
in here, we are animating the logo element which has a class name of “logo”. we’ve selected the “pulse” type of animation for this. we wanted to animation duration for this to be “2000ms” (2 seconds long), we wanted the animation to start right away without any delay (so the delay value is set to “0ms”) and finally we wanted this animation to repeat 3 times.

here is another sample code:
Animate("#cta-2","tada","2000ms");
in here, we are animating the cta element which has a id of “cta-2” and we are looking to use “tada” as the animation style for it. we are looking to animation this element for 2000ms (2 seconds)

an alternate way to trigger animation:
Animate({
target: "#cta-2",
type: "tada",
duration: "2000ms",
delay: "0ms",
repeat: 0
});


ones you are all set, the below is how your code should look like
Screenshot 2025-02-13 at 9.29.44 AM.png

sample ad here >
sample 1:
sample 2:


Digging Deeper in the code:
FlexTools javascript function:
/**
* FlexTools - A utility class for handling CSS animations dynamically.
*
* This class provides animation presets, handles viewability detection,
* and applies animations on elements based on user-defined settings.
*/

class FlexTools {

/**
* Constructor initializes animation presets and speed settings.
* Also, loads an external stylesheet for animations.
*/

constructor() {

// Predefined animation presets with corresponding animation types and durations
this.Presets = {
"fade-slow": { animationType: "fadeIn", duration: "2000ms"},
"fade-fast": { animationType: "fadeIn", duration: "800ms"},
"fadedown-slow": { animationType: "fadeInDown", duration: "2000ms"},
"fadedown-fast": { animationType: "fadeInDown", duration: "800ms"},
"fadeup-slow": { animationType: "fadeInUp", duration: "2000ms"},
"fadeup-fast": { animationType: "fadeInUp", duration: "800ms"},
"slidein-left": { animationType: "slideInLeft", duration: "800ms"},
"slidein-right": { animationType: "slideInRight", duration: "800ms"}
}

// Speed presets for quick configuration
this.SpeedPreset = {"fast": {speed: "800ms"},"faster": {speed:"500ms"},"slow": {speed: "2000ms"},"slower": {speed: "3000ms"}}

// Load external animation stylesheet
let externalStyle = document.createElement("link");
externalStyle.href = "https://static01.nytimes.com/ads/tbrandcreativetech/libs/flex-suite/utilities/animation/animateCSS.css";
externalStyle.rel = "stylesheet";
externalStyle.type = "text/css";
document.body.appendChild(externalStyle);
}


/**
* Triggers an animation on an element when it becomes visible in the viewport.
*
* @param {string} element - The CSS selector for the target element.
* @param {string} [type="fadeIn"] - The animation type (default is "fadeIn").
* @param {string} [duration="800ms"] - Duration of the animation.
* @param {string} [delay="0ms"] - Delay before animation starts.
* @param {number} [repeat=0] - Number of times the animation repeats.
*/

Animate = function (element,type = "fadeIn", duration = "800ms", delay = "0ms", repeat = 0) {

let playLimit = 1;
let currentPlayCount = 0;

/**
* Uses Intersection Observer to detect when an element is in the viewport.
* @param {Object} Ad - Object containing container element and visibility handlers.
*/
function VisibilityUsingObserver(Ad) {
const options = {root: null, rootMargin: '0px',threshold: 0.3};
const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => {if (entry.isIntersecting) { Ad.visible(); } else { Ad.hidden(); }});}, options);
observer.observe(Ad.container);
}
// Start viewability detection on the element
VisibilityUsingObserver({
"container": document.querySelector(element),
"visible": () => {
if (currentPlayCount < playLimit) {
currentPlayCount++;
this.AnimateOnDemand (element,type, duration , delay, repeat);
}
},
"hidden": () => {}
});
}

ViewabilityDetection(data) {

let playLimit = 1000;
let currentPlayCount = 0;

if ((data["playOnce"]) || (data["playOnce"] == undefined)) {
playLimit = 1;
}
function VisibilityUsingObserver(Ad) {
const options = {root: null, rootMargin: '0px',threshold: data.threshold ? data.threshold : 0.3};
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.