Confusion regarding percentage width size of hyperlink

<ul>
  <li><a href="#">Home</a></li><li><a href="#">Pizza</a></li><li><a href="#">Music</a></li><li><a href="#">Wombats</a></li><li><a href="#">Finland</a></li>
</ul>

in css



body,html {
  margin: 0;
  }

ul {
  padding: 0;
  width: 100%;
}

li {
  display : inline;
}

a {
  outline: none;
  text-decoration: none;
  display: inline-block;
  width: 19.5%;
  margin-right: 0.625%;
  text-align: center;
 
  color: black;
}

a:link, a:visited, a:focus {
  background: yellow;
}

li:last-child a {
  margin-right: 0;
}

margin body ,html zero

So width of html = width of body= width of viewport .

ul =100 percent width of its parent body. Now parent of ul i.e body has no width explicitly in pixels although width of body is width of viewport with no horizontal scrollbar




  • Q: width of anchor element in pixel= (19.5/100)* width of li ??
    But width of li has not been mentioned in pixels??

But parent of li i.e ul it’s width has been mentioned .

width of ul as seen from dev tools is same as width of the body (as mentioned 100percent )



As seen from dev tools width of body tag is coming 241.12px
and As seen from dev tools width of anchor tag is coming 47.02px Which is exactly 19.5 percent of body which is not a direct parent of anchor tag but it is considering the width either of the body or ul element as its relative measurement source of pixels out of which 19.5 % is considered.

width of li = (Width of anchor element + right margin of anchor element.)

Width of ul=width of Body

What is happening? When the width of anchor is given as a percentage value then it is searching for some pixel value among its ascendant so it goes to li it sees that its width value has not been mentioned so it then goes one parent above to ul and finds that ul has width equal to viewport so it considers 19.5% of width of ul?

Percentage widths refers to the width of the nearest ancestor that satisfies the condition to be called a containing block. If no such ancestor exists then the initial containing block is used (the root element).

Your list (li) element has a display of inline and therefore does not count as a containing block for block or inline-block descendants. Therefore the containing block is the ul and the percentage width is based on this element’s computed width (it does not need a width applied). The width:100% on the ul is irrelevant (and indeed not needed in this case) as it will automatically fill its containing block anyway.

The rules for block containers and block formatting contexts are complicated and varied so rather than explain them I shall point you towards the specs.

https://www.w3.org/Style/css2-updates/css2/visudet.html
https://www.w3.org/Style/css2-updates/css2/visuren.html#block-boxes

As an aside you should know that display:inline-block elements are treated like words and you will get a gap between each ‘word’ just like you would in a sentence. That means that 5 x20% will not fit in a 100% container because there will also be 4 gaps between the elements (based on the current font-size).

4 Likes

Well you have specified that list items li are to be treated as inline elements. Meaning their width is going to be set at auto and will take the width of whatever they contain. So in this case, your anchor tags are going to look to the UL to know 19.5% of what? Since the UL is the width of the body at 100% it is making each list item 19.5% of 100%.

If you made the li a display block (which they are normally), then would be also 100% by default (aka computed) and your links would be 19.5% of those.

So generally you should think of percentages as percentage of their parent block. The spec refers to this as the parent’s containing block. However in the case that you make the parent block not a block and instead inline, it goes up to the next block since parent doesn’t know its width. Because if you are saying “hey you are 19.5% of your container, but your container is saying it is inline and hence has no defined width, so you have to go to an element that has some width… either specified OR computed

At least that is how I generally look at it all.

In general, because of the trickiness of percentage widths in instances just like this, I generally use percentage for major element layout only and use relational units (like REM) for individual components. But it all depends on what you are building.

2 Likes

https://stackoverflow.com/questions/18585069/why-anchor-tag-does-not-take-height-and-width-of-its-containing-element#:~:text=The%20height%20of%20the%20content,block%20size%20plays%20any%20part.&text=The%20’width’%20property%20does%20not%20apply.

Here i have two questions

The elements are being laid out in a line box in a inline context, so the spaces at the start of the first <a> element and at the end of the second <a> element are being dropped.

  • What if the element was not laid out in a line box in a inline context then will the space before a and end of a be considered?
    What is he saying about the space before <a> element and end of a element. Does that meant to show up when anchor tags are used?

"The spaces at the end of the first a> element and the start of the second <a element are being collapsed into one space"

That means there is supposed to be two spaces in between but due to collapsing concept it is not happening ? But why there will be two spaces coz the first anchor tag element code itself contains a space before closing tag of anchor :

<a href="#"> <img class="normal" src="">  </a>

And there will be a additional space between two anchor elements which is Natural .
Thats why there is supposed to be two spaces after first anchor tag and before second anchor tag

There’s an in-depth article here that answers most of your questions.

https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Whitespace

If the anchor is made into a block element then whitespace at the beginning and the end will be ignored. (Indeed as the end of a block element is a newline there would be no way of knowing if there was a space there or not.)

You can’t have 2 spaces in a row even across inline elements (unless mixing ltr and rtl text in the same line). They are collapsed into one space.

Html is not to be used for appearance as that is the job of CSS. If you want space at the beginning and the end of something then that’s what padding is used for.

White space in html is basically only honoured for one space between words (or inline or inline-block content) . There will be browser variations on this which is why its best never to rely on whitespace other than for separating text or inline images.

4 Likes

After that, any space immediately following another space (even across two separate inline elements) is ignored, so we end up with:

I was seeing this from the link given above :
If i follow this rule any space immediately following another space is ignored then the code
<h1>◦◦◦Hello◦<span>◦World!</span>◦◦◦</h1>

before hello there are three spaces so the second space gets ignored
So it look like this <h1>◦◦Hello◦<span>◦World!</span>◦◦◦</h1>

Now the third space will also get ignored as it is immedeately fllowing 1st space so it looks this
<h1>◦Hello◦<span>◦World!</span>◦◦◦</h1>
There is only one space before Hello .

Same thing happens with three spaces before closing tag of h1
SO finally we get
<h1>◦Hello◦<span>◦World!</span>◦</h1>

h1 is a block element and span is a inline element .
Now the space before World! gets disappeared but the space is not immediately following another space . Why this is happening? Does the inline element span is being ignored by the rendering engine?


What does this part mean " even across two separate inline elements" ?

No spaces at the start and end of a line are removed also.

  1. And finally, sequences of spaces at the beginning and end of a line are removed, so we finally get this:
<h1>Hello◦<span>World!</span></h1>

It means a construct like this.

<span> test </span> <span> testing </span>

The space at the beginning of the first span is removed if its the first element on the line.
The space before the end of the first span closing tag is honoured.
The space after the first closing span is ignored and so is the space at the start of the next opening span.
The space after testing is also ignored if that last span is the last thing on the line.

You can see those behaviours in this pen.

Play around and you will soon see how each is handled.:slight_smile:

No, you lose the start and end spaces and end up with this:

<h1>Hello◦<span>World!</span></h1>

I was going through this link https://javascript.info/dom-nodes which has connection to the OP . I found this code below and

<!DOCTYPE HTML>
<html>
<head>
  <title>About elk</title>
</head>
<body>
   The truth about elk.
</body>
</html>

I am not introduced to javascript and i am in the beginning of css course .

  1. Should n’t there be a line break after body> tag and some spaces before the text inside body tags & also a line break after the text - all these should be included as text node in dom tree


As i can see there is a line break and two spaces which is correctly considered in the DOm tree which is between head and title tag.
So any white space character will be considered under the text node when prsent between two different tags(here the white space character is btwn opening tag of head and title ). Something like that?

As i also see that the line break btwn closing tag of title and closing tag of head is being considered in the dom tree so with that logic (as per me) why there is no line break after the text “The truth about elk.”







3. Why the Dom tree doesn’t include line feed that should be there after closing tag of body Between closing tag of body and html.That’s
coz
Soln to second doubt:

If we put something after </body> , then that is automatically moved inside the body , at the end, as the HTML spec requires that all content must be inside <body> . So there can’t be any spaces and so line breaks are ignored after </body>
right?

This is the CSS forum and JS DOM node traversal would be a question for the JS forum. :slight_smile:

How Javascript sees the DOM is beyond the remit of the CSS forum and indeed is not related to your original topic (which was about the percentage width of a hyperlink). These types of question would seem more pertinent to someone who was trying to build a browser rather than trying to code a webpage.

JS will see the DOM differently to CSS because html and CSS discount certain whitespace nodes although they are actually still there in the DOM. That’s how (in most cases) you can format the html without it affecting the appearance of the display. In the end all you basically need to know is that you can’t code a webpage whilst relying on whitespace for anything other than a single space between words (or inline equivalents).

I suggest you re-phrase your post any make any in-depth JS related questions in the JS forum.

If you have an actual practical CSS question that you would like answered or a layout you can’t achieve then fire away but raise a new topic for your question if it is not related to the percentage width of a hyperlink.

@torresjit100, CSS and Javascript are NOT straight forward as one would like.

Here are some quick take aways tho, for future readers of this post.

  1. inline elements do not have explicit dimensions (height/width)
    1.b) inline elements do not count as container blocks
  2. 100% width of a child = the width of the containing block ( minus any padding of the containing block)
  3. white spaces collapse, so " " = " "
    3.a)this will happen in the dom to as contiguous text is treated as one node
    3.b)SINGLE white spaces remain between any inline ( or inline-block ) elements that have spaces between them.

Trying to answer your question tho, sometimes tho it’s better to post your intent than your methodology, so am going to guess that your desired outcome was a horizontal menu with buttons of equal length ( which you figured to be (19.5%…and not 20%).

really the best way to do this would be to use flexbox:

<html>
	<head>
		<title> </title>
		<style type="text/css" media="screen">
			.hz-nav{
				
			}
			.hz-nav > ul{
				margin: 0 -.5em;
				padding: 0;
				display:flex;
				list-style: none;
			}
			.hz-nav  ul >  li{
				flex: 1 1 0;
				padding: .5em
			}
			.hz-nav >ul > li > a{
				display:block;
				padding: .5em;
				background: #ccc;
				text-align: center;
				border-radius: 4px;
			}
		</style>
	</head>
	<body>
		<nav class="hz-nav">
		<ul >
  <li><a href="#">Home</a></li><li><a href="#">Pizza</a></li><li><a href="#">Music</a></li><li><a href="#">Wombats</a></li><li><a href="#">Finland</a></li>
</ul>
		</nav>
	</body>

hope that helps

1 Like