JSFiddle - React, Tailwind, and code Playground

by Chris Ball

HTML

<ul class="nav-list">
	<li><a href="#"><span>Link One</span></a></li>
	<li><a href="#"><span>Bit of a Longer Link</span></a></li>
	<li><a href="#"><span>Extraordinary Verboseness Inherent in a Text</span></a></li>
	<li><a href="#"><span>Something</span></a></li>
	<li><a href="#"><span>Blah Fucking Blah</span></a></li>
</ul>

SCSS

ul {
	font-size: 13px;
	float: right;
	font-family: monospace;
	list-style-type: none;
	text-align: right;
}
li {
	max-width: 15em;
	max-width: 15ch;
	padding: 1em;
}
a {
	display: block;
	max-width: 15em;
	max-width: 15ch;
	text-decoration: none;
	&:hover span:after {
		transform: scaleX(1);
	}
}
span{
	display: inline-block;
	position: relative;
	&:after {
		background: yellow;
		bottom: 0;
		content: '';
		display: block;
		left: 0;
		position: absolute;
		right: 0;
		top: 50%;
		transform: scaleX(0);
		transition: transform 500ms;
		transform-origin: bottom left;
		z-index: -1;
	}
}

JavaScript

var list = $('.nav-list').eq(0);

var addSpans = function( string, limit ){
	// Split string into component words and spaces
	// Init the current string length, contents and array container
	var splitString = string[0].innerText.split(/(\s+)/),
		currentLength = 0,
		currentString = '',
		stringArray = [];
	for( var i = 0; i < splitString.length; i++ ){
		currentLength += splitString[i].length;
		// Remove leading whitespace
		if( currentString === ' ' ){
			currentString = '';
		}
		// When the limit is exceeded
		// And it's a single word, push it straight in
		// Or if it's a collection, add current iteration and push
		// THen reset
		if( currentLength > limit ){
			if( currentString === '' ){
				stringArray.push( splitString[i] );
			} else {
				currentString += splitString[i];
				stringArray.push( currentString );
			}
			currentLength = 0;
			currentString = '';
		// If uder the limit, continue adding
		} else {
			currentString += splitString[i];
			if( i == splitString.length - 1 ){
				stringArray.push( currentString );
			}
		}
	}
	var output = '<span>' + stringArray.join('</span><span>') + '</span>';
	return output;
}

var setLinkSpans = function(){
	// Setup constants
	var li = list.find('li:first'),
		maxWidth = parseInt( li.css('max-width') ),
		fontSize = parseInt( li.css('font-size') ),
		maxWidthInEms = ( maxWidth / fontSize );
	list.find('a').each(function(){
		var $this = $(this),
			linkLength = $this.text().length;
		if( linkLength > maxWidthInEms ){
			$this.html( addSpans( $this, maxWidthInEms ) );
		}
	});
}
setLinkSpans();