0

I've created an anchor with a ::before pseudo-element used for an SVG icon. When ::before is both position: relative and positioned with either a negative value when using top/left or a positive value when using bottom/right, the text-overflow: ellipsis functionality breaks.

a {
  display: block;
  border: 1px solid blue;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
  width: 200px;
}

a::before {
  content: '';
  display: inline-block;
  width: 20px;
  height: 20px;
  border: 1px solid red;
  position: relative;
}

a.test2::before, a.test3::before {
  left: -1px;
}

a.test3::before {
  position: absolute;
}
<a class="test1">some very long text which overflows</a>
<a class="test2">some very long text which overflows</a>
<a class="test3">some very long text which overflows</a>

For example, the text should overflow and get an ellipsis in each of these examples but the second one breaks (at least in Chrome 61, macOS).

It seems that Firefox 56 on mac does not have this issue.

Using position: absolute or some other variations solve the issue, but I can't find much explanation for why this happens.

enter image description here

helion3
  • 34,737
  • 15
  • 57
  • 100

1 Answers1

-1

Pseudo-elements have a default position of static, much like regular elements. Applying any form of offset (such as with left) on a statically-positioned has no effect. However, you are explicitly applying a position of relative to these three pseudo-elements. Relatively-positioned elements "remain in the normal flow of the document", and are relative to their parent's offsets; their offset calculations apply after taking the parent offset into consideration.

Critically, <body> has a default margin of 8px. Unless you explicitly change this margin, a direct child element with relative positioning will have a default left of 8px. As such, your first element is offset by 8px, and your second element is offset by 7px (8px minus the manually-specified left: 1px).

Once you apply a position of absolute, this position is "relative to its nearest positioned ancestor (i.e., the nearest ancestor that is not static). If a positioned ancestor doesn't exist, the initial container is used". In your case, that's <body>.

Absolute positioning ignores parental padding. There's a great answer on why this happens here, but in short, position: absolute makes the containing box the parent's padding box rather than the content box. As such, the third pseudo-element has a (theoretical) default left offset of 0px. However, this is not applied by default; left must be manually specified in order to take affect. Manually specifying left: -1px applies the offset, and gives it an offset of 1px left of <body>.

Hope this helps explain why this is happening! :)

Obsidian Age
  • 41,205
  • 10
  • 48
  • 71
  • Your explanation does not appear relevant to the calculation of the text-overflow. The containing element is irrelevant because this can reproduced regardless of the margin/padding of the `body`, in fact the real-world issue we have is far deeper than `body > a`. I personally already understood how positioning works but this answer doesn't address why the text-overflow no longer applies despite the text *still obviously overflowing*. – helion3 Oct 23 '17 at 22:11
  • The box is positioned to the left because is the offset of the parent that is taken into consideration for `position: absolute`. If you have hierarchical issues at a deeper level, it's because you're either not specifying `position` on the parent elements, or you're adding either `padding` or `margin`. As for the text not overflowing, that seems to be a quirk of both occupying space and having an offset on the element you're trying to truncate. Either remove `position: absolute` from the pseudo-element or add `position: relative` to the container to resolve that. – Obsidian Age Oct 23 '17 at 22:33
  • Maybe I wasn't clear with my post but I'm not asking about positioning, I have full understanding of how positioning works. In reply to the only question I have, you say it "seems to be a quirk", that's not helpful. – helion3 Oct 23 '17 at 22:59
  • Fair enough, but I would argue that the overflow problem was not immediately "*obvious*", as I initially thought your problem was with the boxes not lining up when there was text-overflow. If you're not happy with my "*not relevant*" explanation of a quirk in using `text-overflow` with absolutely-positioned pseudo-elements, then use **`relative`** pseudo-elements (as I **stated** in my "*not helpful*" answer). Why you wouldn't **want** relative pseudo-elements is beyond me... – Obsidian Age Oct 23 '17 at 23:14
  • I never said I didn't want to, and in fact I originally posted that I knew of workarounds, but my question states that I'm looking for an "explanation for why this happens". I dislike solving problems when I can't identify their cause. – helion3 Oct 23 '17 at 23:24