С трудом понял, что-же вам нужно, но, надеюсь, правильно:)
Идея в том, чтобы рекурсивно перебирать все ноды спана, считать длину содержимого каждой ноды, и добавлять её в первую часть пока пока не превышен лимит количества. В начале итерации лимит - половина от всего текста спана.
function aggregator (a, c, maxChars){
if (a[0].textContent.length > maxChars) {
a[1].appendChild(c)
} else if (c.children?.length > 0) {
const agg = spanParse(c, maxChars - a[0].textContent.length);
a[0].appendChild(agg[0])
if (agg[1]) {
a[1].appendChild(agg[1])
}
} else {
a[0].appendChild(c)
}
return a;
}
function spanParse(rootSpan, maxChars) {
const aggregated = [document.createElement('span'), document.createElement('span')]
return [...rootSpan.childNodes].reduce((a, c) => aggregator(a, c, maxChars), aggregated)
}
function split(elem) {
const r = spanParse(elem, elem.textContent.length / 2)
console.log(r[0].textContent.length, r[1].textContent.length)
}
split(document.getElementByTag('span'));
С тем кодом который в вопросе работать будет если span с текстом есть на странице. Если с какой-то другой разметкой будут ошибки, то нужно докрутить логики в aggregator.