CSS для прерывания строки до/после определенного элемента `inline-block`

Скажем, у меня есть этот 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>

и этот CSS:

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

Результат можно увидеть здесь: http://jsfiddle.net/YMN7U/1/

Теперь представьте, что я хочу разбить это на три столбца, что эквивалентно инъекции a <br> после третьего <li>. (Фактически это будет семантически и синтаксически недействительным.)

Я знаю, как выбрать третий <li> в CSS, но как я могу заставить его сломать строку? Это не работает:

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

Я также знаю, что этот конкретный случай возможен, используя float вместо inline-block, но меня не интересуют решения, использующие float. Я также знаю, что с блоками фиксированной ширины это возможно, установив ширину на родительском ul примерно до 3x этой ширины; Меня это не интересует. Я также знаю, что я мог бы использовать display:table-cell, если бы мне нужны реальные столбцы; Меня это не интересует. Меня интересует возможность принудительного прорыва внутри встроенного контента.

Изменить. Чтобы быть ясным, меня интересует "теория", а не решение конкретной проблемы. Может ли CSS вставить разрыв строки в середине элементов display:inline(-block)?, или это невозможно? Если вы уверены, что это невозможно, это приемлемый ответ.

Ответ 1

Мне удалось заставить его работать с встроенными элементами LI. К сожалению, он не работает, если элементы LI являются встроенным блоком:

Live demo: http://jsfiddle.net/dWkdp/

Или версия примечаний утеса:

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

Ответ 2

Вас не интересует множество "решений" вашей проблемы. Я не думаю, что действительно есть хороший способ сделать то, что вы хотите сделать. Все, что вы вставляете с помощью :after и content, имеет точно такую ​​же синтаксическую и семантическую достоверность, что и в том случае, если бы вы только что написали его там.

Инструменты CSS обеспечивают работу. Вы должны просто поплавать li, а затем clear: left, когда хотите начать новую строку, как вы уже упоминали:

См. пример: http://jsfiddle.net/marcuswhybrow/YMN7U/5/

Ответ 3

Когда переписывание html разрешено, вы можете вложить <ul> в <ul> и просто позволить внутреннему <li> отображать как встроенный блок. Это также семантически имеет смысл ИМХО, поскольку группировка также отражается внутри 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; }

Demo

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

Ответ 4

Легкий способ разбиения списков на строки - это перемещение отдельных элементов списка, а затем элемент, который вы хотите перейти на следующую строку, вы можете очистить float.

например

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

Ответ 5

Я знаю, что вы не хотели использовать float, и вопрос был просто теорией, но в случае, если кто-нибудь найдет это полезным, вот решение, использующее float.

Добавьте класс слева к вашим li элементам, которые вы хотите плавать:

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

и измените свой CSS следующим образом:

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

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

Вам не нужно указывать ширину или встроенные блоки и работать еще в IE6.

Ответ 6

Я достиг этого, создав селектор :: before для первого встроенного элемента в строке и сделав этот селектор блоком с верхним или нижним полем для небольшого разделения строк.

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

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

.2nd_item
{
  color: blue;
}

Ответ 7

Обратите внимание, что это будет работать, в зависимости от того, как вы отображаете страницу. Но как насчет того, чтобы начать новый неупорядоченный список?

т.е.

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

Ответ 8

Возможно, это возможно только с помощью CSS, но я предпочитаю избегать "float" столько, сколько могу, потому что это мешает ему родительскую высоту.

Если вы используете jQuery, вы можете создать простой плагин `wrapN`, похожий на` wrapAll`, за исключением того, что он только обертывает элементы "N", а затем разбивает и обматывает следующие "N" элементы с помощью цикла. Затем установите для класса оболочек `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);
});

Вот JSFiddle готового продукта:

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

Ответ 9

Лучшим решением является использование -webkit-columns: 2;

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

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