cyber, потому что при получении offsetHeight перерисовывается страничка, поэтому работает. Это такой хак. И setTimeout тут не нужен.
Я сам так делаю:
var elem = document.createElement('div');
elem.className = 'transition';
document.body.appendChild(elem);
elem.clientHeight; //HACK - без него анимации не будет
elem.classList.add('show');