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

202

Допустим, у меня есть этот 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/

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

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

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

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

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

Phrogz
источник
2
Поместить первые три и вторые три в два разных списка? Я предполагаю, что вы не хотите делать это, но я думал, что я бы выбросил это туда.
JakeParis
Похоже, вам нужно рассказать нам, чего вы действительно пытаетесь достичь, чтобы кто-то мог порекомендовать лучший метод. Все варианты, которые вы исключили, существуют для решения вашей проблемы. Зачем нужно другое решение?
Джейк
4
@ Джейк, на самом деле я делал именно то, что говорил: использовал семантический список элементов и хотел обернуть некоторые из них. На практике я установил ширину контейнера, но это работает только в моем конкретном случае, потому что элементы оказались одинаковой ширины, и я хотел, чтобы они были обернуты по одному краю. Это не всегда так. То, что я «действительно пытаюсь достичь», - это узнать, может ли CSS вызвать разрыв строки в середине встроенного потока. Уверенный ответ «Это точно невозможно» приемлем (если он правильный).
Phrogz

Ответы:

302

Я был в состоянии заставить это работать на встроенных элементах LI. К сожалению, это не работает, если элементы LI являются inline-block:

Живая демоверсия: http://jsfiddle.net/dWkdp/

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

li { 
     display: inline; 
}
li:nth-child(3):after { 
     content: "\A";
     white-space: pre; 
}
Шиме Видас
источник
2
Симе, почему "\ A" не распечатывается? Все, что я пробовал, :afterвсегда печатается как прямой текст.
JakeParis
12
@JMCCreative Это ASCII 0x0A, AKA символ LF (перевод строки). См. W3.org/TR/CSS2/syndata.html#strings
Phrogz,
5
@JMC \A- символ перевода строки ... это побег
Шиме Видас
3
@JMC Официальная спецификация: w3.org/TR/CSS21/syndata.html#strings Sitepoint: reference.sitepoint.com/css/content
Шиме Видас
18
комментируя здесь, так как я продолжаю возвращаться к этому вопросу каждые несколько месяцев ... Это не сработает для встроенного блока, потому что вы добавляете разрывы строк внутри чего-то, что он действует как контейнерный блок внутри встроенного контекста. Если бы вы могли вырваться из контекста, вставив разрыв строки между <li>, это сработало бы. Позор действительно, поскольку это полезно для отзывчивых точек останова дизайна. Я думаю, что большую часть времени "inline" так же полезен, как inline-block для списков
user1010892
21

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

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

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

Маркус Уайброу
источник
18
ОП не заинтересован в вашем решении :)
Шиме Видас
2
Ну, ничего, что вы можете сделать с помощью :afterсинтаксически правильной или хорошей идеи, так как уже есть инструменты для этого. Отсюда и ответ.
Маркус Уайброу
32
Одна из причин не использовать поплавки в том, что нет такой вещи как float: center.
век
7
плюс inline-block позволяет все виды вертикального выравнивания, которые не могут
плавать
20
«Все, что вы вставляете с помощью: after и content, имеет точно такую ​​же синтаксическую и семантическую валидность», - опоздал на вечеринку, но я совершенно не согласен с этим, - весь смысл использования: before и: after - возможность вставлять стили, которые не мешает смысловой смысл HTML.
Руперт
4

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

демонстрация

$(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
источник
3

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

например

<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
Вы должны заметить, что floatнастройка переопределяет inline-blockнастройку. Они действительно не сосуществуют вместе
Итай
4
если вы используете text-aling: center; это не сработает (плавающий ломает)
Павел Иванов
3

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

Добавьте класс left к вашим 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.

chut319
источник
1

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

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

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

.2nd_item
{
  color: blue;
}
Deji
источник
-1

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

т.е.

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

Фил ЛаНаса
источник
-2

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

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

 ul { margin:0.5em auto;
-webkit-columns:2;
}
Вивекрай КР
источник
Для некоторых случаев использования это может быть разумным решением. В этом случае это не очень хорошее решение, потому что оно полностью переупорядочивает контент, чтобы он шел вниз, потом поперек, а не вниз.
Phrogz
5
Кто бы хотел сделать веб-приложение, которое работает только в нескольких браузерах?
user2867288
-3

Может быть, это полностью возможно только с помощью 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/

Дастин Пуассан
источник