Czy CSS może wymusić podział wiersza po każdym słowie w elemencie?


159

Tworzę witrynę wielojęzyczną, a właściciel pomaga mi w tłumaczeniach. Niektóre z wyświetlanych wyrażeń wymagają podziału wiersza, aby zachować styl witryny.

Niestety właściciel nie jest informatykiem, więc jeśli zobaczy foo<br />bar, jest szansa, że ​​w jakiś sposób zmodyfikuje dane podczas tłumaczenia.

Czy istnieje rozwiązanie CSS (poza zmianą szerokości), które można zastosować do elementu, który pęka po każdym słowie?

(Wiem, że mogę to zrobić w PHP, ale zastanawiam się, czy jest sprytna sztuczka, o której nie wiem w CSS, aby osiągnąć to samo, być może w funkcjach CJK.)

EDYTOWAĆ

Spróbuję sporządzić diagram, co się dzieje:

----------------          ----------------
| Short Word   |          | Gargantuan   |
|              |          | Word         |
----------------          ----------------

Długie słowo łamie się automatycznie, krótkie nie. Chcę, żeby wyglądało to tak:

----------------          ----------------
| Short        |          | Gargantuan   |
| Word         |          | Word         |
----------------          ----------------

2
W HTML elementy łamią się po każdym słowie, gdy wymaga tego szerokość danego elementu. Czy masz na myśli w słowach?
Paul D. Waite

@Paul - Nie, potrzebuję rozwiązania, które nie opiera się na ustalaniu szerokości. Problem w tym, że niektóre frazy są dłuższe i łamią się automatycznie (tak jak opisujesz), a niektóre frazy są krótsze i nie łamią się, co powoduje niespójną prezentację.
Ben

@Paul - Tak, to tak, jak dokładnie opisujesz. Naprawdę nie szkodzi układowi, ale może wyglądać lepiej.
Ben

można użyć odstępów między wyrazami, ale wpłynęłoby to na wszystkie słowa. Myślę, że nie można ominąć tych słów w elementach span.
meo

@meo - Na to wygląda, dzięki za myśl
Ben

Odpowiedzi:


261

Posługiwać się

.one-word-per-line {
    word-spacing: <parent-width>; 
}

.your-classname{
    width: min-intrinsic;
    width: -webkit-min-content;
    width: -moz-min-content;
    width: min-content;
    display: table-caption;
    display: -ms-grid;
    -ms-grid-columns: min-content;
}

gdzie <parent-width>jest szerokością elementu nadrzędnego (lub dowolną wysoką wartością, która nie mieści się w jednej linii). W ten sposób możesz być pewien, że po jednej literze występuje nawet koniec wiersza. Działa z Chrome / FF / Opera / IE7 + (a prawdopodobnie nawet IE6, ponieważ obsługuje również odstępy między wyrazami).


To zdecydowanie najlepsza odpowiedź imho
Hezad

31
@ToniMichelCaubet Odpowiedź jest naprawdę trudna do zinterpretowania, ale ma na myśli : .parent { word-spacing: 100px; }gdzie 100pxjest szerokość elementu nadrzędnego. Problem polega na tym, że to rozwiązanie nie działa, jeśli masz płynnego rodzica.
John Kurlak,

5
Po prostu ustaw bardzo wysoką wartość odstępów między wyrazami, na przykład, word-spacing: 100000pxa nie będziesz musiał się martwić, że rodzic będzie płynny pod względem szerokości. Ustawienie odstępu między wyrazami na 100% miałoby sens (byłoby to 100% szerokości rodzica), ale wartości wyrażone w procentach nie są obsługiwane dla tej właściwości css.
sboisse,

1
To było bardzo pomocne. Użyłem go w sytuacji responsywnej, gdzie przy jednej szerokości chcę zawijać tekst w tabulatorach, aby wszystkie były tej samej wysokości: word-spacing: 2em; a przy szerokości mobilnej chcę, aby były jednowierszowe:word-spacing: unset;
Czy

1
To jest niesamowite. Od wielu lat wielkie dzięki :)
Lucas Medina

124

Odpowiedź udzielona przez @HursVanBloob działa tylko z kontenerem nadrzędnym o stałej szerokości, ale zawodzi w przypadku kontenerów o płynnej szerokości .

Wypróbowałem wiele właściwości, ale nic nie działało zgodnie z oczekiwaniami. W końcu doszedłem do wniosku, że podanie word-spacingbardzo dużej wartości działa idealnie.

p { word-spacing: 9999999px; }

lub w nowoczesnych przeglądarkach możesz użyć vwjednostki CSS (szerokość wizualna w% rozmiaru ekranu).

p { word-spacing: 100vw; }

to właśnie spróbuję!
vaskort

To świetne rozwiązanie!
Joe Conlin

Całkowicie zrywa z & nbsp; chociaż.
Matt Fletcher,

2
Cóż, to nie działa dla mnie, co powoduje, że szerokość płynu w zbiorniku jest bardzo duża.
Onza

@Onza Czy możesz udostępnić łącze do skrzypiec, pokazujące Twój problem?
Deepak Yadav

37

Alternatywne rozwiązanie opisano w sekcji Oddziel zdanie do jednego słowa w wierszu , stosując display:table-caption;do elementu


To faktycznie grupuje słowa tylko na podstawie szerokości najdłuższego słowa.
James South

1
Chociaż może to grupować słowa w linii, działa naprawdę dobrze w wielu sytuacjach i nie wydaje się tak hakerskie, jak opcja ogromnych odstępów między wyrazami.
Dale

1
To jest ten, który działał idealnie dla mnie, fajny!
Matt Fletcher

1
To nie daje żadnego rezultatu
jafarbtech

32

Spróbuj użyć white-space: pre-line;. Tworzy znak końca wiersza w każdym miejscu, w którym pojawia się koniec wiersza w kodzie, ale ignoruje dodatkowe białe znaki (tabulatory i spacje itp.).

Najpierw napisz swoje słowa w oddzielnych wierszach kodu:

<div>Short
Word</div>

Następnie zastosuj styl do elementu zawierającego słowa.

div { white-space: pre-line; }

Uważaj jednak, każdy podział wiersza w kodzie wewnątrz elementu spowoduje podział wiersza. Tak więc napisanie następującego spowoduje dodatkowy podział wiersza przed pierwszym słowem i po ostatnim słowie:

<div>
    Short
    Word
</div>

Jest świetny artykuł na temat sztuczek CSS wyjaśniający inne atrybuty spacji.


Powinieneś wyjaśnić, w jaki sposób white-spacemożna odpowiedzieć na pytanie. Przepraszam, ale nie wiem jak.
jlgrall

2
Cóż, artykuł o Sztukach CSS wyjaśnia to w pełni, więc pomyślałem, że wystarczy link, zamiast próbować zwracać tutaj odpowiedź.
Nass,

Ok, więc sugerujesz umieszczenie prawdziwych podziałów linii w źródle i użycie CSS white-space: pre;do wyświetlania tych podziałów " " tak, jak <pre>zrobiłby to znacznik? To może zadziałać, a podział wiersza powinien wyglądać bardziej naturalnie dla tłumaczy niż plik <br />. Postaram się edytować Twoją odpowiedź, aby ją dodać :)
jlgrall

Dokładnie. Właściwie white-space: pre-line;to prawdopodobnie byłoby bardziej odpowiednie, ponieważ ignoruje dodatkowe białe znaki w kodzie. Zaktualizuję odpowiedź.
Nass

Dobrze, może po prostu dodaj white-space: pre;do IE 7.
jlgrall

12

Jeśli chcesz mieć możliwość wyboru spośród innych rozwiązań oprócz podanych odpowiedzi ...

Alternatywną metodą jest nadanie kontenerowi szerokości 0 i upewnienie się, że przepełnienie jest widoczne. Wtedy każde słowo wypłynie z niego i znajdzie się w osobnym wierszu.

div {
  width: 0;
  overflow: visible;
}
<div>Short Word</div>
<hr>
<div>Gargantuan Word</div>

Możesz też użyć jednej z tych nowo zaproponowanych widthwartości, pod warunkiem, że nadal będą istnieć w chwili, gdy to przeczytasz.

div {
  width: min-intrinsic;       /* old Chrome, Safari */
  width: -webkit-min-content; /* less old Chrome, Safari */
  width: -moz-min-content;    /* current Firefox */
  width: min-content;         /* current Chrome, Safari; not IE or Edge */
}
<div>Short Word</div>
<hr>
<div>Gargantuan Word</div>


4

Nie możesz kierować reklamy na każde słowo w CSS. Jednak z odrobiną jQuery prawdopodobnie mógłbyś.

Dzięki jQuery możesz zawijać każde słowo w a, <span>a następnie ustawić zakres CSS, do display:blockktórego umieściłby je w osobnym wierszu.

Oczywiście w teorii: P.


Tak, bałem się tego. Mógłby to zrobić również w PHP, ale wydaje się to brzydkim rozwiązaniem. Myślałem, że może tam być jakaś :first-childsztuczka lub coś ...
Ben

@Steve: nie, selektory CSS obecnie pozwalają tylko na wybór elementów HTML, a nie węzłów tekstowych. Rzuciłem okiem na moduł CSS 3 Text , ale wydaje się, że nie ma tam niczego, co wymusza przerwę po każdym słowie w elemencie. Rozwiązanie Marka to najlepszy wybór.
Paul D. Waite

@Paul, @Mark - Jeśli któryś z was chce przedstawiciela, możesz udzielić takiej odpowiedzi, a ja ją zaakceptuję. Oznaczę to jako niemożliwe do odpowiedzi (na razie) na meta.stackoverflow.com/questions/48013/… .
Ben

Myślę, że Mark już dał odpowiedź, jeśli o mnie chodzi, cała reprezentacja należy do niego.
Paul D. Waite

@Paul - +1 gracz zespołowy daje facetowi odznakę czy coś :)
Ben

2

https://jsfiddle.net/bm3Lfcod/1/

Dla tych, którzy szukają rozwiązania działającego w elastycznym kontenerze nadrzędnym z elementami podrzędnymi, które są elastyczne w obu wymiarach. na przykład. przyciski paska nawigacyjnego.

//the parent (example of what it may be)
div {
  display:flex;
  width: 100%;
}

//The children
a {
  display: inline-block;
}

//text wrapper
span {
  display: table-caption;
}

Spróbuj nadać temu zakresowi dowolną inną CSSwłaściwość, jaką możesz dać. Podaj właściwość, która może spowodowaćbrowser reflow
Deepak Yadav

1
ponowne wlanie przeglądarki?
Onza

2

Miałem ten sam problem i żadna z opcji tutaj nie pomogła. Niektóre usługi pocztowe nie obsługują określonych stylów. Oto moja wersja, która rozwiązała problem i działa wszędzie tam, gdzie sprawdziłem:

<table>
    <tr>
        <td width="1">Gargantuan Word</td>
    </tr>
</table>

LUB używając CSS:

<table>
    <tr>
        <td style="width:1px">Gargantuan Word</td>
    </tr>
</table>

2

Najlepszym rozwiązaniem jest word-spacingwłasność.

Dodaj <p>w kontenerze o określonym rozmiarze (przykład 300px) i po tym, jak musisz dodać ten rozmiar jako wartość w odstępach między wyrazami.

HTML

<div>
 <p>Sentence Here</p>
</div>

CSS

div {
 width: 300px;
}

p {
 width: auto;
 text-align: center;
 word-spacing: 300px;
}

W ten sposób Twoje zdanie będzie zawsze łamane i umieszczane w kolumnie, ale z akapitu będzie dynamiczne.

Tutaj przykład Codepen


-1

W moim przypadku,

    word-break: break-all;

działało perfekcyjnie, mam nadzieję, że pomoże to każdemu nowemu nowicjuszowi, jak ja.


Ode mnie -1, bo to jest nieprawidłowa odpowiedź. To łamie linię przy każdym znaku, JEŚLI jest potrzebny.
Emobe
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.