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ź.


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

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


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/


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>


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>

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.


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

-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>


-2

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

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

 ul { margin:0.5em auto;
-webkit-columns:2;
}

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/

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.