JSFiddle - React, Tailwind, and code Playground
by joepenzo
HTML
<p class="split-text">Pusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nullam quis risus eget urna mollis ornare vel eu leo. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<h1 class="split-text">Husce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nullam quis risus eget urna mollis ornare vel eu leo. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</h1>
<div class="output"></div>
SCSS
* {
box-sizing: border-box;
}
span {
border: 1px solid red;
}
.split-text {
span {
display: inline-block;
}
}
TypeScript
function splitTextIntoSpansByWidth(element: HTMLElement): void {
if (!element) return;
const text = element.textContent || '';
const len = text.length;
const width = element.clientWidth;
const originalStyle = window.getComputedStyle(element);
const span = document.createElement('span');
span.textContent = 'abcdefghijklmnopqrstuvwxyz,.';
span.style.visibility = 'hidden';
span.style.display = 'inline-block';
span.style.whiteSpace = 'nowrap';
span.style.visibility = 'hidden';
span.style.position = 'absolute';
span.style.width = width;
span.style.whiteSpace = originalStyle.whiteSpace;
span.style.wordWrap = originalStyle.wordWrap;
span.style.font = originalStyle.font;
span.style.lineHeight = originalStyle.lineHeight;
document.body.appendChild(span);
const charWidth = span.clientWidth/span.textContent.length;
document.body.removeChild(span);
const charsPerRow = Math.floor(width / charWidth);
const breakingIndexes: number[] = [];
let gRowStart = 0;
let gRowEnd = charsPerRow;
while (gRowEnd < len) {
const rowEnd = text.substring(gRowStart, gRowEnd).lastIndexOf(' ');
breakingIndexes.push(gRowStart + rowEnd);
gRowStart = gRowStart + rowEnd + 1;
gRowEnd = gRowStart + charsPerRow;
}
const outputElement = document.querySelector('.output') as HTMLElement;
if (!outputElement) return;
let start = 0;
let newText = '';
for (let i = 0; i <= breakingIndexes.length; i++) {
newText += `<span>${text.substring(start, breakingIndexes[i])}</span>`;
start = breakingIndexes[i];
}
element.innerHTML = newText;
}
document.querySelectorAll('.split-text').forEach((element) => {
splitTextIntoSpansByWidth(element);
});