How can I indent every sibling in an ul > li structure?

Viewed 215

I have a simple structure that represents the parents of current navigation (like breadcrumbs).

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>

How can I make the left padding of each li sibling 20px extra compared to the sibling before? I cannot change the html and I cannot use javascript.

Edit: The item text can have one or more lines (automatic word break, if the subject is to long). I've modified the example to cover the case where a line break occurs.

3 Answers

You can use a counter, using system "symbolic".

In the snippet, I have used a visible symbol to show how it works.

Replace this with an Unicode symbol that is equivalent to whitespace, and you will have it working.

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

Another possibility is to use spaces as symbol, and set 'whitespace: pre' on the pseudo before:

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

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

Since the bounty notice mentions:

If it cannot be done using current css features please tell me about current drafts or upcoming features.

I would like to mention that there is a feature request to enable the use of counter() inside calc() which is mentioned in drafts as well. If implemented, the following would work:

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>

Related