Как создать список из двух столбцов в CSS? - PullRequest
14 голосов
/ 10 июня 2009

Мне нужно отобразить список из двух столбцов в соответствии со следующими правилами:

  • Контейнер для колонн имеет ширину жидкости
  • Ширина обоих столбцов должна быть равна
  • Элементы отображаются динамически, и по крайней мере один будет отображаться
  • Порядок позиций должен сначала течь вниз по левому столбцу, затем по правому
  • Элементы должны располагаться равномерно по дну, или в случае нечетного числа дополнительный элемент должен отображаться в левом столбце

Вот пример:

~ Item 1   | ~ Item 6
~ Item 2   | ~ Item 7
~ Item 3   | ~ Item 8
~ Item 4   | ~ Item 9
~ Item 5   |

HTML может быть любым, пока он решает эту проблему. Я ограничен использованием XSLT, чтобы обернуть HTML вокруг того, что выплевывает сервер. У меня есть доступ к двум параметрам XSLT: один говорит мне номер текущего элемента, а второй - сколько элементов.

Мои навыки CSS являются базовыми / средними, и я не знаю, с чего начать. Любые идеи о том, достижимо ли это и как это сделать?

Обновление:

Спасибо за ответы. Похоже, консенсус использует либо статью A List Apart , либо таблицу, которую я бы предпочел, поскольку она проще. Проблема с таблицей заключается в том, что сервер дает мне элементы в отсортированном порядке. Использование таблицы будет означать хитрость XSLT для повторной сортировки, не так ли?

<tr>
    <td>Item 1</td>
    <td>Item 4</td>
</tr>
<tr>
    <td>Item 2</td>
    <td>Item 5</td>
</tr>
<tr>
    <td>Item 3</td>
    <td>&nbsp;</td>
</tr>

Ответы [ 8 ]

7 голосов
/ 18 февраля 2013

Вам просто нужен CSS, например ul {column-count: 2; -webkit-column-count: 2; -moz-column-count: 2}

6 голосов
/ 10 июня 2009

На alistapart есть полезная статья об этом, попробуйте взглянуть туда.

Обновление после редактирования:

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

3 голосов
/ 05 октября 2012

Вы можете попробовать что-то вроде:

.option:nth-of-type(n+5) {
    position: relative;
    left: 14ex;
    top: -6em;
}

.option:nth-of-type(n+9) {
    color: red;
    left: 28ex;
    top: -12em;
}

... для четырех элементов столбца, где line-height равно 1.5em, а ширина столбца будет 14ex.

Но поскольку здесь используется относительное позиционирование, вам, вероятно, придется уменьшить размер контейнера.

Кроме того, согласно w3schools, это свойство недоступно в IE8 или ниже.

3 голосов
/ 10 июня 2009

Я знаю, что люди отклоняют макеты на основе таблиц HTML, но какого черта. Они работают. Если вы тщеславны, вы можете пройти лишнюю милю и найти способ, основанный исключительно на CSS. : -)

Итак, решение XSLT.

<xml>
  <item id="1">Item 1</item>
  <item id="2">Item 2</item>
  <item id="3">Item 3</item>
  <item id="4">Item 4</item>
  <item id="5">Item 5</item>
  <item id="6">Item 6</item>
  <item id="7">Item 7</item>
  <item id="8">Item 8</item>
  <item id="9">Item 9</item>
</xml>

С этим шаблоном XSL 1.0 (количество столбцов можно настраивать):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="html" indent="yes" omit-xml-declaration="yes" />

  <xsl:template match="/xml">
    <xsl:variable name="vCols"  select="2" />
    <xsl:variable name="vCount" select="count(item)" />
    <xsl:variable name="vRows"  select="ceiling($vCount div $vCols)" />
    <xsl:variable name="vIterC" select="item[position() &lt;= $vCols]" />
    <xsl:variable name="vIterR" select="item[position() &lt;= $vRows]" />
    <xsl:variable name="vSelf"  select="." />

    <table>
      <xsl:for-each select="$vIterR">
        <xsl:variable name="vRowIdx" select="position()" />
        <tr>
          <xsl:for-each select="$vIterC">
            <xsl:variable name="vOffset" select="$vRows * (position() - 1)" />
            <td>
              <xsl:value-of select="$vSelf/item[$vRowIdx + $vOffset]" />
            </td>
          </xsl:for-each>
        </tr>
      </xsl:for-each>
    </table>
  </xsl:template>

</xsl:stylesheet>

Урожайность:

<table>
  <tr>
    <td>Item 1</td>
    <td>Item 6</td>
  </tr>
  <tr>
    <td>Item 2</td>
    <td>Item 7</td>
  </tr>
  <tr>
    <td>Item 3</td>
    <td>Item 8</td>
  </tr>
  <tr>
    <td>Item 4</td>
    <td>Item 9</td>
  </tr>
  <tr>
    <td>Item 5</td>
    <td></td>
  </tr>
</table>

Если есть только один предмет, он производит:

<table>
  <tr>
    <td>Item 1</td>
  </tr>
</table>

Так что в этой ситуации нет двух столбцов.

В любом случае таблица всегда будет правильно сформирована (например, без зубчатых строк). Единственное, что не делает это решение - это сортировка результатов. Вывод всегда будет в порядке документа. Похоже, вы правильно отсортировали предметы, так что это не должно быть большой проблемой.

1 голос
/ 10 июня 2009

CSS не может этого сделать. Вам необходимо собрать список на сервере и распределить элементы в двух столбцах таблицы (вы можете использовать CSS, чтобы сделать два столбца одинаковой ширины).

Примечание. Существуют расширения браузера для многостолбцовой разметки, но они не переносимы.

[РЕДАКТИРОВАТЬ] Мне известна статья о alistapart , но я не вижу разницы с моим решением: предлагаемый многостолбцовый макет дает каждому элементу фиксированную позицию (давая каждому элементу уникальный идентификатор CSS, а затем позиционирование его как-то). Это означает, что вам нужно сгенерировать HTML и отсортировать элементы на сервере, а затем использовать множество приемов для их позиционирования.

Гораздо проще использовать таблицу с двумя столбцами и помещать в них элементы во время рендеринга.

0 голосов
/ 03 мая 2014

Проблема со списком a-list, как я мог видеть, состоит в том, что если вы разделите список из 11 элементов на 2 столбца, я бы хотел, чтобы шестой элемент был в первом списке. Алиспарт, я думаю, помещает 11-й пункт вместо этого во второй столбец.

Мое исправление заключалось в использовании jQuery-Columns Plugin . Например, чтобы разделить ul с классом .mylist на 2 столбца, вы должны сделать

$(document).ready( function () {
  $('.mylist').cols(5);
});

Вот живой пример на jsfiddle

0 голосов
/ 10 июня 2009

Если вы можете разделить список с помощью небольшого javascript (что я не очень хорош), то это должно работать:

<script type="text/javascript">
var i=0;
var n=4;
if (i==0)
  {
document.write("<div id='listFlow'><ul>");
}
for (i=1;i<=15;i++)
{
if (i==n)
  {
document.write("<li>The number is " + i + "</li>" +"</ul><ul>");
var n=n+4;
  continue;
  }
document.write("<li>The number is " + i + "</li>");
}
document.write("</ul></div>");
</script>

<style type="text/css">
#listFlow ul{
float:left;
width:200px;
margin:0 0 0 10px;
padding:0;
}

#listFlow ul li{
list-style-position:inside;
list-style-type:disc;
margin:0;
padding:0;
width:180px;
}
</style>

Примечание. Пожалуйста, смотрите на CSS, а не на JavaScript. Это просто, чтобы показать, как списки могут течь, как описано.

0 голосов
/ 10 июня 2009

Одним из ваших критериев является чтение списка вниз, поэтому простое решение - это таблица из двух столбцов (@Aaron Digulla) с первой половиной списка в первом столбце и т. Д. ? Мы прибегли к этому методу для некоторых наших списков, так как мы не хотели редактировать наш CSS каждый раз, когда изменялся список (и мы не хотели помнить, чтобы редактировать классы в HTML).

Метод 1 в статье ALA был бы вторым самым простым решением (и более идеальным с точки зрения пуристов). Поскольку вы знаете текущий номер элемента и его количество, вы можете добавить логику, чтобы получить элементы списка в правильном порядке.

CSS может легко стилизовать любой метод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...