JSFiddle - React, Tailwind, and code Playground

by mgibsonbr

HTML

<ul>
    <li>C</li>
    <li>C++</li>
    <li>Java</li>
    <li>PHP</li>
    <li>JavaScript</li>
    <li>Lisp</li>
    <li>Scheme</li>
    <li>Haskell</li>
    <li>Lua</li>
    <li>Python</li>
    <li>Ruby</li>
    <li>Delphi</li>
    <li>Cobol</li>
</ul>

CSS

ul {
    width: 500px;
    height: 350px;
    border: 1px solid red;
    margin: 0;
    text-align: center;
}

li {
    list-style: none;
    display: inline-block;
    font-size: 2em;
}

JavaScript

var larguraConteiner = 500;
var alturaConteiner = 350;

// Larguras e alturas
var palavras = [];
var larguraTotal = 0;
var alturaMaxima = 0;
$('li').each(function() {
    palavras.push({
        elemento:this,
        largura:this.clientWidth,
        altura:this.clientHeight
    });
    larguraTotal += this.clientWidth;
    alturaMaxima = Math.max(alturaMaxima, this.clientHeight);
});

// Distribuição harmoniosa
var linhas = 0;
do {
    linhas++;
    var horizontal = larguraTotal / linhas / larguraConteiner;
    var vertical = linhas * alturaMaxima / alturaConteiner;
} while ( vertical < horizontal*0.8 ); // Esse 0.8 é uma "folga"

// Distribuir as palavras pelas linhas
var distribuicao = [];
for ( var i = 0 ; i < linhas ; i++ )
    distribuicao.push({ palavras:[], larguraTotal:0 });
function minima() {
    var min = 0;
    for ( var i = 1 ; i < distribuicao.length ; i++ )
        if ( distribuicao[i].larguraTotal < distribuicao[min].larguraTotal )
            min = i;
    return distribuicao[min];
}

palavras.sort(function(a,b) { return b.largura - a.largura; });
for ( var i = 0 ; i < palavras.length ; i++ ) {
    var min = minima();
    min.palavras.push(palavras[i]);
    min.larguraTotal += palavras[i].largura;
}

// Colocar as linhas na tela
var alturaSobrando = alturaConteiner - linhas*alturaMaxima;
var alturaAntes = alturaSobrando / linhas / 2;
for ( var i = 0 ; i < distribuicao.length ; i++ ) {
    var larguraSobrando = larguraConteiner - distribuicao[i].larguraTotal;
    var larguraAntes = larguraSobrando / distribuicao[i].palavras.length / 2;
    
    var top = alturaAntes + i*(2*alturaAntes + alturaMaxima);
    var left = larguraAntes;
    for ( var t = 0 ; t < distribuicao[i].palavras.length ; t++ ) {
        var palavra = distribuicao[i].palavras[t];
        $(palavra.elemento).css({
            position: "absolute",
            top: top,
            left: left
        });
        left += 2*larguraAntes + palavra.largura;
    }
}