newvertex
newvertex

Reputation: 180

How to prevent element absolute position from overlap in css

I have a div element to show my blog post, each post have to load an image, a title and one paragraph inside it,
because I want to show title element at bottom of image with a simple background-color then I write the markup like this:

<div class="post">
  <div class="thumb">
    <img class="image" src="img">
    <h3 class="title">title</h3>
  </div>
  <p class="content">Content</p>
</div>

I put the image and title element inside a div block to place them on each other(title overlap the image) and set thumb position to relative and two child element(image and title) to absolute to achieve the final result, but after that the image and title goes outside of it parent(post element) and overlap the other element above of it in the page.

.post {
  .thumb {
    position: relative;
    .image {
      display: block;
      position: absolute;
      bottom: 0;
      left: 0;
      width: 100%
    }
    .title {
      display: block;
      position: absolute;
      bottom: 0;
      left: 0;
      width: 100%;
      background: rgba(#000, .7);
      color: #fff;
      padding: .5rem;
    }
  }
  .content {

  }
}

I want to know why the parent element lose it's height block space and overlap on other elements.

I read some of the similar questions but non of them answer this.

I know if I just set the title position to absolute and fixed on the bottom of image keep the space of block, or use css grid's to achieve similar things but I want to find the real reason to this problem and how to prevent it?

The complete sample code is on codepen: https://codepen.io/anon/pen/GaMegN?editors=1100#0

.post .thumb {
  position: relative;
}
.post .thumb .image {
  display: block;
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
}
.post .thumb .title {
  display: block;
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  background: rgba(0, 0, 0, 0.7);
  color: #fff;
  padding: .5rem;
}
<div class="page">
  <div>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </div>
  <div class="post">
    <div class="thumb">
      <img class="image" src="https://picsum.photos/400/200">
      <h3 class="title">just a sample title</h3>
    </div>

    <p class="content">
      CSS output is just like HTML, only there is no special formats you need to worry about. Just add the CSS you want to output (using newlines as needed) and it will output that way.
    </p>
  </div>
</div>

Upvotes: 0

Views: 3351

Answers (4)

yunzen
yunzen

Reputation: 33439

Absolute positioned elements step out of the regular flow. The parent elements (position: relative) now don't know anything about the size of their child. For them it is just like the child has display: none. I won't affect their own size in any way.

How can you prevent this? There may be many ways.

Don't use absolute on every element: Here I set the .title to relative so that I can control the z-index. I needed the overflow: hidden on .thumb. I added some margins on .title so I can see more of the image

.post .thumb {
  position: relative;
  
  /* new */
  overflow: hidden;
  margin-top: 20px;
}
.post .thumb .image {
  display: block;
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
}
.post .thumb .title {
  display: block;
  /* position: absolute; */
  /* bottom: 0; */
  /* left: 0; */
  width: 100%;
  background: rgba(0, 0, 0, 0.7);
  color: #fff;
  padding: .5rem;
  
  /* new */
  position: relative;
  z-index: 1;
  margin-bottom: 20px;
  margin-top: 60px;
}
<div class="page">
  <div>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </div>
  <div class="post">
    <div class="thumb">
      <img class="image" src="https://picsum.photos/id/990/400/200">
      <h3 class="title">just a sample title</h3>
    </div>

    <p class="content">
      CSS output is just like HTML, only there is no special formats you need to worry about. Just add the CSS you want to output (using newlines as needed) and it will output that way.
    </p>
  </div>
</div>

Or use a background-image instead of an <img> element

.post .thumb {
  position: relative;
  overflow: hidden;
  margin-top: 20px;
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center 40%;
}
.post .thumb .title {
  display: block;
  width: 100%;
  background: rgba(0, 0, 0, 0.7);
  color: #fff;
  padding: .5rem;
  position: relative;
  z-index: 1;
  margin-bottom: 20px;
  margin-top: 60px;
}
<div class="page">
  <div>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </div>
  <div class="post">
    <div class="thumb" style="background-image: url(https://picsum.photos/id/990/400/200)">
      
      <h3 class="title">just a sample title</h3>
    </div>

    <p class="content">
      CSS output is just like HTML, only there is no special formats you need to worry about. Just add the CSS you want to output (using newlines as needed) and it will output that way.
    </p>
  </div>
</div>

Upvotes: 1

Dejan.S
Dejan.S

Reputation: 19158

The thumb wont have a height because elements with position: absolute; does not take up relative space in it.

I would suggest to remove the position: absolute; on the image, that would give the thumb width and height, but keep absolute on the title

.post .thumb {
  position: relative;
}

.post .thumb .image {
  display: block;
  max-width: 100%;
  max-height: 100%;
}

.post .thumb .title {
  display: block;
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  background: rgba(0, 0, 0, 0.7);
  color: #fff;
  padding: .5rem;
  margin: 0;
}
<div class="post">
  <div class="thumb">
    <img class="image" src="https://picsum.photos/400/200">
    <h3 class="title">title</h3>
  </div>
  <p class="content">Content</p>
</div>

Upvotes: 2

Priyesh Diukar
Priyesh Diukar

Reputation: 2142

When you set any element to absolute they are taken out of normal document flow and thus other elements position themselves as the targeted absolute element does not exist.

*{
 box-sizing:border-box;
}
.post .thumb {
  position: relative;
}
.post .thumb .image {
  display: block;
  width: 100%;
}
.post .thumb .title {
  display: block;
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  background: rgba(0, 0, 0, 0.7);
  color: #fff;
  padding: .5rem;
  margin:0;
}
<div class="page">
  <div>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </div>
  <div class="post">
    <div class="thumb">
      <img class="image" src="https://picsum.photos/400/200">
      <h3 class="title">just a sample title</h3>
    </div>

    <p class="content">
      CSS output is just like HTML, only there is no special formats you need to worry about. Just add the CSS you want to output (using newlines as needed) and it will output that way.
    </p>
  </div>
</div>

Upvotes: 0

Tree Frog
Tree Frog

Reputation: 666

Change the position of the image and the title to relative and just add a top:-100px (or whatever) to your title

Upvotes: 0

Related Questions