CSS per interrompere la linea prima / dopo un particolare elemento `inline-block`


202

Diciamo che ho questo 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>

e questo CSS:

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

Il risultato può essere visto qui: http://jsfiddle.net/YMN7U/1/

Ora immagina di voler dividere questo in tre colonne, l'equivalente di iniettare un <br>dopo il terzo <li>. (In realtà farlo sarebbe semanticamente e sintatticamente non valido.)

So come selezionare il terzo <li>in CSS, ma come posso forzare un'interruzione di riga dopo di esso? Questo non funziona:

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

So anche che questo caso particolare è possibile utilizzando floatinvece di inline-block, ma non mi interessa utilizzare le soluzioni float. So anche che con blocchi a larghezza fissa questo è possibile impostando la larghezza sul genitore ula circa 3 volte quella larghezza; Non mi interessa questa soluzione. So anche che potrei usare display:table-cellse volessi colonne reali; Non mi interessa questa soluzione. Sono interessato alla possibilità di forzare una pausa all'interno del contenuto in linea.

Modifica : per essere chiari, sono interessato alla "teoria", non alla soluzione di un problema particolare. Il CSS può iniettare un'interruzione di riga nel mezzo di display:inline(-block)?elementi o è impossibile? Se sei sicuro che sia impossibile, questa è una risposta accettabile.


2
Metti il ​​primo tre e il secondo tre in due liste diverse? Presumo che tu non voglia farlo, ma ho pensato di buttarlo là fuori.
JakeParis,

Sembra che tu abbia bisogno di dirci cosa stai veramente cercando di ottenere qui, così qualcuno può consigliare il metodo migliore. Tutte le opzioni che hai escluso esistono per risolvere il problema che hai, perché è necessaria un'altra soluzione?
Jake,

4
@Jake In effetti stavo facendo esattamente quello che ho affermato: usando un elenco semantico di elementi e volendo racchiudere quelli particolari. In pratica ho impostato la larghezza del contenitore, ma questo funziona solo nel mio caso particolare perché gli articoli avevano la stessa larghezza e volevo che avvolgessero un bordo coerente. Questo potrebbe non essere sempre il caso. Ciò che " sto davvero cercando di ottenere" è sapere se i CSS possono forzare l'interruzione di una linea nel mezzo del flusso in linea. La risposta sicura "Questo non è assolutamente possibile" è accettabile (se corretta).
Phrogz,

Risposte:


302

Sono stato in grado di farlo funzionare su elementi LI in linea. Sfortunatamente, non funziona se gli elementi LI sono inline-block:

Demo live: http://jsfiddle.net/dWkdp/

O la versione delle note di scogliera:

li { 
     display: inline; 
}
li:nth-child(3):after { 
     content: "\A";
     white-space: pre; 
}

2
Sime, perché "\ A" non viene stampato? Tutto quello che ho provato con le :afterstampe sempre come testo semplice.
JakeParis,

12
@JMCCreative È ASCII 0x0A, AKA un carattere LF (avanzamento riga). Vedi w3.org/TR/CSS2/syndata.html#strings
Phrogz,

5
@JMC \Aè il personaggio del feed di riga ... è una via di fuga
Šime Vidas il


18
commentando qui mentre torno a questa domanda ogni pochi mesi ... Non funzionerà sul blocco inline perché stai aggiungendo interruzioni di riga all'interno di qualcosa che si comporta come un contenitore di blocchi in un contesto inline. Se potessi uscire dal contesto inserendo l'interruzione di linea tra i <li> s funzionerebbe. Peccato davvero perché questo è utile per i breakpoint di progettazione reattivi. Immagino che la maggior parte delle volte "inline" sia utile quanto il blocco inline per gli elenchi
user1010892

21

Non sei interessato a molte "soluzioni" al tuo problema. Non penso che ci sia davvero un buon modo per fare quello che vuoi fare. Qualunque cosa tu inserisca usando :aftere contentabbia esattamente la stessa validità sintattica e semantica che avrebbe fatto se l'avessi scritto tu stesso.

Gli strumenti CSS forniscono lavoro. Dovresti semplicemente fare galleggiare le lis e poi clear: leftquando vuoi iniziare una nuova linea, come hai detto:

Vedi un esempio: http://jsfiddle.net/marcuswhybrow/YMN7U/5/


18
L'OP non è interessato alla tua soluzione :)
Šime Vidas

2
Bene, niente che tu possa fare usando :aftersarà sintatticamente valido o una buona idea, dato che ci sono già degli strumenti per farlo. Da qui la risposta.
Marcus Whybrow,

32
Uno dei motivi per non usare i float è che non esiste float: center.
mancanza di palpebre

7
inoltre il blocco in linea consente tutti i tipi di allineamento verticale che i galleggianti non possono
user1010892

20
"Qualunque cosa tu inserisca usando: after e il contenuto ha esattamente la stessa validità sintattica e semantica" - arrivando in ritardo alla festa, ma non sono assolutamente d'accordo con questo - l'intero punto di usare: before e: after è quello di poter inserire uno stile che non interferisce con il significato semantico di HTML.
Rupert,

4

Quando si riscrive l'html è consentito, è possibile annidare <ul>s all'interno di <ul>e lasciare che l'interno <li>s venga visualizzato come blocco in linea. Ciò avrebbe anche senso semantico su IMHO, poiché anche il raggruppamento si riflette nell'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; }

dimostrazione

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

Un modo semplice per dividere gli elenchi in righe consiste nel fluttuare i singoli elementi dell'elenco e quindi l'elemento che si desidera passare alla riga successiva è possibile cancellare il float.

per esempio

<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
Si dovrebbe notare che l' floatimpostazione sovrascrive l' inline-blockimpostazione. Non convivono davvero insieme
Itay,

4
se usi text-aling: center; non funzionerà (il galleggiante lo rompe)
Павел Иванов

3

So che non volevi usare i float e la domanda era solo teoria, ma se qualcuno lo trova utile, ecco una soluzione che usa i float.

Aggiungi una classe di sinistra ai tuoi lielementi che vuoi galleggiare:

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

e modifica il tuo CSS come segue:

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

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

Non è necessario specificare larghezze o blocchi in linea e funziona fino a IE6.


1

Ho realizzato questo creando un selettore :: before per il primo elemento inline nella riga e trasformando quel selettore in un blocco con un margine superiore o inferiore per separare un po 'le righe.

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

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

.2nd_item
{
  color: blue;
}

-1

Nota che questo funzionerà, a seconda di come esegui il rendering della pagina. Ma che ne dici di iniziare un nuovo elenco non ordinato?

vale a dire

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


-2

Una soluzione migliore è usare -webkit-colonne: 2;

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

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

Per alcuni casi d'uso, questa potrebbe essere una soluzione ragionevole. In questo caso non è una buona soluzione, perché riordina completamente il contenuto in modo che scorra verso il basso anziché attraverso e poi verso il basso.
Phrogz,

5
Chi vorrebbe creare un'applicazione Web che funziona solo con pochi browser?
user2867288

-3

Forse è completamente possibile solo con CSS ma preferisco evitare "float" il più possibile perché interferisce con l'altezza dei genitori.

Se stai usando jQuery, puoi creare un semplice plugin `wrapN` che è simile a` wrapAll` tranne che avvolge solo gli elementi "N" e quindi rompe e avvolge i successivi elementi "N" usando un ciclo. Quindi imposta la tua classe di wrapper su `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);
});

Ecco un JSFiddle del prodotto finito:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.