Changing
top
alters the geometry of the element. That means that it may affect the position or size of other elements on the page, both of which require the browser to perform layout operations. Once those layout operations have completed any damaged pixels will need to be painted and the page must then be composited together.
Changing
transform
does not trigger any geometry changes or painting, which is very good. This means that the operation can likely be carried out by the compositor thread with the help of the GPU.
While originally I'd only explored the scaleY()
transform, there's the translateY()
function. No idea why I didn't think to use that. Regardless, the change to use the more efficient method is trivial. Instead of:
#menu.js {
position: absolute;
top: calc(-1 * var(--items) * var(--item-height));
transition: top var(--duration) ease;
}
#menu.js-open {
top: var(--item-height);
}
use:
#menu.js {
transform: translateY(calc(-1 * var(--items) * var(--item-height)));
transition: transform var(--duration) ease;
}
#menu.js-open {
transform: translateY(var(--item-height));
}