Search code examples
csssassflexboxresponsive-designresponsive

Flexbox and responsiveness: how to get items to wrap and then take up the full width of their new space without overflow?


I'm building an app that has some overlay panels over a video section. I'm trying to make this responsive and rather than having all the panels shrink, I want to just move them into the position shown in the shrunken view image below.

The panel in the top right is absolutely positioned and doesn't need to shrink/move at all when the screen size changes, the ones that need to change are the left side panel and the bottom red panel.

I made a quick Codepen link for this.

I figured the best way to work with this is using flex-direction: column the wrap property to get this to work, however, if you do this you have some overflow from the red element if it's width: 100% (if you dont do this the red box will only be half the width of the space).

Like this:

enter image description here

So I figured I'd capture the width of the blue box and then calc the width so that it doesn't overflow. This seems like it works when you're in the shrunken view, but then you always have that calced value space on the initial view

like this:

enter image description here

So is there any way to make this look like the Ideal Shrunken View? What am I missing with the use of flexbox here? Is there a way to make this happen that I'm not considering?

Initial View

enter image description here

Ideal Shrunken View

enter image description here

html

<div class="wrapper">
  <div class="top-left"></div>
  <div class="top-right"></div>
  <div class="bottom"></div>
</div>

Sass

.wrapper
  --width-top-left: 20px
  display: flex
  flex-direction: column
  flex-wrap: wrap
  height: 60px
  // height: 50px
  
.top-left
  height: 30px
  width: var(--width-top-left)
  
.bottom
  height: 22px
  margin-top: auto
  width: calc(100% - var(--width-top-left))

----------------Box Styles-------------------------

.wrapper
  border: thin solid goldenrod
  position: relative
.bottom
  background: lightcoral
.top-left
  background: mediumslateblue
.top-right
  position: absolute
  top: 0
  right: 0
  background: mediumseagreen
  height: 20px
  width: 30px

Solution

  • I've added a media query to change flex-direction to row for the parent then changed the bottom bar to width:auto and flex-grow:1 so it stretches to fit the parent. Is that what you're looking for?

    .wrapper {
      --width-top-left: 20px;
      display: flex;
      flex-direction: column;
      flex-wrap: wrap;
      height: 60px;
    }
    
    .top-left {
      height: 30px;
      width: var(--width-top-left);
    }
    
    .bottom {
      height: 22px;
      margin-top: auto;
      width: 100%;
    }
    
    .wrapper {
      border: thin solid goldenrod;
      position: relative;
    }
    
    .bottom {
      text-align: center;
      background: lightcoral;
    }
    
    .top-left {
      background: mediumslateblue;
    }
    
    .top-right {
      position: absolute;
      top: 0;
      right: 0;
      background: mediumseagreen;
      height: 20px;
      width: 30px;
    }
    
    .shrunkenview {
      display: none;
    }
    
    @media only screen and (max-width:800px) {
      .wrapper {
        flex-direction: row;
      }
      .top-left {
        height: 100%;
      }
      .bottom {
        width: auto;
        flex-grow: 1;
      }
      .initialview {
        display: none;
      }
      .shrunkenview {
        display: unset;
      }
    }
    <div class="wrapper">
      <div class="top-left"></div>
      <div class="top-right"></div>
      <div class="bottom"><span class='shrunkenview'>Shrunken View</span><span class='initialview'>InitialView</span>
      </div>