Tanmay Lodha
Tanmay Lodha

Reputation: 27

Position:absolute; left property not working correctly

In the following codepen - https://codepen.io/tanmaylodha/pen/MWKXJWW CSS:Line-26; the left:50% is not working correctly. But if I set display:inline-block on the containing block .section-first a of absolutely positioned element .badge then it works fine.

    <section class="section section-first">
   <a href="#">
     <h1 class="badge">Recommended</h1>
     <h1 class="plus-plan">Our PLUS Plan</h1>
     <h2>The most popular choice of our customers.</h2>
     <p>
       Benefit from increased storage and faster support to ensure that
       your mission-critical data and applications are always available!
     </p>
   </a>
 </section>

.section {
  color: #6c6164;
  background-color: #f7fafd;
  padding: 1.563rem;
  margin-bottom: 1.563rem;
  border: 5px solid #fca156;
  margin-right: 12.5rem;
  box-shadow: inset 5px 5px 10px 2px #4fbf99;
}

.section-first {
  margin-top: 8rem;
}

.section-first a {
  position: relative;
}

.badge {
  font-family: "Red Hat Display";
  background-color: #60a7bd;
  padding: 0.625rem;
  border-radius: 5px;
  margin: 0%;
  position: absolute;
  left: 50%;
}

.section h1.badge {
  color: white;
}

.section-first .plus-plan {
  margin-top: 50px;
}

.section-highlighted {
  margin-left: 200px;
  margin-right: 0px;
  box-shadow: inset 5px 5px 10px 2px #4fbf99, 5px 5px 10px 2px #60a7bd;
  text-align: right;
}

.section:hover {
  border-color: #ff943c;
}

.section a {
  text-decoration: none;
}

Now check this codepen - https://codepen.io/tanmaylodha/pen/jOWKyZP But here the results are different. .child being absolutely positioned element is getting correctly positioned after 50% width of its containing block .parent

 <a href="" class="parent">
  I am a Parent
  <div class="child">
    I am a child
  </div>
</a>

.parent {
  position: relative;
  background-color: chocolate;
}
.child {
  position: absolute;
  background-color: darkgreen;
  left: 50%;
}

In both the above Codepen, the containing block(being positioned relative) is always an inline element, then why the results are different?

Upvotes: 1

Views: 2357

Answers (2)

Temani Afif
Temani Afif

Reputation: 272772

To make the issue more clear here is the minimal code that illustrate the difference:

.parent {
  position: relative;
  background-color: chocolate;
}

.child {
  position: absolute;
  background-color: darkgreen;
  left: 50%;
}
<a href="" class="parent">
      I am a Parent
      <div class="child">
        I am a child
      </div>
    </a>
<br><br><br><br><br>
<a href="" class="parent">
  <div>I am a Parent</div>
  <div class="child">
    I am a child
  </div>
</a>

Note how in the first case you have text content inside your inline element so your element is having a width used as reference for the left property. In the second case, you have a block element inside an inline element and this one is now having a width equal to 0 (no background coloration) and this is what you are facing in your first code. left:X% of 0 is 0 so nothing will happen.

What you are doing is of course valid but having block element inside inline element will make the rendring a bit tricky. From the specification you can read:

When an inline box contains an in-flow block-level box, the inline box (and its inline ancestors within the same line box) are broken around the block-level box (and any block-level siblings that are consecutive or separated only by collapsible whitespace and/or out-of-flow elements), splitting the inline box into two boxes (even if either side is empty), one on each side of the block-level box(es). The line boxes before the break and after the break are enclosed in anonymous block boxes, and the block-level box becomes a sibling of those anonymous boxes. When such an inline box is affected by relative positioning, any resulting translation also affects the block-level box contained in the inline box.

Yes not easy to understand but let's take our example and add more CSS to better see:

.parent {
  position: relative;
  background-color: chocolate;
  border:2px solid red;
}
some text before<br>
<a href="" class="parent">
  <div>I am a Parent</div>
</a>
<br> some text after

You can see how the block element broke our inline element in two chunks that are empty.

To avoid dealing with this, avoid having block element inside inline elements. Use inline-block to fix this issue:

.parent {
  position: relative;
  background-color: chocolate;
  border:2px solid red;
  display:inline-block;
}
some text before<br>
<a href="" class="parent">
  <div>I am a Parent</div>
</a>
<br>
some text after

Upvotes: 2

Rayees AC
Rayees AC

Reputation: 4659

Please use this...

.section-first {
  position: relative;
}

Instead of the below style.

.section-first a {
  position: relative;
}

The <div> tag is a block level element. The <a> tag is tag is an inline element.

Upvotes: 0

Related Questions