Pseudo element not full container width when border used

From the specification

The position and size of an element’s box(es) are sometimes calculated relative to a certain rectangle, called the containing block of the element. The containing block of an element is defined as follows:

….

  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.
    2. Otherwise, the containing block is formed by the padding edge of the ancestor

Then

The padding edge surrounds the box padding. If the padding has 0 width, the padding edge is the same as the content edge. The four padding edges define the box’s padding box.

This explain why your element doesn’t use the border-box as reference but the padding-box when positionned. It’s also the same for percentage width1. using width:100% means the padding and the content of the containing block. Border aren’t counted.


Concerning box-sizing

… , any padding or border specified on the element is laid out and drawn inside this specified width and height.

So the border need to belong to the element not a parent element in order to consider box-sizing which is not your case since the border isn’t applied to the pseudo element:


1 For absolutely positioned elements whose containing block is based on a block container element, the percentage is calculated with respect to the width of the padding box of that element.ref

.box {
  border:5px solid;
  padding:10px;
  background:red;
  min-height:100px;
  position:relative;
}
span:first-child {
  display:inline-block;
  width:100%;
  background:blue;
}
span:last-child {
  position:absolute;
  bottom:0;
  left:0;
  width:100%;
  background:green;
}
<div class="box">
  <span>I am a static element</span>
  <span>I am a absolute element</span>
</div>

An idea to obtain what you want is to use inset box-shadow instead of border:

.container {
  padding: 50px;
}

.button {
  box-shadow: inset 0 0 0 4px red;
  box-sizing: border-box;
  display: inline-flex;
  justify-content: center;
  align-items: center;
  height: 36px;
  padding: 0 16px;
  position: relative;
  z-index: 1;
}
.button::before {
  background-color: rgba(76, 255, 0, 0.8);
  box-sizing: inherit;
  content: "";
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  z-index: -1;
}
<div class="container">
    <a class="button">Button</a>
</div>

Leave a Comment