CSS para salto de línea antes / después de un elemento particular de "bloque en línea"

202

Digamos que tengo este 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>

y este CSS:

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

El resultado se puede ver aquí: http://jsfiddle.net/YMN7U/1/

Ahora imagine que quiero dividir esto en tres columnas, el equivalente a inyectar un <br>después de la tercera <li>. (En realidad, hacer eso sería semántica y sintácticamente inválido).

Sé cómo seleccionar el tercero <li>en CSS, pero ¿cómo forzo un salto de línea después? Esto no funciona:

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

También sé que este caso particular es posible usando en floatlugar de inline-block, pero no estoy interesado en las soluciones que usan float. También sé que con los bloques de ancho fijo esto es posible estableciendo el ancho en el padre ula aproximadamente 3 veces ese ancho; No estoy interesado en esta solución. También sé que podría usar display:table-cellsi quisiera columnas reales; No estoy interesado en esta solución. Estoy interesado en la posibilidad de forzar un descanso dentro del contenido en línea.

Editar : Para ser claros, estoy interesado en la 'teoría', no en la solución a un problema en particular. ¿Puede CSS inyectar un salto de línea en el medio de los display:inline(-block)?elementos, o es imposible? Si está seguro de que es imposible, esa es una respuesta aceptable.

Phrogz
fuente
2
¿Poner los primeros tres y los segundos tres en dos listas diferentes? Supongo que no quieres hacer esto, pero pensé que lo tiraría por ahí.
JakeParis
Parece que necesita decirnos lo que realmente está tratando de lograr aquí para que alguien pueda recomendar el mejor método. Todas las opciones que excluyó existen para resolver el problema que tiene, ¿por qué se necesita otra solución?
Jake
44
@Jake De hecho, estaba haciendo exactamente lo que dije: usar una lista semántica de elementos y querer ajustar después de algunos en particular. En la práctica, configuré el ancho del contenedor, pero esto solo funciona en mi caso particular porque los artículos eran del mismo ancho y quería que se ajustaran en un borde consistente. Esto puede no ser siempre el caso. Lo que realmente estoy tratando de lograr es saber si CSS puede forzar un salto de línea en el medio del flujo en línea. La respuesta segura "Esto definitivamente no es posible" es aceptable (si es correcta).
Phrogz

Respuestas:

302

He podido hacer que funcione en elementos LI en línea. Desafortunadamente, no funciona si los elementos LI son bloque en línea:

Demo en vivo: http://jsfiddle.net/dWkdp/

O la versión de las notas del acantilado:

li { 
     display: inline; 
}
li:nth-child(3):after { 
     content: "\A";
     white-space: pre; 
}
Šime Vidas
fuente
2
Sime, ¿por qué no se imprime la "\ A"? Todo lo que he probado con :aftersiempre se imprime como texto directo.
JakeParis
12
@JMCCreative Eso es ASCII 0x0A, también conocido como un carácter LF (avance de línea). Ver w3.org/TR/CSS2/syndata.html#strings
Phrogz
55
@JMC \Aes el personaje de salto de línea ... es un escape
Šime Vidas
3
@JMC Especificaciones oficiales: w3.org/TR/CSS21/syndata.html#strings Sitepoint: reference.sitepoint.com/css/content
Šime Vidas
18
comentando aquí mientras sigo volviendo a esta pregunta cada pocos meses ... No funcionará en bloque en línea porque está agregando saltos de línea dentro de algo que actúa como un contenedor de bloque en un contexto en línea. Si pudiera salir del contexto insertando el salto de línea entre los <li> s, funcionaría. Vergüenza, ya que esto es útil para puntos de corte de diseño receptivo. Supongo que la mayoría de las veces "en línea" es tan útil como el bloqueo en línea para listas
usuario1010892
21

No le interesan muchas "soluciones" a su problema. No creo que realmente haya una buena manera de hacer lo que quieres hacer. Todo lo que inserte usando :aftery contenttenga exactamente la misma validez sintáctica y semántica que hubiera hecho si lo hubiera escrito allí mismo.

Las herramientas CSS proporcionan trabajo. Simplemente debe flotar los lis y luego clear: leftcuando desee comenzar una nueva línea, como ha mencionado:

Vea un ejemplo: http://jsfiddle.net/marcuswhybrow/YMN7U/5/

Marcus Whybrow
fuente
18
El OP no está interesado en su solución :)
Šime Vidas
2
Bueno, nada de lo que pueda hacer mediante el uso :afterserá sintácticamente válido o una buena idea, ya que ya existen herramientas para hacerlo. De ahí la respuesta.
Marcus Whybrow
32
Una razón para no usar flotadores es que no existe tal cosa float: center.
párpado
77
Además, el bloqueo en línea permite todo tipo de alineación vertical que los flotadores no pueden
user1010892
20
"Cualquier cosa que inserte usando: after y content tiene exactamente la misma validez sintáctica y semántica" - llegar tarde a la fiesta, pero estoy totalmente en desacuerdo con esto - el punto principal de usar: before y: after es poder insertar un estilo que no interfiere con el significado semántico del HTML.
Rupert
4

Cuando se permite reescribir el html, puede anidar <ul>s dentro del <ul>y simplemente dejar que el interior se <li>muestre como bloque en línea. Esto también tendría sentido semántico en mi humilde opinión, ya que la agrupación también se refleja en el 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; }

Manifestación

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

Una manera fácil de dividir las listas en filas es flotando los elementos de la lista individual y luego el elemento que desea ir a la siguiente línea puede borrar el flotante.

por ejemplo

<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>
mate
fuente
17
Debería notar que la floatconfiguración anula la inline-blockconfiguración. Realmente no coexisten juntos
Itay
44
si usa text-aling: center; no funcionará (flotante lo rompe)
Fecha de inicio
3

Sé que no querías usar flotadores y la pregunta era solo teoría, pero en caso de que alguien lo encuentre útil, aquí hay una solución con flotadores.

Agregue una clase de izquierda a sus lielementos que desea flotar:

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

y modifique su CSS de la siguiente manera:

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

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

No necesita especificar anchos o bloques en línea y funciona desde IE6.

chut319
fuente
1

Lo logré creando un selector :: before para el primer elemento en línea de la fila y convirtiendo ese selector en un bloque con un margen superior o inferior para separar un poco las filas.

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

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

.2nd_item
{
  color: blue;
}
Deji
fuente
-1

Tenga en cuenta que esto funcionará, dependiendo de cómo renderice la página. Pero, ¿qué tal simplemente comenzar una nueva lista desordenada?

es decir

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

Phil LaNasa
fuente
-2

Una mejor solución es usar -webkit-columnas: 2;

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

 ul { margin:0.5em auto;
-webkit-columns:2;
}
Vivekraj KR
fuente
Para algunos casos de uso, esta puede ser una solución razonable. No es una buena solución en este caso, porque reordena completamente el contenido para ir hacia abajo en lugar de cruzarlo y luego bajarlo.
Phrogz
55
¿Quién querría hacer una aplicación web que solo funcione en unos pocos navegadores?
usuario2867288
-3

Tal vez sea completamente posible solo con CSS, pero prefiero evitar "flotar" tanto como pueda porque interfiere con la altura de sus padres.

Si está utilizando jQuery, puede crear un simple complemento `wrapN` que sea similar a` wrapAll` excepto que solo envuelve elementos "N" y luego rompe y envuelve los siguientes elementos "N" usando un bucle. Luego configure su clase de envoltorios para `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);
});

Aquí hay un JSFiddle del producto terminado:

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

Dustin Poissant
fuente