5

I have <ul> element which is a flex items. This <ul> element contains several <li> elements which are not flex items. When I add percentage paddings to <li> elements then <ul> element is split in several lines like in the photo: enter image description here

When I set fixed paddings (like 30px) the <ul> element is displayed in one line: enter image description here

So, my question is: Why percentage paddings make <ul> behave this way? P.S: I don't need solutions to fix it, I just need an explanation of the behaviour

li {
  display: inline-block;
  padding: 0 5%;
  /* padding: 0 30px; */
  border: 1px solid black;
}

header {
  display: flex;
}

ul {
  border:1px solid red;
}
<header>
  <ul>
    <li>Library</li>
    <li>Telegram channel</li>
    <li>Contacts</li>
    <li>Donate</li>
  </ul>
</header>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
Roman Roman
  • 807
  • 9
  • 26
  • 1
    something similar that happen with CSS grid : https://stackoverflow.com/questions/53355708/css-grid-unnecessary-word-break/53355848#53355848 .. basically (as per my analysis) percentage padding are considered later so they reduce the width initially calculated – Temani Afif Nov 29 '18 at 10:12
  • 2
    @Jeremy flexbox see the padding, try to use px instead of % and the behavior will be different. The issue appear only with % – Temani Afif Nov 29 '18 at 10:20
  • @TemaniAfif Oh I didn't realize, just blindly followed that post. – Jeremy Nov 29 '18 at 10:27

1 Answers1

2

As I explained in a previous similar situation there is a kind of complex calculation involved here. Padding used with percentage value will be relative to the width of the containing blockref and logically the width of the containing block will be defined by its content (or any fixed width value).

In our case, we cannot resolve percentage value of padding before calculating the width, so we first caclulate the width based on our content to obtain this:

console.log(document.querySelector('ul').offsetWidth);
li {
  display: inline-block;
  border: 1px solid black;
}

header {
  display: flex;
}

ul {
  border:1px solid red;
  margin:0;
  padding:0;
}
<header>
  <ul>
    <li>Library</li>
    <li>Telegram channel</li>
    <li>Contacts</li>
    <li>Donate</li>
  </ul>
</header>

Then we will consider the above calculated width in order to calculate the padding

After that, the padding will logically be added to the width which will increase the overall width and create the line break. The browser won't go back to re-caclulate the width of the ul again because we will have a cycle, so the calculation is done only once.

console.log(document.querySelector('ul.pad').offsetWidth);
li {
  display: inline-block;
  border: 1px solid black;
}
.pad li {
  padding:0 0.5%; /*any small value will create the issue*/
}

header {
  display: flex;
}

ul {
  border:1px solid red;
  margin:5px;
  padding:0;
}
<header>
  <ul>
    <li>Library</li>
    <li>Telegram channel</li>
    <li>Contacts</li>
    <li>Donate</li>
  </ul>
</header>
<header>
  <ul class="pad">
    <li>Library</li>
    <li>Telegram channel</li>
    <li>Contacts</li>
    <li>Donate</li>
  </ul>
</header>

We can clearly notice how in both case the width of the ul is exactly the same.

This won't happen with pixel values because they are absolute values that the browser can include in the initial calculation.

li {
  display: inline-block;
  border: 1px solid black;
}
.pad li{
  padding:0 30px; 
}

header {
  display: flex;
}

ul {
  border:1px solid red;
  margin:0;
  padding:0;
}
<header>
  <ul>
    <li>Library</li>
    <li>Telegram channel</li>
    <li>Contacts</li>
    <li>Donate</li>
  </ul>
</header>
<header>
  <ul class="pad">
    <li>Library</li>
    <li>Telegram channel</li>
    <li>Contacts</li>
    <li>Donate</li>
  </ul>
</header>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • It is not an UL, it is a section with articles inside. Now, I see that the grid Parent and Grid Child have different size, i don't know why – Jesús Bohorquez Jun 03 '20 at 21:30