You're given an array of DOM element nodes, targets. Find the single deepest element that is an ancestor of all of them — their lowest common ancestor. Setting that one element to display: none would hide every target at once, and no element below it could do the same. Think of it as: what is the smallest box you can collapse that still swallows every item on the list?
function lowestHidingElement(targets: Element[]): Element | null;
targets is an array of element nodes that already live in a document. The return value is one element from those elements' shared ancestry (it may be one of the targets itself), or null when no single element contains them all.
// <ul id="list"><li id="a">a</li><li id="b">b</li></ul>
lowestHidingElement([a, b]);
// → <ul id="list"> (the shared parent — hiding it hides both li's)
// <div id="outer"><span id="inner">x</span></div>
lowestHidingElement([outer, inner]);
// → <div id="outer"> (outer is an ancestor of inner, so it's the answer)
lowestHidingElement([inner]);
// → <span id="inner"> (a lone target hides itself)
// two elements in completely separate trees
lowestHidingElement([nodeInTreeA, nodeInTreeB]);
// → null (no element contains both)
lowestHidingElement([el]) returns el. Hiding el hides el.null. If the elements don't all share at least one common ancestor, there is no single hiding element. An empty array also returns null.[a, b, c] and [c, a, b] produce the same result.Unlock the solution & editor
Runnable editor + tests
Solve in the browser with instant Jest feedback.
Detailed solutions
Walkthroughs, edge cases, and complexity notes.
Multi-framework variants
React, Vue, Vanilla, Angular — same question, different stacks.