2010-12-04 12 views
20

¿Existe alguna manera de justificar automáticamente las palabras utilizando espacios entre letras, cada una en su fila, a un ancho definido, utilizando CSS?Texto CSS justificar con espaciado entre letras

Por ejemplo, "Algo como esto" se vería, así, algo como esto:

"Something like this" would look something like this

¿Hay una manera no intrusiva para aplicar tales estilo a mi texto? Creo que CSS puro no tiene esta opción (al menos no con versiones CSS anteriores a 3, CSS3 parece tener una propiedad text-justify, pero aún no es bien compatible), por lo que las soluciones js también estarían bien.

+0

¿Está dispuesto a emplear cualquier biblioteca particular, JS para lograr esto, o solamente de vainilla JS? –

+0

@David: se preferiría jQuery, pero es una tarea bastante simple, por lo que puede trasladarse entre marcos sin problemas IMO. – Groo

Respuesta

8

Aquí hay un script que puede hacerlo. No es bonito, pero tal vez puedas hackearlo para satisfacer tus necesidades. (Actualizado para manejar el cambio de tamaño)

<html> 
<head> 
<style> 
#character_justify { 
    position: relative; 
    width: 40%; 
    border: 1px solid red; 
    font-size: 32pt; 
    margin: 0; 
    padding: 0; 
} 
#character_justify * { 
    margin: 0; 
    padding: 0; 
    border: none; 
} 
</style> 
<script> 
function SplitText(node) 
{ 
    var text = node.nodeValue.replace(/^\s*|\s(?=\s)|\s*$/g, ""); 

    for(var i = 0; i < text.length; i++) 
    { 
     var letter = document.createElement("span"); 
     letter.style.display = "inline-block"; 
     letter.style.position = "absolute"; 
     letter.appendChild(document.createTextNode(text.charAt(i))); 
     node.parentNode.insertBefore(letter, node); 

     var positionRatio = i/(text.length - 1); 
     var textWidth = letter.clientWidth; 

     var indent = 100 * positionRatio; 
     var offset = -textWidth * positionRatio; 
     letter.style.left = indent + "%"; 
     letter.style.marginLeft = offset + "px"; 

     //console.log("Letter ", text[i], ", Index ", i, ", Width ", textWidth, ", Indent ", indent, ", Offset ", offset); 
    } 

    node.parentNode.removeChild(node); 
} 

function Justify() 
{ 
    var TEXT_NODE = 3; 
    var elem = document.getElementById("character_justify"); 
    elem = elem.firstChild; 

    while(elem) 
    { 
     var nextElem = elem.nextSibling; 

     if(elem.nodeType == TEXT_NODE) 
      SplitText(elem); 

     elem = nextElem; 
    } 
} 

</script> 
</head> 
<body onload="Justify()"> 
<p id="character_justify"> 
Something<br/> 
Like<br/> 
This 
</p> 
</body> 
+1

Gracias, funciona genial. Para aquellos que estén interesados, este script encuentra un div por su Id, inserta un div por separado para cada carácter en guiones calculados, y luego elimina el div inicial. – Groo

+0

También hay un ligero problema de que los caracteres se colocan a intervalos regulares en lugar de tener espaciado fijo entre ellos. Esto parece extraño cuando tiene caracteres de ancho diferente (como "WiW", por ejemplo). Me preguntaba si podía simplemente agregar espacios entre letras y usar la justificación del navegador, ya que cada carácter era una palabra, pero no se justifican si hay '
' al final. ¿Tienes una sugerencia? – Groo

+0

Ok, se olvidó de esto, lo aceptaré ahora. No lo usé al final, pero está lo suficientemente cerca. – Groo

-1

¿Qué pasa con text-align: justify? Creo que podría malinterpretar tu pregunta.

+12

@CC: no justifica palabras sueltas al aumentar el espaciado entre letras. – Groo

+0

Además, text-align solo es compatible con IE en este momento. – theannouncer

4

Sé que este es un tema antiguo, pero me enfrenté a esto la otra noche. Y encontró una solución adecuada usando tablas.

Cada letra se pondrá en un <td> </td> Sé que parece tedioso, pero si quieres hacer esto, sería por una palabra o dos, ¿verdad? O siempre puedes usar JS para llenarlo si es demasiado. Sin embargo, esto es solo CSS y una solución muy versátil.

Al utilizar el espaciado entre letras, las letras se distribuyen correctamente. Deberías jugar con eso, dependiendo del ancho de la mesa.

#justify { 
    width: 300px; 
    letter-spacing: 0.5em; 
} 
<table id="justify"> 
    <tbody> 
    <tr> 
     <td>J</td> 
     <td>U</td> 
     <td>S</td> 
     <td>T</td> 
     <td>I</td> 
     <td>F</td> 
     <td>Y</td> 
    </tr> 
    </tbody> 
</table> 

See the example here

Crossbrowser segura, prácticamente nada se diferencian. Es solo CSS.

Lo usé en My website que está en inglés y español. el subtítulo debajo de mi nombre en español tiene una letra adicional y saldrá del ancho. Usando las tablas explicadas anteriormente, se distribuye automáticamente al mismo ancho. Al espaciarlo manualmente, tuve que definir una condición completa para cada idioma.

+1

Cancelando su voto ya que tiene un punto: esto es generalmente para una situación de alcance limitado. Además, excavo tu sitio web. Pero supongo que si fuera a "ir nuclear" (dividir físicamente las letras), igual usaría flexbox o bloque en línea. Las tablas llevan consigo otras rarezas de diseño (es decir, no se comportan igual que otras cajas de nivel de bloque). – harpo

+0

Definitivamente la mejor y más limpia forma de hacerlo en mi opinión. Y sí, un guión fácil crearía y llenaría la tabla por usted. Mucho mejor que las otras opciones aquí. – ElDoRado1239

2

Aquí es otro abordaje utilizando un fragmento de jQuery que escribí para esta pregunta: Stretch text to fit width of div:

DEMO

HTML:

<div class="stretch">Something</div> 
<div class="stretch">Like</div> 
<div class="stretch">This</div> 

jQuery:

$.fn.strech_text = function() { 
    var elmt = $(this), 
     cont_width = elmt.width(), 
     txt = elmt.html(), 
     one_line = $('<span class="stretch_it">' + txt + '</span>'), 
     nb_char = elmt.text().length, 
     spacing = cont_width/nb_char, 
     txt_width; 

    elmt.html(one_line); 
    txt_width = one_line.width(); 

    if (txt_width < cont_width) { 
     var char_width = txt_width/nb_char, 
      ltr_spacing = spacing - char_width + (spacing - char_width)/nb_char; 

     one_line.css({ 
      'letter-spacing': ltr_spacing 
     }); 
    } else { 
     one_line.contents().unwrap(); 
     elmt.addClass('justify'); 
    } 
}; 


$(document).ready(function() { 
    $('.stretch').each(function() { 
     $(this).strech_text(); 
    }); 
}); 
+1

Simple, funcional y listo, ¡guau! – Fanky

0

De nuevo, sé que esto es REALMENTE viejo, pero ¿por qué no poner un espacio entre cada letra y luego alinear con el texto: justificar?Entonces cada letra sería considerada como una 'palabra' y justificada en consecuencia

+2

Eso funcionaría, sí, pero la pregunta era cómo hacerlo sin mezclar el marcado y la presentación. Las soluciones de este tipo son similares a usar tablas en lugar de css para el diseño de página, mientras que en este caso también pierde puntos de SEO porque los motores de búsqueda no los reconocerán como palabras completas. Se ha resuelto en CSS3. – Groo

2

Necesaria también, así que he incluido la técnica sugerida en un jquery-plugin fácil de usar que puede encontrar aquí: .

Utiliza el mismo procedimiento en su núcleo, y agrega algunas opciones para ajustar. Comentarios bienvenidos.

0

Una forma alternativa de manejar esto podría ser usar la unidad de tamaño "vw". Este tipo de unidad se puede usar en propiedades de tamaño de fuente y representa un porcentaje del ancho de la ventana.

Descargo de responsabilidad: No es exactamente lo que está buscando, pero no requiere secuencias de comandos. Ajusta el tamaño del texto, pero también se ampliará al ancho de su página.

Por ejemplo,

.heading { 
    font-size: 4vw; 
} 

hará que el ancho de un carácter en la corriente de la fuente 4% de la anchura de la ventana.

A continuación, puede utilizar las consultas de medios si desea bloquear el tamaño de fuente a un tamaño mínimo en función del ancho de la ventana.

@media only screen and (max-width: 768px) { 
    font-size: 2rem; 
} 

utilizar el inspector de navegador para jugar con la propiedad font-size y ajustar el valor de lo que tiene sentido para su aplicación.

La unidad "vw" funciona en IE9 +, iOS 8.3+ y Android 4.4+ y todos los demás navegadores mainstream. No me preocuparía demasiado la compatibilidad con dispositivos móviles, ya que puede utilizar las consultas de medios para establecer el tamaño correcto para estos dispositivos como se describe anteriormente.

http://caniuse.com/#feat=viewport-units

https://css-tricks.com/viewport-sized-typography/

unidades de ventanilla son una poderosa manera de escalar muchos aspectos diferentes de su sitio con poco código.

+0

Pero no creo que cambie el kerning? – Groo

+0

No. No es así. Es un enfoque ligeramente diferente. Está configurando el tamaño del texto para que se ajuste al contenedor. Luego, al cambiar el tamaño de la ventana, todo el bloque de texto se ajusta al ancho de la ventana. Definitivamente es un enfoque alternativo, y no una respuesta al 100% de la pregunta, pero aceptable si no es posible o no se desea un método de scripting. –

0

Acabo de crear una secuencia de comandos de JQuery a partir del enfoque Tony B de la tabla. Aquí está el JSFiddle https://jsfiddle.net/7tvuzkg3/7/

Este script crea una tabla con cada char en una fila. Esto funciona con la oración completa. No estoy seguro de que esto esté completamente optimizado.

justifyLetterSpacing("sentence"); 
 

 
function justifyLetterSpacing(divId) { 
 

 
\t // target element 
 
\t domWrapper = $('#' + divId).clone().html(''); 
 
\t // construct <td> 
 
\t $('#' + divId).contents().each(function(index){ 
 
     // store div id to td child elements class 
 
\t var tdClass = divId ; 
 
     // split text 
 
\t $textArray = $(this).text().split(''); 
 
     // insert each letters in a <td> 
 
\t for (var i = 0; i < $textArray.length; i++) { 
 
     // if it's a 'space', replace him by an 'html space' 
 
     if($textArray[i] == " ") { 
 
      $('<td>') 
 
       .addClass(tdClass) 
 
       .html("&nbsp;&nbsp;") 
 
       .appendTo(domWrapper); 
 
     }// if it's a char, add it 
 
     else{ 
 
      $('<td>') 
 
       .addClass(tdClass) 
 
       .text($textArray[i]) 
 
       .appendTo(domWrapper); 
 
     } 
 
\t } 
 
\t }); 
 
    // create table 
 
    table = 
 
    $("<table id='"+divId+"'/>").append( 
 
     $("<tbody>").append( 
 
      $("<tr>").append( 
 
       (domWrapper).children('td') 
 
      ) 
 
     ) 
 
    ); 
 
    // replace original div 
 
\t $('#' + divId).replaceWith(table); 
 
} \t
#sentence { 
 
    width : 100%; 
 
    background-color : #000; 
 
    color : #fff; 
 
    padding : 1rem; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="sentence">LOREM IPSUM DOLOR</div>

3

El css única solución es text-justify: distributehttps://www.w3.org/TR/css-text-3/#text-justify pero el apoyo es aún muy pobre.

Un pequeño experimento usando text-align-last: justify y agregando espacios entre las letras.

div{ 
 
\t display:inline-block; 
 
\t text-align: justify; 
 
\t text-align-last: justify; 
 
\t letter-spacing: -0.1em; 
 
}
<div> 
 
S o m e t h i n g<br> 
 
l i k e<br> 
 
t h i s 
 
</div>

Cuestiones relacionadas