Why is '::after' pseudo-selector over the image and not under it? [duplicate]

情到浓时终转凉″ 提交于 2020-12-13 03:28:55

问题


I have this container with some text and an image inside it as last element, I am trying to set an ::after to my container, however it is being shown over the image and not as the last element of the container:

I understand that I can't set a pseudo-selector to an <img/>, but here I am setting ::after to the container and I don't get why it isn't working properly.

Why is this happening and how could I make ::after actually the last element of testDiv?

P.S. I can't set the container or any parent element with position: relative, since I need ::after to have the same width as the screen and not just to fit inside the container and I don't have any element with the same width as the screen.

P.S. The margin-left:100px is just to make it easier to be seen in the snippet, therefore it doesn't matter to my purpose.

.testDiv > div::after {
  position: absolute;
  height: 2px;
  content: "";
  background-color: red;
  left: 0;
  right: 0;
}

.testDiv > div {
  margin-left: 100px;
}
<div class="testDiv">
    <div>
      <h1>TEST</h1>
      <h2>TEST</h2>
      <img src="https://www.acmetek.com/wp-content/uploads/rapidssl-logo.png" />
    </div>
</div>

回答1:


As far as I can see, neither existing answer actually address the question of why the line is over, not under the image. The reason can be found in CSS 2.2 Section 10.6.4. Absolutely positioned, non-replaced elements where it says if:

top and bottom are auto and height is not auto, then set top to the static position, set auto values for margin-top and margin-bottom to 0, and solve for bottom

and

the static position for top is the distance from the top edge of the containing block to the top margin edge of a hypothetical box that would have been the first box of the element if its specified position value had been static and its specified float had been none and its specified clear had been none.

Which means that the top of the absolute positioned box will be the top of where the box would have been had not been position:absolute.

Since both the img and the ::after pseudo element without position:absolute are display:inline they would have lined up alongside one another. The pseudo element taken out of the flow and stretched horizontally to meet the left:0;right:0 requirements.

What this means is that you can move the red line to below the img just by making the ::after pseudo element display:block.

This is quite an interesting effect given that we normally think of position:absolute blockifying the box anyway, but this only happens after the static position calculation.

Another solution, perhaps a little more intuitive, is to make the img element display:block.

.testDiv > div::after {
  position: absolute;
  height: 2px;
  content: "";
  background-color: red;
  left: 0;
  right: 0;
  display:block;
}

.testDiv > div {
  margin-left: 100px;
}
<div class="testDiv">
    <div>
      <h1>TEST</h1>
      <h2>TEST</h2>
      <img src="https://www.acmetek.com/wp-content/uploads/rapidssl-logo.png" />
    </div>
</div>



回答2:


You can still use position:relative but have your element overflow from both sides:

.testDiv>div::after {
  position: absolute;
  height: 2px;
  content: "";
  background-color: red;
  left: -100vw; /* big value here */
  right: 0;
  bottom: 0;
  box-shadow: 100vw 0 0 red; /* big value here too*/
}

.testDiv>div {
  margin-left: 100px; /* we have a margin */
  width: 200px; /* and a width too */
  position: relative;
}
<div class="testDiv">
  <div>
    <h1>TEST</h1>
    <h2>TEST</h2>
    <img src="https://www.acmetek.com/wp-content/uploads/rapidssl-logo.png" />
  </div>
</div>
<div class="testDiv">
  <div>
    <h1>Another one </h1>
    <h2>TEST</h2>
    <img src="https://www.acmetek.com/wp-content/uploads/rapidssl-logo.png" />
  </div>
</div>



回答3:


Given your comment

It doesn't solve my problem, since I need the ::after to have the width of the screen and not only of the container

You need to set position:relative to .testDiv parent and also add bottom:0 and width:100% to the pseudo element

.testDiv {
  position: relative
}

.testDiv>div {
  margin-left: 100px;
}

.testDiv>div::after {
  position: absolute;
  height: 2px;
  content: "";
  background-color: red;
  left: 0;
  bottom: 0;
  width: 100%
}
<div class="testDiv">
  <div>
    <h1>TEST</h1>
    <h2>TEST</h2>
    <img src="https://www.acmetek.com/wp-content/uploads/rapidssl-logo.png" />
  </div>
</div>

UPDATE - based on your comment

you will need either set bottom: (any value)(any unit you need) or top: (any value)(any unit you need)

.testDiv>div::after {
  position: absolute;
  height: 2px;
  content: "";
  background-color: red;
  left: 0;
  bottom: 50px;
  width: 100%
}
<div class="testDiv">
  <div>
    <h1>TEST</h1>
    <h2>TEST</h2>
    <img src="https://www.acmetek.com/wp-content/uploads/rapidssl-logo.png" />
  </div>
</div>


来源:https://stackoverflow.com/questions/64996565/why-is-after-pseudo-selector-over-the-image-and-not-under-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!