The updating of the box-layout, a.k.a "reflow" can be triggered synchronously, and doesn't require a "full render".
You can see this answer for more details on the synchronicity of the rendering operations.
So in your case, you can directly get the new sizes of your elements right after you did your DOM update, because this size getting will itself trigger a reflow; it's not even necessary to use a MutationObserver.
const elem = document.getElementById('elem');
console.log('initial', elem.offsetHeight);
elem.querySelectorAll('p:not(.notme)').forEach(el=>el.remove());
// getting '.offsetHeight' triggers a reflow
console.log('after removing', elem.offsetHeight);
<div id="elem">
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p class="notme">Hello</p>
</div>
Though beware, triggering a reflow has some costs in terms of performance, so if you fear other things may also modify the DOM afterward, you may want to wait for the painting event-loop iteration, using requestAnimationFrame
before calling one of the methods that do trigger it.
const elem = document.getElementById('elem');
console.log('initial', elem.offsetHeight);
elem.querySelectorAll('p:not(.notme)').forEach(el=>el.remove());
// wait the painting frame in case other operations also modify the DOM
requestAnimationFrame(()=> {
console.log('after removing', elem.offsetHeight);
});
<div id="elem">
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p class="notme">Hello</p>
</div>
Ps: for the ones still interested in the Y of this XY problem, you can have a look at this Q/A which demonstrates the use of the upcoming requestPostAnimationFrame
and offers a monkey-patch for it.