2011-09-16 22 views
18

Powszechnym problemem przy pracy z typografią w HTML/CSS jest coś, co nazywamy "horunge" po szwedzku ("widow" w języku angielskim).JavaScript, aby uniknąć wdów

Co to jest:

Powiedzmy masz pudełko o szerokości 200px i z tekstem „I love typograpy bardzo dużo”. Teraz przerwy tekstowe i staje się:

Kocham typografii bardzo
dużo

Jako projektant nie chcę bękarta słowa (jedno słowo/wiersz). Jeśli był to dokument/PDF itd. Chciałbym złamać słowo przed bardzo i wyglądać tak:

Kocham typografii
bardzo dużo

która wygląda o wiele lepiej.

Czy mogę rozwiązać ten problem z regułą CSS lub z javascript? Zasada powinna polegać na tym, aby słowo nie było puste z rzędu.

wiem, może być rozwiązany poprzez dodanie <br /> ale to nie jest rozwiązanie, które współpracuje z dynamicznymi szerokościach, treści paszowym, różnych tłumaczeń, czcionka przeglądarka kwestie renderingu itp

Update (roztwór) Rozwiązałem mój problem z tą wtyczką jquery: http://matthewlein.com/widowfix/

+0

Wdowy ... Słowo draniu ... Uwielbiam szwedzkiego! :) – rybo111

Odpowiedz

0

Istnieją również wdowy CSS i właściwości sierot: patrz about.com article.

Nie wiesz o wsparcie przeglądarki ...

EDIT: więcej informacji na temat realizacji WebKit tutaj: https://bugs.webkit.org/buglist.cgi?quicksearch=orphans.

+0

Te dwie tylko prace do drukowania http://www.w3.org/TR/CSS21/page.html#break-inside – c69

+0

@ c69 Masz rację. Ktoś wie o jakichkolwiek planach dodania tego do niestronicowanych mediów? Nie można znaleźć niczego w Internecie. Byłoby wspaniale widzieć więcej narzędzi typograficznych, takich jak ten (i przepływ i runaround) zaimplementowanych dla mediów ekranowych. –

+0

http://www.w3.org/TR/css3-regions/#best-region-breaks - niektóre z tych rzeczy działają w IE10 pp3, a także będą działać w nowej wersji WebKit. – c69

0

Zrobiłem mały script here, przy pomocy this function, aby znaleźć wysokość linii.

To tylko podejście, może, ale nie musi działać, nie ma czasu na pełne sprawdzenie.

Do tej pory text_element musi być obiektem 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); 
     } 

    } 

} 

Różne przeglądarki mają różne ustawienia czcionek. Spróbuj zagrać trochę, aby zobaczyć różnice. Testowałem go na IE8 i Opera, modyfikując ciąg za każdym razem i wydawało się, że działa dobrze.

Chciałbym usłyszeć pewne opinie i poprawić, ponieważ myślę, że i tak może się przydać.

Po prostu baw się tym! :)

0

ręcznie, można zastąpić przestrzeń pomiędzy z &nbsp;

Szukałem sposobów dynamicznie dodawać je.Znalazłem kilka, ale nie byłem w stanie zrobić tego samemu.

+0

, które powinno być z "& n b s p;" (bez spacji pomiędzy, i bez łamania przestrzeni) – matt

+0

zawiń kod pomiędzy dwoma 'symbolami, aby umożliwić właściwe formatowanie – Luca

6

Proste rozwiązanie jQuery/regrex może wyglądać następująco, jeśli dodasz klasę "noWidows" do znacznika dowolnego elementu zawierającego tekst, który Cię niepokoi.

Takich jak:

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

a następnie użyć tego skryptu:

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

używa regex znaleźć i zastąpić ostatniego miejsca w łańcuchu o charakterze non-breaking. Oznacza to, że dwa ostatnie słowa zostaną przymuszone na tę samą linię. To dobre rozwiązanie, jeśli masz wolną przestrzeń wokół końca linii, ponieważ może to spowodować, że tekst będzie działał poza elementem o stałej szerokości lub jeśli nie jest stały, spowoduje to, że element stanie się większy.

+0

Byłoby miło, gdyby to nie złamało html wewnątrz tych elementów. – ShayneStatzell

2

Chciałbym dodać tę stronę, ponieważ bardzo mi pomogło.

Jeśli masz (wdowy) w rzeczywistości powinieneś być sierotą, ponieważ wdowy to pojedyncze słowa, które wylądują na następnej stronie, a nie pojedyncze słowa w nowej linii.

Praca z kodami pocztowymi, takimi jak "N12 5GG" spowoduje, że pełny kod pocztowy będzie znajdować się w nowej linii razem, ale nadal będzie sklasyfikowany jako sierota, więc obejście jest takie. (Zmieniono klasę „noWidow2”, dzięki czemu można korzystać z obu wersji.

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)); 
}); 

Spowoduje to jest ostatnie 3 białe przestrzenie będące na nową linię razem czyniąc praca problem kod pocztowy.

Wynik końcowy

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>

Powiązane problemy