Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flexbox won't wrap on browser resize

Tags:

html

css

flexbox

I am trying to get my flexbox to resize on mobile devices and window size.

For the life of me I have no idea why it is not working. The flexbox should resize and wrap around to the next row as the browser scales down.

Demo

here

CSS/HTML

#flex-container {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: left;
  width: 1000px;
  height: 400px;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
  background-color: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
  overflow: hidden;
}

#left-zone {
  background: #fff;
  height: 75%;
  flex-grow: 0;
  display: flex;
  width: 350px;
  align-items: center;
  justify-content: left;
  min-width: 0;
}

#left-zone .list {
  display: flex;
  list-style: none;
  align-content: stretch;
  flex-direction: column;
  /* flex-grow: 1; */
  flex: 1 1 calc(33.33% - 20px);
  margin: 0;
  padding: 0;
}

.item input {
  display: none;
}

label {
  display: block;
  opacity: 0.5;
  height: 50px;
  text-align: center;
  line-height: 50px;
}

label:hover {
  opacity: 0.75;
  cursor: pointer;
}

/* content slides in on the right side of the flexbox */
.content {
  position: absolute;
  left: 350px;
  top: -400px;
  width: 650px;
  height: 400px;
  -webkit-animation-duration: 0.75s;
  animation-duration: 0.75s;
  -webkit-animation-name: slideout;
  animation-name: slideout;
  -webkit-animation-timing-function: ease-out;
  animation-timing-function: ease-out;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
}

/* p tag content in the right side of the flexbox */
.content p {
  max-width: 50%;
  text-align: center;
}

#middle-border {
  background-color: #eee;
  height: 75%;
  flex-grow: 1;
  max-width: 2px;
  z-index: 0;
}

/* Right side of flexbox where the content slides in */
#right-zone {
  background-color: #ff000070;
  height: 100%;
  flex-grow: 3;
}




/* ==========Styles only related to the animation slidein: IGNORE============*/
@-webkit-keyframes slidein {
  0% {
    top: -400px;
    opacity: 0;
  }
  100% {
    opacity: 1;
    top: 0;
  }
}
@keyframes slidein {
  0% {
    top: -400px;
    opacity: 0;
  }
  100% {
    opacity: 1;
    top: 0;
  }
}
@-webkit-keyframes slideout {
  0% {
    top: 0;
    opacity: 1;
  }
  100% {
    top: -400px;
    opacity: 0;
  }
}
@keyframes slideout {
  0% {
    top: 0;
    opacity: 1;
  }
  100% {
    top: -400px;
    opacity: 0;
  }
}
input:checked ~ .content {
  -webkit-animation-duration: 0.75s;
  animation-duration: 0.75s;
  -webkit-animation-name: slidein;
  animation-name: slidein;
  -webkit-animation-fill-mode: forwards;
  animation-fill-mode: forwards;
  -webkit-animation-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955);
  animation-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955);
}
body {
  background: #eee;
  font-family: Tahoma;
  -moz-user-select: none;
  -webkit-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
  <meta charset="utf-8">
  <title>Flex Test</title>
</head>
<body>
  <div id="flex-container">
    <div id="left-zone">
      <ul class="list">
        <li class="item">
          <input type="radio" id="radio_strawberries" name="basic_carousel" checked="checked" />
          <label class="label_strawberry" for="radio_strawberries">strawberry</label>
          <div class="content content_strawberry">
            <h1>strawberry</h1>
            <p>The garden strawberry... blah blah</p>
          </div>
        </li>
        <li class="item">
          <input type="radio" id="radio_banana" name="basic_carousel"/>
          <label class="label_banana" for="radio_banana">banana</label>
          <div class="content content_banana">
            <h1>banana</h1>
            <p>A banana... blah blah</p>
          </div>
        </li>
        <li class="item">
          <input type="radio" id="radio_apple" name="basic_carousel"/>
          <label class="label_apple" for="radio_apple">apple</label>
          <div class="content content_apple">
            <h1>apple</h1>
            <p>The apple... blah blah</p>
          </div>
        </li>
        <li class="item">
          <input type="radio" id="radio_orange" name="basic_carousel"/>
          <label class="label_orange" for="radio_orange">orange</label>
          <div class="content content_orange">
            <h1>orange</h1>
            <p>The orange... blah blah</p>
          </div>
        </li>
      </ul>
    </div>
    <div id="middle-border"></div>
    <div id="right-zone"></div>
  </div>
</body>

</html>

I would like to make the right side wrap underneath the left side as the browser window resolution gets smaller, but I just can't seem to figure it out.

The content in the right side of the flexbox is hidden and simply slides in from the top using CSS keyframes. I am guessing that this might be an issue since the content div on the right side of the flexbox is essentially empty

CodePen

appreciate any help

like image 887
jpisty Avatar asked Oct 24 '18 16:10

jpisty


3 Answers

Michael_B explains very well the problem here.

In addition to his answer, I'd say only that you are working also with an absolute .content, so your flexbox it is not a "normal" flexbox.

BTW, using your HTML, I tried to make it responsible. The trick is to remove all your fixed width.

Bootstrap is a possible way, but if you have already started your work, you can finish it using only CSS properties and no javascript (as you are doing): CSS have all the credentials to do it, without framework. This is what I think.

I tried not to change your HTML. I removed only <div id="middle-border"></div> 'cause you can create a right border in your #left-zone .list with the help of box-sizing property... and border-right, naturally ;)

In your CSS, I changed your animation with a more simple opacity and translateY transition (you have to go to point A to point B without another animation so a transition is enough, I think). But, well, it is not an error using an animation, I think only it's more simple use a transition for this work.

Another important think is to use a CSS that provides better cross-browser consistency in the default styling of HTML elements. To do this, I used "normalize.css": https://necolas.github.io/normalize.css/)

This is the code, hope it helps:

 body {
    background: #eee;
    font-family: Tahoma;
    -moz-user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
    user-select: none;
  }


  #flex-container {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    width: 100%; /* no fixed width */
 
    min-height: 400px; /*add min-height for 1 column layout */
    height: 100vh;
    max-width: 1000px;
    
    margin: auto;
    background-color: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
    overflow: hidden;

    flex-direction: column;
    position: relative;
  }

  #left-zone {
    height: 50%;
    flex: 0 0 auto;
    display: flex;
    width: 100%;

  }

  #left-zone .list {
    display: flex;
    list-style: none;
    align-content: stretch;
    flex-direction: column;
    flex: 1 1 auto;
    margin: auto;
    padding: 0;
    box-sizing: border-box;
    
  }

  .item input {
    display: none;
  }

  label {
    display: block;
    opacity: 0.5;
    height: 50px;
    text-align: center;
    line-height: 50px;

    position: relative;
  }

  label:hover {
    opacity: 0.75;
    cursor: pointer;
  }

  /* content slides in on the right side of the flexbox */
  .content {
    position: absolute;
    right: 0;
    bottom: 0;
    opacity: 0;
    transform: translateY(100%);

    height: 50%;
    width: 100%;
    
    transition: 0.5s ease-out;

    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    pointer-events: none;
  }

  /* p tag content in the right side of the flexbox */

  .content p {
    max-width: 50%;
    text-align: center;
  }

  /* Right side of flexbox where the content slides in */
  #right-zone {
    background-color: #ff8f8f;
    width: 100%;
    flex: 1 0 auto;
    height: 50%;
  }

  input:checked ~ .content {
    transform: translateY(0%);
    opacity: 1;
  }

  @media (min-width:480px){
    #flex-container {
      flex-direction: row;
      min-height: auto;
      height: 400px;
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
    }

    #left-zone .list {
      border-right: 2px solid #cccccc;
    }

    .content {
        width: 65%; /* no fixed width */
        height: 100%;
        pointer-events: auto;
        transform: translateY(-100%);
    }

    #left-zone {
        width: 35%; /* no fixed width */
    }

    #right-zone {
      height: 100%;
      width: 65%; /* no fixed width */
    }
  }
<link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.0/normalize.min.css" rel="stylesheet">
<div id="flex-container">
    <div id="left-zone">
      <ul class="list">
        <li class="item">
          <input type="radio" id="radio_strawberries" name="basic_carousel" checked="checked" />
          <label class="label_strawberry" for="radio_strawberries">strawberry</label>
          <div class="content content_strawberry">
              <h1>strawberry</h1>
              <p>The garden strawberry... blah blah</p>
          </div>
        </li>
        <li class="item">
          <input type="radio" id="radio_banana" name="basic_carousel"/>
          <label class="label_banana" for="radio_banana">banana</label>
          <div class="content content_banana">
            <h1>banana</h1>
            <p>A banana... blah blah</p>
          </div>
        </li>
        <li class="item">
          <input type="radio" id="radio_apple" name="basic_carousel"/>
          <label class="label_apple" for="radio_apple">apple</label>
          <div class="content content_apple">
            <h1>apple</h1>
            <p>The apple... blah blah</p>
          </div>
        </li>
        <li class="item">
          <input type="radio" id="radio_orange" name="basic_carousel"/>
          <label class="label_orange" for="radio_orange">orange</label>
          <div class="content content_orange">
            <h1>orange</h1>
            <p>The orange... blah blah</p>
          </div>
        </li>
      </ul>
    </div>
    <div id="right-zone"></div>
  </div>
like image 101
ReSedano Avatar answered Oct 14 '22 07:10

ReSedano


Flex items wrap in their containers. Sounds obvious, but it's the key concept to understand here.

If the flex items were in a container whose width was tied to the viewport width – that would commonly be a container taking width: 100% of the body element – then the flex items would wrap in relation to the viewport width. A resizing viewport would have a direct impact on the flex container, which would have a direct impact on the flex items.

However, in your case, the flex container is not tied to the viewport width. It has a different width:

#flex-container {
  display: flex;
  flex-wrap: wrap;
  width: 1000px;
}

In this case, the flex items are laid out in relation to the 1000px wide space, not the viewport space. Since the items and the viewport have no association, the items have no reason to do anything when the viewport is resized.

like image 25
Michael Benjamin Avatar answered Oct 14 '22 05:10

Michael Benjamin


Well, after some time working on it, I have the next (responsive) approach using Bootstrap 4 and Animate.css plugin in replacement of your animations. I hope you enjoy it!

$(document).ready(function()
{
    $("input[type='radio']").click(function()
    {
        $("#right-zone .animated").addClass("d-none");
        var target = $(this).attr("target-div");
        $("." + target).toggleClass("d-none");
    });
});
#flex-container {
    min-height: 50vh;
    margin-top: 25vh;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
}

/* On XS screen devices, use all the available height */

@media(max-width:576px)
{
    #flex-container {
        min-height: 100vh;
        margin-top: 0vh;
    }
}

#right-zone {
    background-color: rgba(255,0,0,0.6);
}

.item input {
    display: none;
}

label {
    opacity: 0.5;
    height: 50px;
    line-height: 50px;
}

label:hover {
    opacity: 0.75;
    cursor: pointer;
}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.0/animate.min.css"/>

<div class="container-fluid">
<div class="row w-75 mx-auto" id="flex-container">

  <div class="col-sm-4 bg-light" id="left-zone">
  <div class="d-flex h-100 align-items-center justify-content-center">
  <div class="items-container text-center">

    <div class="item">
      <input type="radio" id="radio_strawberries" target-div="content_strawberry"/>
      <label class="label_strawberry" for="radio_strawberries">strawberry</label>
    </div>

    <div class="item">
      <input type="radio" id="radio_banana" target-div="content_banana"/>
      <label class="label_banana" for="radio_banana">banana</label>
    </div>

    <div class="item">
      <input type="radio" id="radio_apple" target-div="content_apple"/>
      <label class="label_apple" for="radio_apple">apple</label>
    </div>

    <div class="item">
      <input type="radio" id="radio_orange" target-div="content_orange"/>
      <label class="label_orange" for="radio_orange">orange</label>
    </div>

  </div>
  </div>
  </div>
  
  <div class="col-sm-8" id="right-zone">
  <div class="d-flex h-100 align-items-center justify-content-center text-center">

    <div class="content_strawberry animated fadeInDown">
      <h1>strawberry</h1>
      <p>The garden strawberry... blah blah</p>
    </div>

    <div class="content_banana d-none animated fadeInDown">
      <h1>banana</h1>
      <p>A banana... blah blah</p>
    </div>

    <div class="content_apple d-none animated fadeInDown">
      <h1>apple</h1>
      <p>The apple... blah blah</p>
    </div>

    <div class="content_orange d-none animated fadeInDown">
      <h1>orange</h1>
      <p>The orange... blah blah</p>
    </div>

  </div>
  </div>

</div>
</div>
like image 42
Shidersz Avatar answered Oct 14 '22 06:10

Shidersz