2011-09-16 16 views
18

Un problema común cuando se trabaja con tipografía en HTML/CSS es algo que llamamos "horunge" en sueco ("widow" en inglés).JavaScript para evitar viudas

Qué es:

Digamos que usted tiene una caja con un ancho de 200 píxeles y con el texto "Me encanta typograpy mucho". Ahora se rompe el texto y se convierte en:

Me encanta la tipografía muy
mucho

Como diseñador no quiero un hijo de puta palabra (palabra/fila). Si se trataba de un documento/PDF, etc. Me volvería a romper la palabra antes de mucho y tener este aspecto:

Me encanta la tipografía
mucho

que se ve mucho mejor.

¿Puedo resolver esto con una regla CSS o con un javascript? La regla debería ser nunca dejar que una palabra permanezca vacía en una fila.

Sé que puede ser resuelto mediante la adición de un <br /> pero eso no es una solución que funciona con anchos dinámicos, contenido de la fuente, diferentes traducciones, problemas de representación de fuentes navegador etc.

actualización (solución) solucioné mi problema con este plugin de jquery: http://matthewlein.com/widowfix/

+0

Viudas ... Palabra bastarda ... ¡Me encanta el sueco! :) – rybo111

Respuesta

0

También hay propiedades de viudas y huérfanos de CSS: ver about.com article.

No

seguro acerca de la compatibilidad con exploradores ...

EDIT: más información acerca de la aplicación WebKit aquí: https://bugs.webkit.org/buglist.cgi?quicksearch=orphans.

+0

Esos dos solo funcionan para imprimir http://www.w3.org/TR/CSS21/page.html#break-inside – c69

+0

@ c69 Tienes razón. ¿Alguien sabe de algún plan para agregar esto para medios no paginados? No puedo encontrar nada en la web. Sería genial ver algunas herramientas de tipografía más como esta (y flujo y runaround) implementadas para medios de pantalla. –

+0

http://www.w3.org/TR/css3-regions/#best-region-breaks - algunas de estas cosas funcionan en IE10 pp3, y también funcionarán en el nuevo WebKit. – c69

0

Hice un poco script here, con la ayuda de this function para encontrar la altura de la línea.

Es solo un enfoque, puede que funcione o no, no tuvo tiempo de probarse.

A partir de ahora, text_element debe ser un objeto jQuery.

function avoidBastardWord(text_element) 
{ 
    var string = text_element.text(); 
    var parent = text_element.parent(); 
    var parent_width = parent.width(); 
    var parent_height = parent.height(); 

    // determine how many lines the text is split into 
    var lines = parent_height/getLineHeight(text_element.parent()[0]); 

    // if the text element width is less than the parent width, 
    // there may be a widow 
    if (text_element.width() < parent_width) 
    { 
     // find the last word of the entire text 
     var last_word = text_element.text().split(' ').pop(); 

     // remove it from our text, creating a temporary string 
     var temp_string = string.substring(0, string.length - last_word.length - 1); 

     // set the new one-word-less text string into our element 
     text_element.text(temp_string); 

     // check lines again with this new text with one word less 
     var new_lines = parent.height()/getLineHeight(text_element.parent()[0]); 

     // if now there are less lines, it means that word was a widow 
     if (new_lines != lines) 
     { 
      // separate each word 
      temp_string = string.split(' '); 

      // put a space before the second word from the last 
      // (the one before the widow word) 
      temp_string[ temp_string.length - 2 ] = '<br>' + temp_string[ temp_string.length - 2 ] ; 

      // recreate the string again 
      temp_string = temp_string.join(' '); 

      // our element html becomes the string 
      text_element.html(temp_string); 
     } 
     else 
     { 
      // put back the original text into the element 
      text_element.text(string); 
     } 

    } 

} 

Los diferentes navegadores tienen configuraciones de fuente diferentes. Intenta jugar un poco para ver las diferencias. Lo probé en IE8 y Opera, modificando la cadena cada vez y parecía funcionar bien.

Me gustaría escuchar algunos comentarios y mejorar porque creo que puede ser útil de todos modos.

¡Solo juegue con él! :)

0

manualmente, que podría reemplazar el espacio intermedio con &nbsp;

He estado buscando maneras de agregar dinámicamente en.Encontré algunos, pero no he podido hacerlo funcionar yo mismo.

+0

que debería estar con "& n b s p;" (sin espacios entre ellos, y espacio sin interrupciones) – matt

+0

envuelve el código entre dos símbolos para permitir el formato correcto – Luca

6

Una solución simple de jQuery/regrex podría verse como la siguiente, si agrega la clase "noWidows" a la etiqueta de cualquier elemento que contenga texto que le preocupe.

Tales como:

<p class="noWidows">This is a very important body of text.</p> 

y luego usar este script:

$('.noWidows').each(function(i,d){ 
    $(d).html($(d).text().replace(/\s(?=[^\s]*$)/g, "&nbsp;")) 
}); 

Esto utiliza expresiones regulares para buscar y reemplazar el último espacio en la cadena con un carácter de no separación. Lo que significa que las dos últimas palabras serán forzadas a la misma línea. Es una buena solución si tiene espacio al final de la línea porque esto podría hacer que el texto se ejecute fuera de un elemento con un ancho fijo, o si no se lo repara, el elemento se agrandará.

+0

Sería bueno si esto no rompiera html dentro de dichos elementos. – ShayneStatzell

2

Solo quería agregar a esta página, ya que me ayudó mucho.

Si tiene (viudas) en realidad deberían ser huérfanos, ya que las viudas son palabras sueltas que aparecen en la página siguiente y no palabras sueltas en una nueva línea.

Trabajar con códigos postales como "N12 5GG" dará como resultado que el código postal completo esté en una nueva línea, pero aún así se clasificará como huérfano, por lo que se puede solucionar este problema. (Cambiado la clase de "noWidow2" para que pueda utilizar las dos versiones.

123 Some_road, Some_town, N12 5GG

$('.noWidows2').each(function(i,d){ 
    var value="&nbsp;" 
    $(d).html($(d).text().replace(/\s(?=[^\s]*$)/g, value).replace(/\s(?=[^\s]*$)/g, value)); 
}); 

Esto dará lugar son los 3 últimos espacios en blanco Estar en una nueva línea juntos haciendo el trabajos cuestión código postal.

resultado final

123 Some_road, 
Some_town, N12 5GG 
0

$('span').each(function() { 
 
    var w = this.textContent.split(" "); 
 
    if (w.length > 1) { 
 
    w[w.length - 2] += "&nbsp;" + w[w.length - 1]; 
 
    w.pop(); 
 
    this.innerHTML = (w.join(" ")); 
 
    } 
 
});
#foo { 
 
    width: 124px; 
 
    border: 1px solid #ccc; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="foo"> 
 
    <span class="orphan">hello there I am a string really really long, I wonder how many lines I have</span> 
 
</div>

Cuestiones relacionadas