CSS do podziału wiersza przed / po określonym elemencie „w linii”

202

Powiedzmy, że mam ten kod HTML:

<h3>Features</h3>
<ul>
    <li><img src="alphaball.png">Smells Good</li>
    <li><img src="alphaball.png">Tastes Great</li>
    <li><img src="alphaball.png">Delicious</li>
    <li><img src="alphaball.png">Wholesome</li>
    <li><img src="alphaball.png">Eats Children</li>
    <li><img src="alphaball.png">Yo' Mama</li>
</ul>

i ten CSS:

li { text-align:center; display:inline-block; padding:0.1em 1em }
img { width:64px; display:block; margin:0 auto }

Wynik można zobaczyć tutaj: http://jsfiddle.net/YMN7U/1/

Teraz wyobraź sobie, że chcę rozbić to na trzy kolumny, co odpowiada wstrzyknięciu <br>po trzeciej <li>. (W rzeczywistości byłoby to nieprawidłowe semantycznie i składniowo).

Wiem, jak wybrać trzeci <li>w CSS, ale jak wymusić przerwanie linii po nim? To nie działa:

li:nth-child(4):after { content:"xxx"; display:block }

Wiem też, że ten konkretny przypadek jest możliwy przy użyciu floatzamiast inline-block, ale nie interesują mnie rozwiązania float. Wiem również, że w przypadku bloków o stałej szerokości jest to możliwe poprzez ustawienie szerokości nadrzędnej ulna około 3x tę szerokość; Nie jestem zainteresowany tym rozwiązaniem. Wiem też, że mógłbym użyć, display:table-cellgdybym chciał prawdziwych kolumn; Nie jestem zainteresowany tym rozwiązaniem. Interesuje mnie możliwość wymuszenia przerwy w treści wbudowanej.

Edycja : Dla jasności interesuje mnie „teoria”, a nie rozwiązanie konkretnego problemu. Czy CSS może wprowadzić przerwanie linii pośrodku display:inline(-block)?elementów, czy jest to niemożliwe? Jeśli masz pewność, że jest to niemożliwe, jest to akceptowalna odpowiedź.

Phrogz
źródło
2
Umieścić pierwszą trzy i drugą trzy na dwóch różnych listach? Zakładam, że nie chcesz tego robić, ale pomyślałem, że go tam
wyrzucę
Wygląda na to, że musisz powiedzieć nam, co tak naprawdę chcesz osiągnąć, aby ktoś mógł polecić najlepszą metodę. Istnieją wszystkie wykluczone opcje rozwiązania problemu, dlaczego potrzebne jest inne rozwiązanie?
Jake
4
@Jake W rzeczywistości robiłem dokładnie to, co powiedziałem: korzystałem z semantycznej listy elementów i chciałem zawijać się po poszczególnych. W praktyce ustawiam szerokość pojemnika, ale działa to tylko w moim konkretnym przypadku, ponieważ przedmioty miały tę samą szerokość i chciałem, aby zawijały się na jednolitej krawędzi. Nie zawsze tak może być. To, co „naprawdę próbuję osiągnąć”, to dowiedzieć się, czy CSS może wymusić przerwanie linii w środku przepływu liniowego. Pewna odpowiedź „To zdecydowanie nie jest możliwe” jest akceptowalna (jeśli jest poprawna).
Phrogz,

Odpowiedzi:

302

Udało mi się sprawić, że będzie działać na elementach wbudowanych LI. Niestety nie działa, jeśli elementy LI są wbudowane w blok:

Demo na żywo: http://jsfiddle.net/dWkdp/

Lub wersja z notatkami na klifie:

li { 
     display: inline; 
}
li:nth-child(3):after { 
     content: "\A";
     white-space: pre; 
}
Šime Vidas
źródło
2
Sime, dlaczego „\ A” nie jest drukowane? Wszystko, co próbowałem z :afterzawsze drukuje jako zwykły tekst.
JakeParis,
12
@JMCCreative To ASCII 0x0A, AKA znak LF (wstawianie wiersza). Zobacz w3.org/TR/CSS2/syndata.html#strings
Phrogz
5
@JMC \Ato znak kanału ... to ucieczka
Šime Vidas
3
@JMC Oficjalna specyfikacja: w3.org/TR/CSS21/syndata.html#strings Sitepoint: reference.sitepoint.com/css/content
Šime Vidas
18
komentując tutaj, gdy wracam do tego pytania co kilka miesięcy ... To nie będzie działać na bloku wstawiania, ponieważ dodajesz podziały wiersza wewnątrz czegoś, co działa jak kontener bloku w kontekście wstawiania. Gdybyś mógł wyrwać się z kontekstu, wstawiając podział linii między <li> s, zadziałałoby. Wstyd naprawdę, ponieważ jest to przydatne do responsywnych punktów przerwania projektu.
Wydaje
21

Nie interesuje Cię wiele „rozwiązań” swojego problemu. Nie sądzę, aby naprawdę był dobry sposób na robienie tego, co chcesz. Cokolwiek wstawisz za pomocą :afteri contentma dokładnie taką samą poprawność składniową i semantyczną, co zrobiłby, gdybyś sam to tam napisał.

Narzędzia CSS zapewniają pracę. Powinieneś po prostu przesunąć lis, a następnie, clear: leftkiedy chcesz rozpocząć nową linię, jak już wspomniałeś:

Zobacz przykład: http://jsfiddle.net/marcuswhybrow/YMN7U/5/

Marcus Whybrow
źródło
18
OP nie jest zainteresowany twoim rozwiązaniem :)
Šime Vidas
2
Cóż, nic, co możesz zrobić za pomocą, :afterbędzie poprawne pod względem składniowym lub dobrym pomysłem, ponieważ istnieją już narzędzia do tego. Stąd odpowiedź.
Marcus Whybrow
32
Jednym z powodów, dla których nie należy używać pływaków, jest to, że nie ma czegoś takiego jak float: center.
powiek
7
Plus inline-block pozwala na wszelkiego rodzaju pionowego wyrównania że pływaki nie mogę
user1010892
20
„Wszystko, co wstawisz za pomocą: po i treść ma dokładnie taką samą ważność składniową i semantyczną” - spóźniając się na imprezę, ale całkowicie się z tym nie zgadzam - cały sens używania: przed i po po to, aby móc wstawić styl, który: nie koliduje z semantycznym znaczeniem HTML.
Rupert
4

Gdy przepisywanie html jest dozwolone, możesz zagnieździć <ul>s wewnątrz <ul>i po prostu pozwolić wewnętrznemu <li>s wyświetlać się jako blok wbudowany. Miałoby to również semantyczny sens w przypadku IMHO, ponieważ grupowanie jest również odzwierciedlane w pliku HTML.


<ul>
    <li>
        <ul>
            <li>Item 1</li>
            <li>Item 2</li>
            <li>Item 3</li>
        </ul>
    </li>
    <li>
        <ul>
            <li>Item 4</li>
            <li>Item 5</li>
            <li>Item 6</li>
        </ul>
    </li>
</ul>

li li { display:inline-block; }

Próbny

$(function() { $('img').attr('src', 'http://phrogz.net/tmp/alphaball.png'); });
h3 {
  border-bottom: 1px solid #ccc;
  font-family: sans-serif;
  font-weight: bold;
}
ul {
  margin: 0.5em auto;
  list-style-type: none;
}
li li {
  text-align: center;
  display: inline-block;
  padding: 0.1em 1em;
}
img {
  width: 64px;
  display: block;
  margin: 0 auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<h3>Features</h3>
<ul>
  <li>
    <ul>
      <li><img />Smells Good</li>
      <li><img />Tastes Great</li>
      <li><img />Delicious</li>
    </ul>
  </li>
  <li>
    <ul>
      <li><img />Wholesome</li>
      <li><img />Eats Children</li>
      <li><img />Yo' Mama</li>
    </ul>
  </li>
</ul>

fabb
źródło
3

Łatwym sposobem podziału list na wiersze jest przestawienie poszczególnych pozycji listy, a następnie element, który chcesz przejść do następnego wiersza, możesz wyczyścić pływak.

na przykład

<li style="float: left; display: inline-block"></li>
<li style="float: left; display: inline-block"></li>
<li style="float: left; display: inline-block"></li>

<li style="float: left; display: inline-block; clear: both"></li> --- this will start on a new line
<li style="float: left; display: inline-block"></li>
<li style="float: left; display: inline-block"></li>
matowy
źródło
17
Należy zauważyć, że floatustawienie zastępuje inline-blockustawienie. Tak naprawdę nie współistnieją razem
Itay
4
jeśli korzystasz z funkcji edycji tekstu: centrum; to nie zadziała (pływanie psuje go)
Павел Иванов
3

Wiem, że nie chciałeś używać pływaków, a pytanie było tylko teorią, ale na wypadek gdyby ktoś uznał to za przydatne, oto rozwiązanie wykorzystujące pływaki.

Dodaj klasę left do lielementów, które chcesz unosić:

<li class="left"><img src="http://phrogz.net/tmp/alphaball.png">Smells Good</li>

i zmień swój CSS w następujący sposób:

li { text-align:center; float: left; clear: left; padding:0.1em 1em }
.left {float: left; clear: none;}

http://jsfiddle.net/chut319/xJ3pe/

Nie musisz określać szerokości ani bloków śródliniowych i działa już w IE6.

chut319
źródło
1

Osiągnąłem to, tworząc selektor :: before dla pierwszego elementu śródrzędnego w wierszu i tworząc selektor bloku z górnym lub dolnym marginesem, aby nieco oddzielić rzędy.

.1st_item::before
{
  content:"";
  display:block;
  margin-top: 5px;
}

.1st_item
{
  color:orange;
  font-weight: bold;
  margin-right: 1em;
}

.2nd_item
{
  color: blue;
}
Deji
źródło
-1

Pamiętaj, że to zadziała, w zależności od sposobu renderowania strony. Ale co powiesz na rozpoczęcie nowej, nieuporządkowanej listy?

to znaczy

<ul>
<li>
<li>
<li>
</ul>
<!-- start a new ul to line break it -->
<ul>

Phil LaNasa
źródło
-2

Lepszym rozwiązaniem jest użycie -webkit-columns: 2;

http://jsfiddle.net/YMN7U/889/

 ul { margin:0.5em auto;
-webkit-columns:2;
}
Vivekraj KR
źródło
W niektórych przypadkach może to być rozsądne rozwiązanie. W tym przypadku nie jest to dobre rozwiązanie, ponieważ całkowicie zmienia kolejność treści w dół, a potem w dół.
Phrogz,
5
Kto chciałby stworzyć aplikację internetową, która działa tylko w kilku przeglądarkach?
user2867288,
-3

Być może jest to całkowicie możliwe tylko z CSS, ale wolę unikać „unosić się” tak bardzo, jak to możliwe, ponieważ przeszkadza to wysokości jego rodzica.

Jeśli używasz jQuery, możesz stworzyć prostą wtyczkę `wrapN`, która jest podobna do` wrapAll` oprócz tego, że otacza tylko elementy „N”, a następnie łamie i otacza kolejne elementy „N” za pomocą pętli. Następnie ustaw swoją klasę opakowań na `display: block;`.

(function ($) {
    $.fn.wrapN = function (wrapper, n, start) {
        if (wrapper === undefined || n === undefined) return false;
        if (start === undefined) start = 0;
        for (var i = start; i < $(this).size(); i += n)
           $(this).slice(i, i + n).wrapAll(wrapper);
        return this;
    };
}(jQuery));

$(document).ready(function () {
    $("li").wrapN("<span class='break' />", 3);
});

Oto JSFiddle gotowego produktu:

http://jsfiddle.net/dustinpoissant/L79ahLoz/

Dustin Poissant
źródło