9

I was checking how Github display the below menu:

enter image description here

If you notice, each menu item is given an equal width. In CSS, we should give it any percentage value, what's the reason behind that? notice that the parent div is not given display: table property.

div {
  border: 1px solid #000;
  border-radius: 4px;
}

div ul {
  padding: 0;
  margin: 0;
}

div ul li {
  display: table-cell;
  width: 1%;
  text-align: center;
  border-right: 1px solid #000;
  padding: 10px 0;
}

div ul li:last-child {
  border-right: 0;
}
<div>
  <ul>
    <li><a href="#">Commits</a>
    </li>
    <li><a href="#">Branch</a>
    </li>
    <li><a href="#">Contribution</a>
    </li>
    <li><a href="#">anything</a>
    </li>
  </ul>
</div>

What's the reason behind the percentage width?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
shadeed9
  • 1,786
  • 5
  • 22
  • 29

2 Answers2

17

This has to do with how automatic table layout works. In particular:

A percentage value for a column width is relative to the table width. If the table has 'width: auto', a percentage represents a constraint on the column's width, which a UA should try to satisfy. (Obviously, this is not always possible: if the column's width is '110%', the constraint cannot be satisfied.)

In your case, you're setting a minuscule percentage width on every table-cell element. But the browser needs to ensure that the table-cells fill up the width of the table (which itself is as wide as its containing block), so it has to expand the cells to occupy as much space within the table as possible.

The reason why this results in approximately equal-width cells is because the percentage value is equal for all of them. If, for example, you set a slightly larger width for one of the cells, you'll see that it grows wider and the other cells become narrower to accommodate:

div {
  border: 1px solid #000;
  border-radius: 4px;
}

div ul {
  padding: 0;
  margin: 0;
}

div ul li {
  display: table-cell;
  width: 1%;
  text-align: center;
  border-right: 1px solid #000;
  padding: 10px 0;
}

div ul li:first-child {
  width: 3%;
}

div ul li:last-child {
  border-right: 0;
}
<div>
  <ul>
    <li><a href="#">Commits</a>
    </li>
    <li><a href="#">Branch</a>
    </li>
    <li><a href="#">Contribution</a>
    </li>
    <li><a href="#">anything</a>
    </li>
  </ul>
</div>

However, note that there is a slight difference because some cells have longer content than others, and the length of this content is accounted for when calculating the cell widths.

The reason why a value as small as 1% is used is so that you can continue to add cells and the browser will still try to distribute the available width as evenly as possible. You're essentially telling the cells that they don't need to be a certain width at minimum so you can add away (although technically, 1% is still something).

The fact that no elements are assigned display: table is inconsequential, because an anonymous table wrapper will be generated around the table-cells so that they can render correctly. This anonymous table wrapper functions exactly the same as an unstyled element with display: table, which means the table width is auto for the purposes of calculating percentage cell widths.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
3

This is something called the 1% width table hack.

This is because the table-cell inherits it's width from the parent div, allowing you to specify a related percentage of the cell width.

Here is a working demo on CodePen that you can play with and examine further.

http://codepen.io/ld0rman/pen/FCiLh

    <ul>
  <li><a href="#">One</a></li>
  <li><a href="#">Two</a></li>
  <li><a href="#">Three</a></li>
  <li><a href="#">Four</a></li>
  <li><a href="#">Five</a></li>
</ul>  

CSS:

  ul {
 list-style-type: none; 
 margin: 100px auto;
  width: 80%;
 }

 li {
   display: table-cell; 
   width: 1%;
    text-align: center;
    }

      a {
     display: block;
        border: 1px solid black;
      padding: 25px;
      text-decoration: none;
      color: white;
   text-transform: uppercase;
font-weight: bold;
background: grey;

 &:hover {
text-decoration: none; 
color: yellow;
background: darken(grey, 10%);
  }
   }

As you can see, it is coded similarly to your github example. Any more questions, ask away!

Sanova
  • 551
  • 3
  • 10
  • "This is because the table-cell inherits it's width from the parent div" How can it inherit the width when it's being specified as 1%? And why does it not act like 1% despite being specified as such? – BoltClock Jan 08 '15 at 17:58
  • 1
    Because if you look at the CSS, the **UL** tag has a width of 80% which is 80% the width of your screen. And the **LI** tag is the one that has 1%, so it is distributing 1% of the previously distributed 80% along with the space provided by the 25px padding on the content inside of the **LI** @BoltClock Table-cell makes it display like a cell in a table, thus distributing the weight of the content evenly. – Sanova Jan 08 '15 at 18:02
  • That's not inheritance, but OK. What about the question? There is no specified width, or any `display: table` for that matter. – BoltClock Jan 08 '15 at 18:03
  • That is inheritance. If the **UL** class was 10px, the **LI** would inherit this 10px, but now we are explicitly telling it to do 1% of THAT (because it inherited THAT), now we have placed 25px padding in it explicitly. For your question: there is a specified width. The code you provided doesn't show the parent's width because you've only included one CSS process. I inspected the same element on github. It has a responsive width. For my resolution the class showing the width is: .repository-with-sidebar.with-full-navigation .repository-content { width: 790px; @BoltClock – Sanova Jan 08 '15 at 18:09
  • If you just look at the codepen example i sent in my answer, you can change the width and percentage values as you see fit to get a better grasp on how the browser calculate the table-cell width based on the available parameters. It seems to me that you think it is more complicated than it is. @BoltClock – Sanova Jan 08 '15 at 18:11