Skip to main content

Promo: Nested Timelines

Master Advanced GreenSock Animation Control with Nested Timelines

Key Concepts You'll Master

Timeline Nesting

Learn to organize complex animations by nesting child timelines within a parent timeline for better control and debugging.

Individual Tweens

Discover how to mix individual tweens with nested timelines within the same parent timeline structure.

Error Prevention

Implement strategies to handle connectivity problems and prevent visual glitches during page load.

Topics Covered in This GreenSock Tutorial:

Nesting Timelines Within a Parent Timeline, Adding Individual Tweens to the Parent Timeline, Making Provisions for Connectivity Problems

Exercise Preview

promo nested timelines exercise preview

Exercise Overview

In this exercise, we'll master one of GreenSock's most powerful organizational features: nesting multiple timelines within a parent timeline. By consolidating the two timelines we created in previous exercises into a single parent timeline, we unlock sophisticated control capabilities that are essential for production-level animation work.

This hierarchical approach allows you to debug entire animation sequences holistically, fine-tune timing relationships between complex elements, and implement robust fallbacks for real-world deployment challenges like network connectivity issues. You'll also gain the ability to control your entire animation ecosystem through unified controls—play(), pause(), and reverse() methods that affect the complete sequence rather than individual components.

Exercise Workflow

1

Modify Existing Functions

Update getStarsTimeline() and getTitlesTimeline() functions to return timeline objects instead of just creating them

2

Create Parent Timeline

Build a main TimelineLite instance that will contain all nested timelines and individual tweens

3

Add Connectivity Protection

Implement safeguards against network issues using CSS visibility and autoAlpha properties

Getting Started

Let's begin by setting up our workspace and preparing the existing code for timeline nesting.

  1. In your code editor, open yourname-GSAP Class > Promo Nested Timelines > index.html (or the entire Promo Nested Timelines folder if your editor supports project-based workflows).

    This file represents the final state from our previous exercise, where two independent timelines execute simultaneously. While this works functionally, it lacks the architectural control needed for complex animations. We'll restructure these timelines to operate within a parent timeline hierarchy.

  2. Locate the following function calls on lines 55–56 and delete them entirely:

    getStarsTimeline();
    getTitlesTimeline();

    These immediate function calls will be replaced with a more controlled approach that allows us to manage when and how these timelines execute within our parent structure.

Starting Point

This exercise builds on previous work where two separate timelines were playing simultaneously. We'll restructure this code to use a parent timeline architecture for better control.

Nesting Timelines Within a Parent Timeline

Now we'll implement TimelineLite's powerful add() method to create a hierarchical timeline structure. This approach mirrors professional animation workflows where complex sequences are built from modular, reusable components.

  1. To enable timeline nesting, we need to modify our existing functions to return timeline instances rather than simply executing them. Add the return statements shown below in bold to both functions (around lines 44 and 54):

    function getStarsTimeline(){
       var $starfield = $("#starfield"), 
           tl = new TimelineLite();
    
       for(var i = 0; i<50; i++){

    Code Omitted To Save Space

    }
       return tl;
    }
    
    function getTitlesTimeline(){ 
       var $titles = $(".title"), 
           tl = new TimelineLite();
    
          tl.set($titles, {xPercent:-100}).staggerTo($titles, 3, {X:width, xPercent:0, ease:SlowMo.ease.config(0.1,1.2)}, 0.3).staggerFrom($titles, 3, {scale:0, opacity:0, ease:SlowMo.ease.config(0.1,1.2, true)}, 0.3,0);
       return tl;
    }

    This architectural change transforms our functions from immediate executors to timeline factories. By returning timeline instances, we enable precise control over their integration into parent timelines, including when they start, how they're positioned relative to other animations, and how they can be manipulated as a cohesive unit.

  2. Create the master timeline that will orchestrate all child animations. Add the following code beneath the getTitlesTimeline() function (around line 57):

    .staggerFrom($titles, 3, {scale:0, opacity:0, ease:SlowMo.ease.config(0.1,1.2, true)}, 0.3,0);
       return tl;
    }
    
    var mainTimeline = new TimelineLite();

    This parent timeline serves as the conductor for our animation orchestra, providing centralized control and coordination capabilities.

  3. Integrate the first child timeline using the add() method:

    var mainTimeline = new TimelineLite();
    mainTimeline.add(getStarsTimeline())

    The add() method seamlessly incorporates the timeline returned by getStarsTimeline() into our parent structure, maintaining all of its internal timing and animation properties.

  4. Save the file and preview in your browser.

    You'll notice the Animation Beyond Flash text remains static, while the starfield animation executes perfectly. This confirms that our nested timeline architecture is functioning correctly—the parent timeline is successfully managing the child timeline execution.

  5. Add the second child timeline to complete our nested structure:

    var mainTimeline = new TimelineLite();
    mainTimeline.add(getStarsTimeline())
    .add(getTitlesTimeline())

    GreenSock's method chaining allows for clean, readable timeline construction that clearly shows the sequence relationships.

  6. Save and preview the file again.

    The animations now execute sequentially—the title animation waits for the starfield animation to complete. While this demonstrates proper nesting, it doesn't match our intended simultaneous playback design.

  7. Implement simultaneous playback using position parameters:

    .add(getTitlesTimeline(), 0)

    The position parameter "0" instructs the titles timeline to begin at the very start of the parent timeline, creating the simultaneous playback we need.

  8. Save and test your changes. Excellent—both animations now launch simultaneously within the coordinated parent timeline structure.

return tl;
The key modification that transforms timeline creation functions into reusable components that can be nested within parent timelines

Timeline Execution Behavior

FeatureWithout Position ParameterWith Position Parameter
Execution OrderSequential (one after another)Simultaneous (at same time)
Code Example.add(getTitlesTimeline()).add(getTitlesTimeline(), 0)
Use CaseStory progressionLayered effects
Recommended: Use position parameters to control when nested timelines start relative to the parent timeline

Adding Individual Tweens to the Parent Timeline

Beyond nesting complete timelines, GreenSock allows you to integrate individual tweens directly into parent timelines. This flexibility enables sophisticated animation sequences that combine both modular timeline components and specific, targeted animations.

  1. Let's enhance our sequence with a smooth fade-in effect for the entire demo container. Add this code around line 59:

    mainTimeline
    .from($demo, 2, {autoAlpha:0}).add(getStarsTimeline())

    This fade-in tween uses GreenSock's intelligent autoAlpha property, which combines opacity and visibility management. When autoAlpha reaches zero, the element becomes both invisible and non-interactive, preventing user interface issues that can occur with opacity-only approaches. This attention to detail reflects professional animation standards.

  2. Save and preview the animation in your browser.

  3. Reload the page several times, observing carefully how the black background fades in over two seconds. While this creates a more polished introduction, you'll notice the timing relationships have shifted—the titles timeline begins immediately while the stars timeline waits for the fade to complete.

    Let's implement a storyboard-based approach using GreenSock's label system to maintain clean timing relationships. We'll designate the fade-in as "panel1" and the combined animations as "panel2."

  4. Apply timeline labels to coordinate the timing:

    var mainTimeline = new TimelineLite();
    mainTimeline.from($demo, 2, {autoAlpha:0}).add(getStarsTimeline(), "panel2").add(getTitlesTimeline(), "panel2")

    Timeline labels provide semantic timing control that's both readable and maintainable. The first reference to "panel2" creates the label at that timeline position, while subsequent references place additional elements at that same point. This approach scales beautifully for complex, multi-phase animations.

  5. Test your changes. The sequence now flows properly: a two-second fade-in followed by synchronized child timeline execution. This demonstrates professional-level timing coordination.

    However, the fade duration feels excessive for modern web standards. Let's optimize for contemporary user expectations.

  6. Refine the fade timing for better pacing:

    var mainTimeline = new TimelineLite();
    mainTimeline.from($demo, 0.5, {autoAlpha:0}).add(getStarsTimeline(), "panel2").add(getTitlesTimeline(), "panel2")
  7. Save and preview the final result. This refined timing creates a more responsive, engaging experience that aligns with current web animation best practices. The label-based architecture meant we only needed to modify one value to achieve this timing improvement.

AutoAlpha Plugin Benefits

GSAP's autoAlpha plugin automatically toggles CSS visibility to hidden when opacity reaches zero, preventing user interaction with invisible elements. This is more robust than using opacity alone.

Animation Sequence Structure

0s

Panel 1: Fade In

Demo div fades in from autoAlpha 0 over 0.5 seconds

0.5s

Panel 2: Stars Timeline

Starfield animation begins at panel2 label

0.5s

Panel 2: Titles Timeline

Title animations start simultaneously with stars

Making Provisions for Connectivity Problems

Professional web animation requires robust consideration of real-world deployment conditions. Network instability, slow connections, and resource loading failures can create jarring visual experiences if not properly addressed. Let's implement defensive animation patterns that ensure graceful degradation under adverse conditions.

Modern web applications must handle various network conditions gracefully. Let's simulate connectivity issues and implement the autoAlpha property strategically to prevent flash-of-unstyled-content (FOUC) problems that can occur when JavaScript assets load slowly or fail entirely.

  1. Encapsulate the parent timeline creation within a function to enable controlled execution timing:

    function createTimeline() {
       var mainTimeline = new TimelineLite();
       mainTimeline.from($demo, 0.5, {autoAlpha:0}).add(getStarsTimeline(), "panel2").add(getTitlesTimeline(), "panel2")
    }

    This functional approach provides precise control over when our animation system initializes, allowing us to simulate various loading scenarios and implement appropriate fallback strategies.

  2. Save and test the file. The page displays as completely static with white text on black background—this represents the fallback experience users would encounter if JavaScript fails to load or execute due to severe connectivity problems.

  3. Simulate network latency using GreenSock's delayed execution capabilities:

    function createTimeline() {
       var mainTimeline = new TimelineLite();
       mainTimeline.from($demo, 0.5, {autoAlpha:0}).add(getStarsTimeline(), "panel2").add(getTitlesTimeline(), "panel2")
    }
    //simulate network connectivity issues
    TweenLite.delayedCall(1, createTimeline);

    The delayedCall() method simulates the delay that occurs when JavaScript resources load slowly. The first parameter specifies the delay duration in seconds, while the second parameter references the function to execute (note the absence of parentheses, as we're passing the function reference rather than invoking it immediately).

  4. Test the simulated connectivity scenario. You'll observe one second of static display followed by normal animation execution. This mimics real-world conditions where users might experience loading delays.

    However, we need to prevent users from seeing unstyled content during the loading phase.

  5. Open the CSS file to implement defensive styling: Promo Nested Timelines > css > style.css

  6. Add visibility control to prevent FOUC issues:

    #demo {
       position:relative;
       width:500px;
       height:445px;
       background-color:#000;
       margin:auto; 
       overflow:hidden;
       visibility:hidden;
    }

    By setting initial visibility to hidden, we ensure that content remains invisible during the critical loading and initialization phase. Once JavaScript executes and creates the timeline, autoAlpha will override this CSS property and provide the smooth fade-in experience.

  7. Save both files and conduct final testing.

    Perfect! The sequence now handles connectivity issues elegantly: one second of invisible loading (simulating network delay), followed by the controlled autoAlpha fade-in that overrides the CSS visibility setting, and finally smooth execution of the synchronized animation timelines. This approach prevents jarring visual artifacts while maintaining professional animation quality.

Connectivity Protection Strategy

Pros
Prevents flash of unstyled content during load delays
Provides graceful degradation for slow connections
AutoAlpha overrides CSS visibility for smooth transitions
DelayedCall method allows realistic testing scenarios
Cons
Requires additional CSS setup for initial state
Adds complexity to timeline initialization
May delay animation start for users with good connections

Implementation Steps

1

Wrap in Function

Contain the main timeline creation within a createTimeline() function to control when it executes

2

Add CSS Protection

Set visibility:hidden on the demo div in CSS to prevent premature visibility

3

Use DelayedCall for Testing

Implement TweenLite.delayedCall(1, createTimeline) to simulate network delays

Bonus 1: Promo Animation with Controller

To demonstrate the true power of nested timeline architecture, we've prepared an advanced implementation that showcases centralized animation control. This example illustrates why hierarchical timeline structure is essential for professional animation workflows.

  1. Launch the enhanced controller version in your browser: Promo Nested Timelines Done > finished_with_controls.html

    If you completed the TimelineLite Control exercise, you'll recognize the sophisticated control interface from the Into the Wind animation project. This implementation demonstrates how timeline nesting enables complex animation systems to be managed through unified control interfaces.

  2. Experiment with the full range of controls available. Notice how the parent timeline architecture enables seamless reverse playback, pause functionality, and scrub-through capabilities across the entire animation sequence. This level of control is only possible when child timelines are properly nested within a parent structure—individual timeline management would require multiple, complex control systems.

Parent Timeline Benefits

Because all child timelines are contained within a single parent timeline, you can control the entire complex animation sequence with one set of play, pause, and reverse controls.

Bonus 2: Checking Out the Finished Promo's Code

Let's examine the complete implementation to understand how these principles scale to production-level animation projects.

  1. Open the comprehensive implementation file: Promo Done > index.html

  2. Study the architecture of the five modular timeline functions (such as getStarsTimeline() around line 88 and getTitlesTimeline() around line 100). Notice the consistent pattern: each function creates its timeline logic and concludes with return tl, making it a reusable timeline factory that can be integrated into any parent timeline structure.

  3. Examine the sophisticated parent timeline implementation around line 134:

    //build main timeline
    mainTimeline.from($demo, 0.5, {autoAlpha:0}).add(getNobleTimeline(), 0.5).add("panel2", "-=1.5").add(getStarsTimeline(), "panel2").add(getTitlesTimeline(), "panel2").add(getPoweredByTimeline()).add(getEndTimeline(), "-=0.2");

    This production-ready timeline demonstrates advanced techniques including relative positioning ("-=1.5", "-=0.2"), multiple labeled sections, and the seamless integration of five distinct timeline components. The add() method provides the architectural foundation that makes this level of complexity manageable and maintainable.

    This hierarchical approach represents industry best practices for complex animation development. By building animations as modular, nested components, you create systems that are easier to debug, modify, and extend—essential qualities for professional animation projects.

Production Code Review Points

0/4

Key Takeaways

1Nested timelines provide superior organization and control for complex animations compared to managing multiple separate timelines
2Functions that create and return timeline objects can be reused as components within parent timelines using the add() method
3Position parameters and labels offer precise control over when nested timelines start relative to their parent timeline
4Individual tweens can be mixed with nested timelines within the same parent timeline structure
5The autoAlpha property is more robust than opacity alone as it automatically manages CSS visibility for better user experience
6Connectivity protection strategies using CSS visibility and delayed function calls prevent visual glitches during slow page loads
7Parent timeline architecture enables unified control over complex animation sequences with single play, pause, and reverse controls
8Labels provide cleaner, more maintainable code than absolute time positioning when coordinating multiple timeline elements

RELATED ARTICLES