GSAP - Documentation

Getting Started with GSAP

GreenSock Animation Platform (GSAP) is a powerful JavaScript library for creating high-performance animations. This section will guide you through the initial setup and fundamental concepts.

Installation

GSAP offers several installation methods:

1. CDN (Content Delivery Network): The quickest way to get started is by including GSAP via a CDN link in your HTML <head>:

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>

Replace 3.12.2 with the latest version number if necessary. Check the official GSAP website for the most up-to-date version.

2. npm (Node Package Manager): For projects using npm, install GSAP using:

npm install gsap

Then import it into your JavaScript file:

import { gsap } from 'gsap';

3. yarn (Yarn Package Manager): Similar to npm:

yarn add gsap

Then import it into your JavaScript file:

import { gsap } from 'gsap';

After installation, GSAP’s core functionality is available globally as gsap (unless using ES modules as shown above). For additional plugins (like ScrollTrigger or DrawSVGPlugin), you’ll need to install and import those separately.

Basic Usage

GSAP’s core function is gsap.to(), which creates a tween. A tween animates properties of a target element over time. The basic structure is:

gsap.to(target, duration, vars);

First Animation Example

Let’s animate a box’s position and opacity:

<!DOCTYPE html>
<html>
<head>
<title>GSAP Example</title>
<style>
#myBox {
  width: 100px;
  height: 100px;
  background-color: blue;
  position: absolute;
  left: 0;
  top: 0;
}
</style>
</head>
<body>
<div id="myBox"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<script>
  gsap.to("#myBox", 2, { x: 300, y: 200, opacity: 0 });
</script>
</body>
</html>

This code animates the #myBox element over 2 seconds, moving it 300px to the right and 200px down, while fading it out (opacity to 0).

Key Concepts: Tweens and Timelines

let tl = gsap.timeline();

tl.to(".element1", 1, { x: 100 });
tl.to(".element2", 0.5, { opacity: 0 }, "<"); //"<" indicates this tween starts at the same time as the previous one
tl.to(".element1", 1, { y:100 });

This example shows a simple timeline. The first tween moves .element1 100px horizontally over 1 second. The second tween fades out .element2 over 0.5 seconds, starting simultaneously with the first tween due to the < symbol. The third tween moves .element1 100px vertically after the first tween completes. Timelines offer extensive control over the timing and sequencing of animations, making them essential for complex projects. Explore GSAP’s documentation for more advanced timeline features like labels, pausing, and callbacks.

Core Concepts of GSAP

This section delves deeper into the fundamental building blocks of GSAP animations.

Tweens

Tweens are the heart of GSAP. They control the animation of individual properties of a target element over time. GSAP provides several functions to create tweens:

Example:

gsap.to(".box", 1, { x: 200, y: 100, opacity: 0, ease: "power1.inOut" }); // Animates to specified values
gsap.from(".box", 1, { x: -200, scale: 0.5 }); // Animates from specified values
gsap.fromTo(".box", 1, { x: -200, scale: 0.5 }, { x: 200, scale: 1, rotation: 360 });

The vars object (the third argument) defines the properties to animate and their target values. These values can be numbers, strings (for colors or CSS units), or even functions. More on that in the “Properties” section.

Timelines

Timelines are containers for organizing and controlling multiple tweens. They allow you to sequence animations, run them concurrently, and manage their playback. Timelines provide a structured way to create complex animations.

Creating a Timeline:

const tl = gsap.timeline();

Adding Tweens to a Timeline:

tl.to(".box", 1, { x: 200 })
  .to(".box", 0.5, { y: 100 })
  .to(".box", 1, { opacity: 0 });

This creates a timeline with three tweens that execute sequentially.

Timeline Control:

Timelines offer methods like play(), pause(), reverse(), seek(), restart(), progress(), etc., for fine-grained control over the animation sequence. See the GSAP documentation for detailed information on these methods.

Properties

GSAP can animate a vast array of properties, including:

Example:

gsap.to(".element", 1, {
  x: 100,
  backgroundColor: "red",
  scale: 1.2,
  attr: { "data-custom": "value" } //Animates an attribute
});

Easing

Easing controls the speed and rhythm of an animation. GSAP provides a wide range of easing functions, categorized as:

Example:

gsap.to(".element", 1, { x: 100, ease: "power1.inOut" }); // Power easing, ease-in-out variation
gsap.to(".element", 1, { x: 100, ease: "elastic.out(1, 0.3)" }); //Elastic easing with parameters

Repeating and Yoyo

Animations can be repeated using the repeat and yoyo properties:

Example:

gsap.to(".element", 1, { x: 100, repeat: 3, yoyo: true });

Chains and Sequencing

Multiple tweens can be chained together using the then() method (for sequential execution) or by using a timeline (for more complex arrangements with parallel animations). Chaining allows you to create complex animations by stringing together simpler tweens.

Example (Chaining):

gsap.to(".element", 1, { x: 100 })
  .then(() => gsap.to(".element", 1, { y: 100 }));

Callbacks and Events

Callbacks allow you to execute custom functions at specific points during an animation’s lifecycle:

Example:

gsap.to(".element", 1, {
  x: 100,
  onComplete: () => {
    console.log("Animation completed!");
  },
});

GSAP also provides events you can listen to, offering more control over the animation lifecycle. Consult the GSAP documentation for the complete list of available events and callbacks.

Tweening Basics with GSAP

This section details how to tween various data types and properties using GSAP.

Tweening Numbers

Tweening numbers is straightforward. Simply specify the target numerical property and its desired end value. GSAP will smoothly interpolate between the starting and ending values.

Example:

let myNumber = 0; //Initial value
gsap.to(
  { myNumber }, // Target object containing the number
  1, // Duration
  { myNumber: 100 } // Target value
);

After 1 second, myNumber will be 100. You can also tween multiple numerical properties within a single object:

let myObject = { x: 0, y: 0, scale: 1 };
gsap.to(myObject, 1, { x: 100, y: 50, scale: 2 });

Tweening Colors

GSAP seamlessly handles color tweening. You can use hexadecimal (#RRGGBB), RGB (rgb(r, g, b)), or RGBA (rgba(r, g, b, a)) color notations.

Example:

gsap.to(".element", 1, { backgroundColor: "#ff0000" }); // To red
gsap.to(".element", 1, { backgroundColor: "rgb(0, 255, 0)" }); // To green
gsap.to(".element", 1, { backgroundColor: "rgba(0, 0, 255, 0.5)" }); // To semi-transparent blue

GSAP intelligently handles color interpolation, even between different color formats.

Tweening CSS Properties

Many standard CSS properties can be animated directly using GSAP. This includes properties like width, height, opacity, left, top, margin, padding, transform properties (more on that in the next section), and more.

Example:

gsap.to(".element", 1, { width: "200px", opacity: 0.5, left: "100px" });

Remember that for certain properties (like width and height), you might need to ensure the element’s initial state (display, position etc) is correctly set in your CSS for the animation to work as expected.

Tweening SVG Attributes

GSAP can animate attributes of SVG elements. This allows for creating dynamic and complex SVG animations. You access SVG attributes using the attr property within the vars object.

Example:

gsap.to("circle", 1, { attr: { r: 50, cx: 100, cy: 100 } }); // Animates SVG circle's radius and center coordinates

This example animates the radius (r), x-coordinate (cx), and y-coordinate (cy) of an SVG circle element.

Tweening Custom Properties

GSAP can tween any property of a JavaScript object. This is incredibly useful for animating data unrelated to the DOM.

Example:

let myData = { progress: 0 };
gsap.to(myData, 2, { progress: 100, onUpdate: updateProgress });

function updateProgress() {
  // Update UI based on myData.progress
  console.log("Progress:", myData.progress);
}

In this example, we’re animating the progress property of the myData object. The onUpdate callback allows you to update your UI or other parts of your application based on the changing value of progress during the animation. This opens up many possibilities for creating data-driven animations. Remember that for this type of animation, GSAP is only updating the value of the object; it’s your responsibility to use that value to update your UI or perform other necessary actions.

Advanced Tweening Techniques with GSAP

This section explores more advanced techniques for creating sophisticated animations with GSAP.

Complex Animations

GSAP excels at handling complex animations involving numerous elements and intricate timing. Timelines are crucial for managing these scenarios. By combining multiple tweens and utilizing timeline controls (like play(), pause(), reverse(), timeScale(), etc.), you can orchestrate highly intricate sequences. Consider using labels within your timelines to easily reference specific points within your animation for more precise control.

Multiple Properties

Tweening multiple properties simultaneously is a core strength of GSAP. Simply list them within the vars object of your tween. GSAP handles the interpolation of all properties smoothly and efficiently.

Example:

gsap.to(".element", 1, {
  x: 200,
  y: 100,
  scale: 1.5,
  opacity: 0.5,
  rotation: 360,
  backgroundColor: "red",
});

Nested Tweens

Tweens can be nested within other tweens or within timelines. This allows for creating animations within animations, offering increased complexity and control.

Example:

gsap.to(".container", 1, {
  x: 200,
  onComplete: () => {
    gsap.to(".element", 0.5, { scale: 2 }); // Nested tween triggered on completion of the parent tween
  },
});

Delayed Tweens

You can introduce delays between tweens using the delay property. This is essential for creating precisely timed sequences.

Example:

gsap.to(".element1", 1, { x: 100 });
gsap.to(".element2", 1, { x: 100, delay: 1 }); // This tween starts 1 second after the first one

Alternatively, you can use the delay parameter directly in a Timeline:

const tl = gsap.timeline();
tl.to(".element1", 1, {x:100})
  .to(".element2", 1, {x:100}, 1); // This tween starts 1 second after the first one

Staggered Animations

GSAP’s stagger property is powerful for creating animations where elements appear or animate sequentially with a specific time offset. This is commonly used for lists or sequences of elements.

Example:

gsap.to(".element.item", {
  duration: 1,
  y: 100,
  stagger: 0.2, // 0.2 second delay between each element
});

This animates all elements with the class “item” vertically, with a 0.2-second delay between each.

Using Variables in Tweens

Using variables makes your code more maintainable and reusable. You can easily store durations, easing functions, or target values in variables for later use within your tween definitions:

Example:

const duration = 1;
const myEase = "power2.inOut";
const targetX = 200;

gsap.to(".element", duration, { x: targetX, ease: myEase });

Conditional and Dynamic Updates

Based on various conditions (e.g., user input, data changes, or screen size), you can dynamically adjust tween parameters. This enables creating interactive and responsive animations. Use functions within your tween parameters to calculate values at runtime.

Example:

let direction = 1; // 1 for right, -1 for left

gsap.to(".element", 1, {
  x: direction * 100, // x value depends on direction variable
  onComplete: () => {
    direction *= -1; // Reverse direction for next animation
  },
});

Tweening Arrays

While GSAP doesn’t directly tween arrays as a whole, you can tween individual elements of an array. You’ll need to manage the array updates yourself within the onUpdate callback.

Example:

let myArray = [0, 0, 0];

gsap.to(myArray, {
  duration: 2,
  onUpdate: () => {
    myArray.forEach((value, index) => {
       myArray[index] =  index * 20; // example update
    });
    // update visual elements that rely on myArray here
    console.log("myArray:", myArray)
  },
});

Remember that direct manipulation of the array within onUpdate needs to be handled carefully to avoid unexpected behaviors. It is recommended to create a copy of the array before performing any changes within the callback if the source array is used elsewhere. Consider using alternative approaches like using GSAP to animate individual properties of JavaScript objects where each object represents an array element for better performance and easier management in more complex scenarios.

Timelines in GSAP

Timelines are powerful tools in GSAP for orchestrating complex animations involving multiple tweens and intricate sequencing. They provide a structured way to manage the timing and order of your animations, making them essential for creating sophisticated and dynamic visual effects.

Creating Timelines

Creating a timeline is simple:

let myTimeline = gsap.timeline();

This creates an empty timeline ready to accept tweens.

Adding Tweens to Timelines

Tweens are added to a timeline using the timeline’s methods. The most common is the chaining method:

myTimeline
  .to(".element1", 1, { x: 100 })
  .to(".element2", 0.5, { opacity: 0 }, 0.2) // Added with a delay of 0.2 seconds relative to the previous tween.
  .to(".element3", 1, { y: 200 }, "+=0.5"); // Added with a delay of 0.5 seconds relative to the previous tween

This adds three tweens to myTimeline. The first animates .element1, the second animates .element2 after a 0.2-second delay, and the third animates .element3 0.5 seconds after the second tween. Notice the various ways you can specify timing: directly after the tween definition, or using the += syntax which adds a relative delay, or using a label (more on labels below). Multiple tweens can also be added using the add() method to provide more fine-grained control.

Timeline Sequencing

Timelines control the order of execution of tweens. By default, tweens are added sequentially. However, you have great flexibility in how these are sequenced:

Timeline Control

Timelines provide methods for controlling their playback:

Nested Timelines

Timelines can be nested within other timelines, creating a hierarchical structure for managing complex animations. This allows for modularity and easier organization of your animation code.

let mainTimeline = gsap.timeline();
let subTimeline = gsap.timeline();

subTimeline.to(".element1", 1, { x: 100 });
subTimeline.to(".element2", 1, { opacity: 0 });

mainTimeline.add(subTimeline);
mainTimeline.to(".element3", 1, { y: 200 });

In this example, subTimeline is added to mainTimeline, allowing you to manage the animations of .element1 and .element2 as a unit within the larger mainTimeline.

Labels and Time Markers

Labels provide named points within a timeline, making it easier to reference specific moments for adding tweens or seeking to particular positions.

let tl = gsap.timeline();
tl.to(".element", 1, { x: 100 }).addLabel("middle");
tl.to(".element", 1, { y: 100 }, "middle"); //Added at the `middle` label
tl.to(".element", 1, { x: 0 });

This adds a label named “middle” and adds a tween at that label in the timeline. Time markers (using add() with a time value instead of a label) serve a similar purpose, though they are visually distinguishable in the Timeline’s debug tools. They are often used for visually identifying key moments in an animation sequence.

Timeline Events

Timelines emit events at various points in their lifecycle. These can be used to trigger actions or other animations. You can listen for events such as:

let tl = gsap.timeline({
  onComplete: () => {
    console.log("Timeline completed!");
  },
});

tl.to(".element", 1, { x: 100 });

This timeline logs a message to the console when it finishes playing. These events, along with the robust control methods provided by timelines, allow for precise management of complex and dynamic animation sequences.

Easing and Interpolation in GSAP

Easing and interpolation determine how properties change over time during an animation. They are crucial for creating natural-looking and visually appealing animations.

Understanding Easing

Easing functions control the rate of change of a property’s value over time. A simple linear easing means the property changes at a constant rate. Other easing functions create variations in speed, like accelerating, decelerating, or bouncing. This allows you to create animations that feel more natural and engaging. Easing significantly impacts the perceived quality of your animations.

Built-in Easing Functions

GSAP provides a wide variety of built-in easing functions, categorized for ease of use:

Example:

gsap.to(".element", 1, { x: 100, ease: "power2.inOut" }); // Smooth acceleration and deceleration
gsap.to(".element", 1, { x: 100, ease: "elastic.out(1, 0.5)" }); // Elastic bounce effect

Custom Easing Functions

For complete control, you can define your own easing functions. GSAP uses an easing function that takes a normalized time value (between 0 and 1) as input and returns a modified value also between 0 and 1. GSAP can use either a string that represents a built-in easing function or a function that returns a value between 0 and 1 given a normalized time value.

// Example of a simple custom easing function (ease-in-out)
let customEase = function(t) {
  return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
};

gsap.to(".element", 1, { x: 100, ease: customEase });

You can create remarkably complex ease functions this way, offering almost limitless control over how your animations behave over time.

Bezier Curves

Bezier curves are a powerful way to visually design and create custom easing functions. GSAP can interpret Bezier curve coordinates to generate easing functions that match those curves exactly.

Tools exist online (search for “Bezier curve easing generator”) to help create these curves visually and then obtain the corresponding easing function, which you can then provide to GSAP as a string, similar to built-in functions.

Example (Using Bezier coordinates):

//Using a string representation of the Bezier Curve coordinates
gsap.to(".element", 1, {x: 100, ease: "power1.in"});  //Same as "M0,0 C0.1,0 0.9,1 1,1"

//Using a function that returns a value:
let bezierEase = function (t) {
    return t * t; //Example Quadratic Curve.  More complex Bezier curves will require appropriate calculations.
}

gsap.to(".element", 1, { x: 100, ease: bezierEase });

For more complex Bezier curves, you will need to perform the necessary calculations to obtain a function that produces the desired interpolation.

Interpolation Methods

Interpolation methods determine how values are calculated between keyframes (especially useful with multiple keyframes in timelines). GSAP’s default interpolation is highly optimized for most cases. However, you can specify other interpolation methods if needed, especially when dealing with complex data structures or custom properties.

This area is relatively advanced. Usually, you won’t need to change the default interpolation. Consult the GSAP documentation for details on overriding the default interpolation method if you have specific requirements for how GSAP handles values between keyframes. For most use cases, letting GSAP handle interpolation automatically is the most efficient and convenient approach.

Special Properties and Plugins in GSAP

This section covers advanced features and plugins that extend GSAP’s capabilities.

Transform Properties

GSAP provides optimized handling of CSS transform properties. This is crucial for performance, especially when animating multiple transforms simultaneously. Instead of animating individual properties like translateX, translateY, scale, and rotate, you can use a shorthand notation:

gsap.to(".element", 1, { x: 100, y: 50, scale: 1.5, rotation: 360 });

This is far more efficient than individually setting each transform property. GSAP intelligently handles these properties, ensuring smooth and performant animations, even with complex transformations. It uses optimized methods for transforming elements, ensuring the best possible performance, particularly on mobile devices.

Motion Path

The MotionPathPlugin (requires installation) allows you to animate elements along a path defined by an SVG path data string or a Bézier curve. This opens up possibilities for creating complex movement animations.

// Assuming you've installed and imported the MotionPathPlugin
gsap.to(".element", {
  duration: 2,
  motionPath: {
    path: "#myPath", // The ID of your SVG path element
    align: true, // Aligns the element to the path's tangent
    alignOrigin: [0.5, 0.5], // Center of the element
  },
});

This example animates the .element along the SVG path with the ID #myPath. The align property ensures the element rotates to follow the path. The alignOrigin property adjusts the alignment point within the animated element.

ScrollTrigger Integration

ScrollTrigger (requires installation) integrates GSAP with the browser’s scroll events. This lets you create animations that trigger based on scroll position, providing powerful control over scroll-based interactions.

// Assuming you've installed and imported ScrollTrigger
ScrollTrigger.create({
  trigger: ".element",
  start: "top 80%", // Animation starts when the element's top is 80% from the top of the viewport
  end: "bottom top", // Animation ends when the element's bottom reaches the top of the viewport
  animation: gsap.to(".element", { y: 100, duration: 1 }), // Animation to apply
});

This code makes an element animate when it enters the viewport, demonstrating the basic setup of ScrollTrigger, a powerful tool for creating complex scroll-based animations. ScrollTrigger allows for intricate control over animation start and end points, providing smooth integration with user scrolling behavior.

DrawSVGPlugin

DrawSVGPlugin (requires installation) provides specialized functionality for animating SVG paths. This plugin allows you to animate the drawing of SVG paths, creating drawing effects.

// Assuming you've installed and imported DrawSVGPlugin
gsap.to(".mySVGPath", {
  duration: 2,
  drawSVG: 1, // Draw the entire path
});

This will animate the drawing of the SVG path element with the class .mySVGPath, providing a dynamic drawing effect. The drawSVG property controls how the path is drawn (0 for beginning, 1 for ending).

Physics Plugins

GSAP offers plugins that add physics-based animations. These plugins allow you to simulate realistic physical motion, making animations feel more natural and dynamic. Examples include plugins enabling the simulation of springy or bouncy movements.

Custom Plugins

You can create custom GSAP plugins to extend its functionality. This is advanced but lets you integrate GSAP with other libraries or frameworks, or add specific animation capabilities not directly available in GSAP’s core. Creating a plugin involves extending GSAP’s API, adding new functionalities and properties for more specialized animation control. Consult GSAP’s plugin documentation for detailed guidance on plugin development.

These special properties and plugins greatly extend the capabilities of GSAP, enabling the creation of highly sophisticated, performant, and visually stunning animations. They are key for creating complex and interactive animations beyond what is possible with only core GSAP functionalities. Remember to install and import plugins before using them in your code.

GSAP Plugins: Extending Animation Capabilities

GSAP’s core functionality is incredibly powerful, but its true potential is unleashed through its extensive plugin system. Plugins add specialized animation capabilities, significantly broadening GSAP’s range of applications.

Plugin Architecture

GSAP plugins follow a consistent architecture. They typically extend GSAP’s core functionality by:

  1. Registering themselves: Plugins register themselves with GSAP, making their features available.
  2. Providing new properties: Plugins introduce new properties that can be used within gsap.to(), gsap.from(), gsap.fromTo(), and Timeline tweens.
  3. Handling complex animations: Plugins often handle more intricate animations that are difficult or inefficient to manage directly with core GSAP functions.
  4. Extending data parsing: Some plugins extend GSAP’s ability to parse and interpret specific data types within animation parameters.

Installing Plugins

GSAP plugins are typically installed using a package manager like npm or yarn, or via a CDN link.

npm install gsap-plugin-name  //or
yarn add gsap-plugin-name

After installation, you generally need to register the plugin with GSAP. The exact method varies slightly depending on the plugin, but usually involves a simple registration call:

//Example (Check plugin documentation for specifics):
gsap.registerPlugin(MyPlugin); //MyPlugin is the plugin name

Using Plugins

Once a plugin is installed and registered, its properties can be used directly within GSAP’s tweening functions:

// Example using a hypothetical plugin "MyPlugin"
gsap.to(".element", 1, {
  x: 100,
  myPluginProperty: "myValue", //Using plugin-specific property
});

Refer to the individual plugin’s documentation for details on its specific properties and usage.

Creating Custom Plugins

Creating custom plugins allows extending GSAP’s capabilities to suit your specific needs. This is an advanced topic requiring a solid understanding of JavaScript and GSAP’s architecture. GSAP’s documentation provides a detailed guide on plugin development. Creating a custom plugin involves defining a class that extends GSAP’s plugin structure and adding your custom logic within that structure.

List of Available Plugins

GreenSock provides a wide variety of plugins. The official GSAP website maintains a comprehensive list of available plugins, including descriptions of their functionalities. Some commonly used plugins include:

Refer to the official GSAP website for the most up-to-date list of available plugins and their detailed documentation. Each plugin’s documentation will specify installation instructions, registration methods, and how to use its unique features. Using plugins empowers you to implement highly tailored and effective animations for your projects.

GSAP Best Practices for Efficient and Maintainable Animations

This section covers best practices for writing efficient, maintainable, and debuggable GSAP code.

Performance Optimization

GSAP is already highly optimized, but certain practices can further improve performance, especially in complex animations or on lower-powered devices:

Code Structure and Organization

Well-structured code improves readability, maintainability, and debuggability:

Debugging Techniques

Debugging complex animations can be challenging:

Working with External Libraries

When integrating GSAP with other libraries (e.g., React, Vue, or Three.js), follow these guidelines:

By following these best practices, you can create efficient, maintainable, and high-performance GSAP animations. Remember that careful planning and structured code are essential for managing complex animation projects effectively. Always refer to the official GSAP documentation for the latest best practices and optimization recommendations.

Troubleshooting GSAP Animations

This section addresses common issues encountered when working with GSAP and provides resources for resolving them.

Common Errors and Solutions

Here are some frequently encountered errors and their solutions:

Debugging Tools

Several tools aid in debugging GSAP animations:

Community Resources

If you’re unable to resolve an issue, several resources can assist:

Remember to provide clear and concise information when seeking help, including relevant code snippets, error messages, and a description of the expected behavior versus the actual behavior. The more details you provide, the better equipped others are to assist you.

Appendix

This appendix provides supplementary information for working with GSAP.

Glossary of Terms

API Reference

A comprehensive API reference is available on the official GreenSock website. This reference provides detailed information on all GSAP classes, methods, and properties, including parameters, return values, and usage examples. It’s an essential resource for understanding and utilizing the full potential of GSAP. The documentation is well-structured and searchable, making it easy to find the specific information you need.

Changelog

The changelog for GSAP is also accessible on the official GreenSock website. This document details all changes, bug fixes, new features, and updates released in each version of GSAP. Checking the changelog is important for understanding updates and compatibility issues between different versions. Keeping up-to-date with the changelog ensures you are aware of improvements, potential breaking changes, and new features that could enhance your animation development process. The changelog is usually organized chronologically, clearly indicating the version number and a summary of changes for each release.