Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Absolute positioning within inline elements. Is this behaviour correct?

Consider the following simple HTML and CSS

a.rel{
  position:relative;
}
button{
  position:absolute;
  top:0;
  left:0;
}
Lorem ipsum dolor sit amet
<a class="rel" href="https://www.google.co.uk">
  <img src=
   "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png">
  <button>I'm a button</button>
</a>

Now consider CSS2 10.1.4.1

  1. If the element has 'position: absolute', the containing block is established by the nearest ancestor with a 'position' of 'absolute', 'relative' or 'fixed', in the following way:

    1. In the case that the ancestor is an inline element, the containing block is the bounding box around the padding boxes of the first and the last inline boxes generated for that element. In CSS 2.1, if the inline element is split across multiple lines, the containing block is undefined.

or CSS3 3.1.2.2

  1. If the element has position: absolute, the containing block is established by the nearest ancestor with a position other than static, in the following way:

    1. In the case that the ancestor is inline-level, the containing block depends on the direction property of the ancestor:

      1. If the direction is ltr, the top and left of the containing block are the top and left content edges of the first box generated by the ancestor, and the bottom and right are the bottom and right content edges of the last box of the ancestor.

Doesn't this mean that the button should appear on top of the image to the top left? What part of the spec have I failed to understand when the button appears below the image?

like image 747
spender Avatar asked Aug 03 '16 17:08

spender


2 Answers

The height of an inline box (that is, a box generated by an element with display: inline) is determined by the strut, which is an imaginary box that's tall enough to contain text in the computed font-size. See §10.6.1 and §10.8.1, as well as the line-height propdef (although note that line-height determines the height of the line box on which the inline box appears, not the inline box itself).

Notably, an inline-level child does not affect the height of its parent inline box, even if that child is taller than the strut. The position of the button is therefore relative to the strut of the a element. This also means that the position of the button would be the same if the image were not present to begin with:

a.rel{
  position:relative;
}
button{
  position:absolute;
  top:0;
  left:0;
}
Lorem ipsum dolor sit amet
<a class="rel" href="https://www.google.co.uk">
  <!-- img src=
   "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png" -->
  <button>I'm a button</button>
</a>

(The button is now horizontally closer to the text because there is no other in-flow content left in the a element besides the inter-element whitespace, which ends up being collapsed. However, its vertical position remains the same.)

Here, I've added some horizontal padding to the a element, given both it and the preceding text a background, and made the button semitransparent to show that the height of the inline box is indeed the height of the strut:

span{
  background-color:#f00;
}
a.rel{
  position:relative;
  background-color:#00f;
  padding:0 1em;
}
button{
  position:absolute;
  top:0;
  left:0;
  opacity:0.5;
}
<span>Lorem ipsum dolor sit amet</span>
<a class="rel" href="https://www.google.co.uk">
  <!-- img src=
   "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png" -->
  <button>I'm a button</button>
</a>

You can see part of the inline box peeking out from the corners of the button on certain browsers; I cannot explain that beyond "different browsers render inlines differently" unfortunately.

Note also that the button isn't exactly appearing below the image. If you give the image an outline you'll see that the button isn't adhering to the bounds of the image at all (it shouldn't try to; after all, it's absolutely positioned):

a.rel{
  position:relative;
}
button{
  position:absolute;
  top:0;
  left:0;
}
img{
  outline:thin solid;
}
Lorem ipsum dolor sit amet
<a class="rel" href="https://www.google.co.uk">
  <img src=
   "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png">
  <button>I'm a button</button>
</a>
like image 143
BoltClock Avatar answered Sep 29 '22 07:09

BoltClock


The button IS on the top-left of the link. You're mistaken, however, about the size of the link. As a has display inline by default, its size doesn't increase by the size of the img, instead its just the line-height (determined by the font size).

If you increase the font-size of the link element, the button will therefore go up.

You may use the dev tools to easily view the exact dimensions of the link element.

like image 37
MattDiMu Avatar answered Sep 29 '22 06:09

MattDiMu