Как я могу сделать отступ для каждого сиблинга в структуре ul> li?

#html #css

Вопрос:

У меня есть простая структура, которая представляет родительские элементы текущей навигации (например, хлебные крошки).

 ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

ul > li {
  padding: 0;
  margin: 0;
  display: flex;
}

ul > li ~ li:before {
  content: '⤷';
  display: inline-block;
  padding: 0 5px;
}

/* I want to make this part dynamic to cover an infinite amount of child nodes: */
ul > li ~ li ~ li {
  padding-left: 20px;
}

ul > li ~ li ~ li ~ li {
  padding-left: 40px;
}

ul > li ~ li ~ li ~ li ~ li {
  padding-left: 60px;
} 
 <ul>
<li>Parent #1</li>
<li>One more parent</li>
<li>Another parent</li>
<li>A very long item with potential page break,<br /> br tag just used as an example</li>
<li>Current item</li>
</ul> 

Как я могу сделать левое заполнение каждого сиблинга li на 20 пикселей больше по сравнению с предыдущим сиблингом? Я не могу изменить html и не могу использовать javascript.

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

Комментарии:

1. У вас всегда будет ровно 4 li или их будет произвольное количество?

2. @RoddyoftheFrozenPeas Целью является бесконечное / неизвестное количество дочерних элементов. Ограничение в четыре работает без каких-либо изменений.

3. Я бы вложил <ul> их внутрь каждого <li> , этот способ был бы более семантическим

Ответ №1:

Вы можете использовать счетчик, используя system «symbolic».

Во фрагменте я использовал видимый символ, чтобы показать, как это работает.

Замените это символом Unicode, эквивалентным пробелу, и он будет работать.

 @counter-style pad {
 system: symbolic;
 symbols:" ";   /* unicode U 2003 */
 suffix: " ";
}


ul {
  list-style: none;
  padding: 0;
  margin: 0;
  counter-reset: section;  
}

ul > li {
  padding: 0;
  margin: 0;
  display: flex;
}

ul > li:nth-child(even):before {
  counter-increment: section;  
  content:  counter(section, pad) '⤷';
  display: inline-block;
  padding: 0 5px 0 0;
  font-size: 20px;
 
}

ul > li:nth-child(1):before {
   padding: 0px 5px 0px 20px;
  content: '⤷';
  display: inline-block;
}

ul > li:nth-child(3):before {
   padding: 0px 5px 0px 40px;
  content: '⤷';
  display: inline-block;
}
ul > li:nth-child(5):before {
   padding: 0px 5px 0px 60px;
  content: '⤷';
  display: inline-block;
}
ul > li:nth-child(7):before {
   padding: 0px 5px 0px 80px;
  content: '⤷';
  display: inline-block;
}
ul > li:nth-child(9):before {
   padding: 0px 5px 0px 100px;
  content: '⤷';
  display: inline-block;
} 
 <ul>
<li>Parent #1</li>
<li>Parent #1</li>
<li>One more parent</li>
<li>One more parent</li>
<li>Another parent</li>
<li>Another parent</li>
<li>A very long item with potential page break,<br /> br tag just used as an example</li>
<li>A very long item with potential page break,<br /> br tag just used as an example</li>
<li>Current item</li>
<li>Current item</li>
</ul> 

Другая возможность — использовать пробелы в качестве символа и установить ‘пробел: pre’ на псевдо перед:

 @counter-style pad {
 system: symbolic;
 symbols: '      ';
 suffix: " ";
}


ul {
  list-style: none;
  padding: 0;
  margin: 0;
  counter-reset: section;  
}

ul > li {
  padding: 0;
  margin: 0;
  display: flex;
}

ul > li ~ li:before {
  counter-increment: section;  
  content:  counter(section, pad) ' ⤷';
  white-space: pre;
  display: inline-block;
  padding: 0 5px;
} 
 <ul>
<li>Parent #1</li>
<li>One more parent</li>
<li>Another parent</li>
<li>A very long item with potential page break,<br /> br tag just used as an example</li>
<li>Current item</li>
</ul> 

Комментарии:

1. Или просто используйте color: transparent для символов, чтобы они не были видны.

2. @SalmanA да, конечно. Но использование пробелов кажется более «семантическим», чем использование некоторого прозрачного текста. (не то, чтобы я сильно заботился о семантике, но ..)

3. Я принял это как ответ. Это не позволяет добавлять точное заполнение и зависит от размера рендеринга шрифта. Я еще не играл с этим, но, возможно, его можно комбинировать с атрибутом межбуквенного интервала и идеальным количеством пробелов с нулевой шириной. Таким образом, рендеринг шрифта не имеет значения. Я не знаю, применяется ли интервал между буквами к пробелам нулевой ширины.

4. Я отредактировал первый фрагмент. li дублируются, один использует счетчик для отступа, другой использует жестко заданное заполнение. Они выглядят практически одинаково. Я использовал Юникод «EM space», который должен иметь размер 1em.

Ответ №2:

Используйте float: left;

 ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

ul > li {
  padding: 0;
  margin: 0;
}

ul > li:before {
  content: '⤷';
  display: inline-block;
  padding: 0 5px;
  
  float: left;
} 
 <ul>
  <li>Parent #1</li>
  <li>One more parent</li>
  <li>Another parent</li>
  <li>Current item</li>
  <li>Another item</li>
  <li>Another item</li>
  <li>Another item</li>
  <li>Another item</li>
  <li>Another item</li>
  <li>Another item</li>
</ul> 

Комментарии:

1. Хорошо, это отличный трюк. Но это работает только в том случае, если текст :before находится выше текста элемента. Если в тексте элемента есть вторая строка, весь макет прерывается. Но я сохраню эту идею.

2. @Lundstromski Хороший трюк, но, я думаю, у него есть некоторые ограничения, например, если вы укажете border lis , макет будет нарушен.

Ответ №3:

Поскольку в уведомлении о вознаграждении упоминается:

Если это невозможно сделать с использованием текущих функций css, пожалуйста, сообщите мне о текущих черновиках или предстоящих функциях.

Я хотел бы упомянуть, что существует запрос функции для включения использования counter() внутри calc(), который также упоминается в черновиках. Если это будет реализовано, будет работать следующее:

 ul {
  padding: 0;
  margin: 0;
  counter-reset: child-counter;
}
ul li {
  display: flex;
  gap: .5em;
  counter-increment: child-counter;
}
ul li:nth-child(n   2)::before {
  content: "⤷";
  /* this won't work now but may be in the future */
  margin-left: calc(1em * counter-value(child-counter));
}
ul li:nth-child(n   2)::after {
  content: "(counter = " counter(child-counter) ")"
} 
 <ul>
  <li>Parent #1</li>
  <li>One more parent</li>
  <li>Another parent</li>
  <li>A very long item with potential page break,<br /> br tag just used as an example</li>
  <li>Current item</li>
</ul>