fupuchu
fupuchu

Reputation: 307

Flexbox Layout with image overlaps

I ran into a hitch where I'm trying to replicate this:

enter image description here

I can't seem to have the image occupy the container width and overlap the black box. I had a working copy but it was not friendly for mobile/desktop. Here's a quick example in codepen: https://codepen.io/pandar3n/pen/jQqvjm

HTML:

<div class="test-container">
  <div class="wrapper">
    <div class="test-img"><img src="https://placekitten.com/800/300" /></div>
    <div class="test-text">
      <div class="testtext-inner">
        <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae
          est. Mauris placerat eleifend leo.</p>
      </div>
    </div>
  </div>
</div>

<div class="test-container alt">
  <div class="wrapper">
    <div class="test-img"><img src="https://placekitten.com/800/300" /></div>
    <div class="test-text">
      <div class="testtext-inner">
        <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
      </div>
    </div>
  </div>

SCSS

*{
  font-family: sans-serif;
}
.test-container {
  .wrapper {
    max-width: 80vw;
    margin: 50px auto;
    position: relative;
    display: flex;
    height: 80vh;
  }
  .test-text {
    width: 50%;
    background-color: #aaa;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .testtext-inner {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 50%;
  }

.test-img {
  width: 50%;
  align-self: center;

  img {
    transform: translateX(80px);
  }
}

&.alt {
  .test-text {
    order: 1;

    .testtext-inner {
      padding-right: 150px;
      padding-left: 50px;
    }
  }
  .test-img {
    order: 2;

    img {
      transform: translateX(-80px);
    }
  }
}
}

Managed to get the alternating layouts to work but the image won't occupy the white space to the left/right.

Would a 60% 50% flex work?

Upvotes: 0

Views: 2171

Answers (2)

fupuchu
fupuchu

Reputation: 307

Update: I managed to get it work somehow with flexbox, in this case I had to overlay the div on top of another for overlap to happen.

HTML:

<div class="block">
  <div class="image-wrapper">
  <img src="https://placekitten.com/600/400"/>
</div>
  <div class="div-wrapper">
  <h1>There are some text here.</h1>
  <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Saepe, ullam esse quia suscipit sapiente, provident expedita voluptatum illo facilis asperiores vitae. Atque aliquid et similique nostrum molestiae, dolores dignissimos beatae.</p>
</div>
</div>

<div class="block">
  <div class="div-wrapper">
  <h1>There are some text here.</h1>
  <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Saepe, ullam esse quia suscipit sapiente, provident expedita voluptatum illo facilis asperiores vitae. Atque aliquid et similique nostrum molestiae, dolores dignissimos beatae.</p>
</div>
  <div class="image-wrapper">
  <img src="https://placekitten.com/900/300"/>
</div>
</div>

<div class="wrapper2">
  <div class="image-overlay">
    <img src="https://placekitten.com/600/400"/>
  </div>
  <div class="row-wrapper">
    <div class="filler"></div>
    <div class="text-block">
      <div class="text-wrapper">
        <h1>Hello World!</h1>
    <p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Non at sunt consequatur laborum molestiae quidem pariatur quibusdam! Ipsum tempore explicabo dolorum voluptate, asperiores sapiente quod qui modi, iusto assumenda adipisci.</p>
      </div>
    </div>
  </div>
</div>

<div class="wrapper2">
  <div class="image-overlay alt">
    <div class="overlay-filler"></div>
    <div class="image-me">
      <img src="https://placekitten.com/600/400"/>
    </div>
  </div>
  <div class="row-wrapper alt">
    <div class="filler"></div>
    <div class="text-block">
      <div class="text-wrapper">
        <h1>Hello World!</h1>
    <p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Non at sunt consequatur laborum molestiae quidem pariatur quibusdam! Ipsum tempore explicabo dolorum voluptate, asperiores sapiente quod qui modi, iusto assumenda adipisci.</p>
      </div>
    </div>
  </div>
</div>

SCSS:

.block{
  width: 600px;
  margin: 0 auto;
  border: 1px solid black;
}
.div-wrapper {
    position: relative;
    width: 100%;
    height: auto;
    text-align: center;
}
.image-wrapper{
  width: 100%;
  text-align: center;
}
.image-wrapper > img {
  width: 100%;
}


/* Second Block */
.wrapper2{
  width: 80%;
  margin: 0 auto;
  border: 1px solid purple;
  height: 100vh;
}
.row-wrapper{
  display: flex;
  &.alt {
    .filler{
      order: 1;
    }
  }
}
.filler{
  width: 50%;
}
.text-block{
  width: 50%;
  background: blue;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
}
.text-wrapper{
  width: 50%;
}
.image-overlay{
  width: 45%;
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  &.alt{
    width: 100%;
    .overlay-filler{
      width: 15%;
    }
    .image-me{
      width: 45%;
      img{
      width: 100%;
    }
    }
  }
}
.image-overlay > img {
  width: 100%;
}

Explanation: How this works is that there's two divs in one container; overlay-div and row-wrapper(could have named it other things). overlay-div has a position of absolute which will make it position on top of row-wrapper.

row-wrapper is a flexbox with a filler and a text-block.

Just a quick note that for this to work, the height of the wrappers must be set to 100vh.

Upvotes: 0

Croot
Croot

Reputation: 331

The values depend on the dimensions of your image, but I feel you've over-complicated the CSS, see the following example: https://codepen.io/anon/pen/mQPvZW

* {
  box-sizing: border-box;
  font-family: Arial, Helvetica, sans-serif;
  margin: 0;
}

.row {
  background: #333;
  display: flex;
  margin: 20px;

  .col {
    background: #c33;
    flex-grow: 0;
    margin: 10px;
    min-height: 400px;
    padding: 20px;
    position: relative;
    width: 60%;

    &:first-child {
      margin-right: 0;
      width: 40%;
    }

    img {
        height: 300px;
        position: absolute;
        // Adjust the indent of the image as necessary.
        // 30px calculated by 20px padding + 10px margin gutter.
        right: -30px;
        z-index: 1;

        // If you want to vertically align in the area assuming you dont know the dimensions of the image.
        top: 50%;
        transform: translateY(-50%);
      }
  }

  + .row .col {
    width: 40%;

    img {
      right: auto;
      left: -30px;
    }

    &:first-child {
      width: 60%;
    }
  }
}

A short explanation below with an image depicting the styles:

  • Black box: Flex wrapper.
  • Red box: Flex item (notice how they both should fill the entire flex area).
  • Blue box: Image element absolutely positioned in the flex container.

enter image description here

There are a lot of caveats to this approach - mostly around whether you know the dimensions of the image, and the content area. But with the information supplied I believe this is the most stable approach.

Upvotes: 1

Related Questions