# How to Handle Unit Conversions in Anime.js Animations

> Master unit conversions in Anime.js animations. Discover how anime.js automatically normalizes CSS units for seamless animation across different values and lengths. Learn more.

- Repository: [Julian Garnier/anime](https://github.com/juliangarnier/anime)
- Tags: how-to-guide
- Published: 2026-03-04

---

**Anime.js automatically normalizes CSS units through a three-stage pipeline—parsing, conversion, and application—using the `convertValueUnit` function in [`src/core/units.js`](https://github.com/juliangarnier/anime/blob/main/src/core/units.js) to handle angles via mathematical lookup tables and lengths via temporary DOM measurements, with built-in caching to avoid redundant calculations.**

Anime.js (juliangarnier/anime) eliminates the friction of mixing CSS units in animations by converting values internally before interpolation begins. Whether you are tweening from `em` to `px`, `deg` to `turn`, or querying computed styles in specific units, the library ensures numeric values share a common baseline. This article explains the technical implementation of unit handling based on the actual source code.

## The Unit Conversion Pipeline

The conversion process follows a strict three-step architecture that separates concerns between value parsing, unit mathematics, and animation application.

### Parsing Values with `decomposeRawValue`

Located in [`src/core/values.js`](https://github.com/juliangarnier/anime/blob/main/src/core/values.js), the `decomposeRawValue` function inspects raw CSS values and breaks them into structured objects. It detects numbers, units, relative operators (`+=`, `-=`), colors, and complex values, producing a decomposed object with the shape `{t, n, u, …}` where `t` represents the value type, `n` the numeric component, and `u` the unit string.

### Converting Units via `convertValueUnit`

The core algorithm resides in [`src/core/units.js`](https://github.com/juliangarnier/anime/blob/main/src/core/units.js). The `convertValueUnit` function accepts an element, a decomposed value, a target unit, and an optional force flag. It returns a new decomposed value with the numeric part converted to the requested unit.

```javascript
// src/core/units.js
export const convertValueUnit = (el, decomposedValue, unit, force = false) => {
  const currentUnit = decomposedValue.u;
  const currentNumber = decomposedValue.n;

  // Early exit if already in target unit
  if (decomposedValue.t === valueTypes.UNIT && currentUnit === unit) {
    return decomposedValue;
  }

  const cachedKey = currentNumber + currentUnit + unit;
  const cached = convertedValuesCache[cachedKey];
  if (!isUnd(cached) && !force) {
    decomposedValue.n = cached;
  } else {
    let convertedValue;
    // Angle units: deg, rad, turn
    if (currentUnit in angleUnitsMap) {
      convertedValue = currentNumber * angleUnitsMap[currentUnit] / angleUnitsMap[unit];
    } else {
      // Length units: px, em, rem, cm, etc.
      const baseline = 100;
      const tempEl = el.cloneNode();
      const parent = el.parentNode && (el.parentNode !== doc) ? el.parentNode : doc.body;
      parent.appendChild(tempEl);
      const style = tempEl.style;
      style.width = baseline + currentUnit;
      const curWidth = tempEl.offsetWidth || baseline;
      style.width = baseline + unit;
      const newWidth = tempEl.offsetWidth || baseline;
      const factor = curWidth / newWidth;
      parent.removeChild(tempEl);
      convertedValue = factor * currentNumber;
    }
    decomposedValue.n = convertedValue;
    convertedValuesCache[cachedKey] = convertedValue;
  }

  decomposedValue.t = valueTypes.UNIT;
  decomposedValue.u = unit;
  return decomposedValue;
}

```

### Applying Conversions During Tween Creation

In [`src/animation/animation.js`](https://github.com/juliangarnier/anime/blob/main/src/animation/animation.js), the tween preparation logic ensures that `from` and `to` values share the same unit before interpolation begins. If the source value carries a unit different from the target, the engine invokes `convertValueUnit` to align them under a single `_unit` property.

## How `convertValueUnit` Handles Different Unit Types

The function implements two distinct strategies based on the unit category.

**Angle Conversion via Lookup Table**

For angular units (`deg`, `rad`, `turn`), Anime.js uses a constant map: `angleUnitsMap = { deg: 1, rad: 180/π, turn: 360 }`. Converting between any two angle units requires only multiplication and division using these ratios, avoiding DOM manipulation entirely.

**Length Conversion via DOM Measurement**

For CSS length units (`px`, `em`, `rem`, `cm`, `in`, etc.), the function creates a hidden clone of the target element, sets its width to a baseline value (100) in the source unit, measures the pixel width via `offsetWidth`, then repeats the process in the target unit. The ratio of these two measurements yields the conversion factor. Results are memoized in `convertedValuesCache` using a key pattern of `number + sourceUnit + targetUnit` to prevent expensive reflows on subsequent calls.

## Practical Implementation Examples

### Querying CSS Properties in Specific Units

Use `utils.get` from [`src/utils/target.js`](https://github.com/juliangarnier/anime/blob/main/src/utils/target.js) to retrieve a computed style converted to any supported unit. The function automatically decomposes the original value and calls `convertValueUnit` when you supply a unit argument.

```javascript
import { utils } from 'animejs';

// Element has width: 2em with font-size: 16px
const widthInPx = utils.get('#box', 'width', 'px');
// Returns: "32px"

```

### Animating Between Angle Units

Anime.js normalizes angle values automatically, allowing you to mix units in keyframes.

```javascript
anime({
  targets: '#rotor',
  rotate: ['360deg', '.5turn'], // 360deg converts to 1turn internally
  duration: 800,
  easing: 'linear'
});

```

Internally, `360deg` converts to `1turn` using the `angleUnitsMap`, ensuring the tween interpolates from 1.0 to 0.5 rather than attempting to animate between incompatible strings.

### Manual Length Unit Conversion

Access `convertValueUnit` directly for programmatic unit math without animation.

```javascript
import { convertValueUnit } from 'animejs/lib/utils/units.js';

const el = document.createElement('div');
document.body.appendChild(el);

const decomposed = { t: valueTypes.UNIT, n: 5, u: 'cm' };
const result = convertValueUnit(el, decomposed, 'px');

console.log(`${result.n}${result.u}`); // e.g., "188.976px"
document.body.removeChild(el);

```

### Automatic Unit Inheritance

When you omit units in subsequent calls, Anime.js preserves the original unit from the element's inline style.

```javascript
utils.set('#box', { width: '1em' }); // font-size: 20px
utils.set('#box', { width: 2 });     // Infers "em" unit
utils.get('#box', 'width', 'px');    // Returns "40px"

```

## Summary

- **Parsing**: `decomposeRawValue` in [`src/core/values.js`](https://github.com/juliangarnier/anime/blob/main/src/core/values.js) splits CSS values into typed objects containing numeric and unit components.
- **Conversion**: `convertValueUnit` in [`src/core/units.js`](https://github.com/juliangarnier/anime/blob/main/src/core/units.js) handles angles via `angleUnitsMap` (mathematical ratios) and lengths via temporary DOM element measurement (baseline 100 technique).
- **Caching**: Conversion results are stored in `convertedValuesCache` keyed by value, source unit, and target unit to minimize reflow costs.
- **Application**: Tween creation in [`src/animation/animation.js`](https://github.com/juliangarnier/anime/blob/main/src/animation/animation.js) automatically aligns units between from/to values, while `utils.get` in [`src/utils/target.js`](https://github.com/juliangarnier/anime/blob/main/src/utils/target.js) exposes unit conversion for property queries.

## Frequently Asked Questions

### How does Anime.js convert between angle units like deg and rad?

Anime.js uses a lookup table defined as `angleUnitsMap = { deg: 1, rad: 180/π, turn: 360 }`. When converting between angle units, the `convertValueUnit` function multiplies the source number by the source unit's map value and divides by the target unit's map value, producing mathematically accurate results without DOM manipulation.

### Why does Anime.js create a temporary DOM element for length conversions?

CSS length units (`em`, `rem`, `cm`, `in`) are context-dependent based on font sizes or viewport settings. To obtain accurate conversion factors, Anime.js clones the target element, appends it to the DOM, sets a baseline width of 100 in both the source and target units, and measures the resulting pixel widths via `offsetWidth`. The ratio between these measurements provides the precise conversion factor for that specific rendering context.

### Can I force a specific unit when querying a CSS property?

Yes. The `utils.get` function accepts a third argument specifying the desired unit. When provided, the function decomposes the computed style and passes it through `convertValueUnit` before returning the rounded string value, allowing you to retrieve dimensions in `px` even if the element is styled in `em` or `rem`.

### Does Anime.js cache unit conversion results for performance?

Yes. The `convertValueUnit` function maintains a `convertedValuesCache` object that stores results using a composite key of `number + sourceUnit + targetUnit`. Before performing any DOM measurement or calculation, the function checks this cache, significantly reducing reflow costs when the same conversion is requested multiple times during an animation sequence.