Almost every software timer follows this rule (even ones in the kernel) - "Interval timers / Thread Sleep guarantee that the amount of time waited is at least this long, it doesn't guarantee that it is exactly this long.
As seanalltogether mentions, timers are run at the beginning of the render loop => "Run timers, layout page, render page, repeat". If you're busy doing stuff in #2 or #3 (or if your timer handler takes forever), you're not running #1.
Similar to many gui frameworks you have a run loop that processes an event pool and a render sequence over and over and over. Events are queued and dispatched into the event pool as the browser receives them, followed by dom updates being processed in the render step. However this isn't always true and many javascript code blocks can force an immediate render(Text is deferred, canvas is immediate, not sure about css).
For this reason your event pool can be delayed significantly while waiting for rendering to complete.
As seanalltogether mentions, timers are run at the beginning of the render loop => "Run timers, layout page, render page, repeat". If you're busy doing stuff in #2 or #3 (or if your timer handler takes forever), you're not running #1.