web-dev-qa-db-fra.com

espace blanc: nowrap casse flexbox layout

J'ai créé une mise en page réactive pour une application utilisant Flexbox. La mise en page nécessite un menu pliable à gauche, un bloc avec un en-tête et un corps au milieu et un volet d'aide à bascule à droite (il y a plus mais c'est la structure de base).

Le menu de gauche a deux états: 180px de large ou 80 px de large. Le volet d'aide est soit masqué, soit prend 180 pixels. La boîte du milieu prend le reste de l'espace. Flexbox fonctionne comme un charme.

Le problème commence lorsque je crée une div à défilement à l'aide de white-space: nowrap. J'ai un tas d'éléments qui doivent être affichés dans un défilement horizontal, j'ai donc une liste div avec les éléments, définie sur overflow:auto et white-space: nowrap.

Habituellement, cela fonctionne comme un charme, mais maintenant cela brise ma disposition flexible. Au lieu de prendre la largeur de la div parent (flex), le scroller rend la div plus large, ce qui à son tour pousse le volet d'aide hors des limites.


Le violon suivant illustre ce problème:

http://jsfiddle.net/PieBie/6y291fud/

Vous pouvez basculer le volet d'aide en cliquant sur basculer l'aide dans la barre de menus. Recréez le problème en cliquant sur liste bascule espace dans le menu, cela fait basculer le white-space: no-wrap Propriété CSS de la liste. Si le volet d'aide est ouvert, vous pouvez voir qu'il est poussé hors des limites.

La liste du bas est ce que je veux réaliser, mais je veux que ce soit la pleine largeur de son parent.

Je peux recréer le problème dans Chrome, Firefox, Opera, Vivaldi et Edge. Internet Explorer 11 joue Nice (° _ °). Je préférerais une solution CSS pure (SCSS est également une option), mais si besoin, je peux utiliser JS.


$('#nav-toggle').on('click',function(){
        $(this).parent().toggleClass('collapsed');
});
$('#help-toggle').on('click',function(){
        $('#help-pane').toggleClass('visible');
});
$('#list-toggle').on('click',function(){
        $('#list').toggleClass('nowrap');
});
body,html{width:100%;height:100%;overflow:hidden;}

#body{
  display:flex;
  flex-flow:row nowrap;
  position:absolute;
  top:0;
  left:0;
  margin:0;
  padding:0;
  width:100%;
  height:100%;
  background-color:#abc;
  overflow:hidden;
}

#Shell{
  flex: 1 1 auto;
  display:flex;
  flex-flow:row nowrap;
  position:relative;
  width:100%;
  min-height:100%;
}

  #left{
    flex: 0 0 180px;
    min-height:100%;
    min-width: 0;
    background:lightblue;
  }
  #left.collapsed{
    flex: 0 0 80px;
  }
  
  #mid{
    flex: 1 1 auto;
    min-height:100%;
    min-width: 0;
    display:flex;
    flex-flow:column nowrap;
    align-items:stretch;
    align-content:stretch;
    position:relative;
    width:100%;
    min-height:100vh;
    min-width: 0;
    background:purple;
  }
      #mid-top{
        flex: 0 0 auto;
        min-height:100px;
        background:green;
      }
      #mid-bottom{
        min-height:calc(100% - 100px);
        flex: 1 1 auto;
        background:lightgreen;
      }
      #list{
        overflow: auto;
        width: 100%;
        max-width: 100%;
      }
      #list.nowrap{
        white-space: nowrap;
      }
      #secondlist{
        overflow: auto;
        max-width: 250px;
        white-space: nowrap;
      }
      .list-item{
        display: inline-block;
        width: 50px;
        height: 50px;
        margin: 2px;
        background: purple;
      }
      .list-item.odd{
        background: Violet;
      }
      
#help-pane{
  display:none;
  flex: 0 0 0px;
  background:red;
}
#help-pane.visible{
  display:inherit;
  flex:0 0 180px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="body">
 <div id="Shell">
      <div id="left">
          <div id="nav">
            - menu -
          </div>
          <div id="help-toggle">
            help toggle
          </div>
          <div id="nav-toggle">
            nav toggle
          </div>
          <div id="list-toggle">
            list whitespace toggle
          </div>
      </div>
      <div id="mid">
          <div id="mid-top">
                - mid top -
          </div>
          <div id="mid-bottom">
               - mid bottom- <br><br>
               <div id="list">
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
               </div>
               <hr>
               <div id="secondlist">
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
               </div>
          </div>
      </div>
 </div>
 <div id="help-pane" class="visible">
   - help-pane -
 </div>
</div>
36
PieBie

Cela est dû au comportement par défaut de la boîte flexible , qui empêche les boîtes flexibles de devenir plus petites que son contenu.

La solution à ce problème consiste à définir min-width: 0 (ou min-height: 0 pour les colonnes) à toutes les boîtes flexibles parentes. Dans ce cas précis (et dans le violon ):

#Shell{
  flex: 1 1 auto;
  display:flex;
  flex-flow:row nowrap;
  position:relative;
  width:100%;
  min-height:100%;
  min-width: 0; /* this one right here does it!*/
} 

$('#nav-toggle').on('click',function(){
        $(this).parent().toggleClass('collapsed');
});
$('#help-toggle').on('click',function(){
        $('#help-pane').toggleClass('visible');
});
$('#list-toggle').on('click',function(){
        $('#list').toggleClass('nowrap');
});
body,html{width:100%;height:100%;overflow:hidden;}

#body{
  display:flex;
  flex-flow:row nowrap;
  position:absolute;
  top:0;
  left:0;
  margin:0;
  padding:0;
  width:100%;
  height:100%;
  background-color:#abc;
  overflow:hidden;
}

#Shell{
  flex: 1 1 auto;
  display:flex;
  flex-flow:row nowrap;
  position:relative;
  width:100%;
  min-height:100%;
  min-width: 0;
}

  #left{
    flex: 0 0 180px;
    min-height:100%;
    min-width: 0;
    background:lightblue;
  }
  #left.collapsed{
    flex: 0 0 80px;
  }
  
  #mid{
    flex: 1 1 auto;
    min-height:100%;
    min-width: 0;
    display:flex;
    flex-flow:column nowrap;
    align-items:stretch;
    align-content:stretch;
    position:relative;
    width:100%;
    min-height:100vh;
    min-width: 0;
    background:purple;
  }
      #mid-top{
        flex: 0 0 auto;
        min-height:100px;
        background:green;
      }
      #mid-bottom{
        min-height:calc(100% - 100px);
        flex: 1 1 auto;
        background:lightgreen;
      }
      #list{
        overflow: auto;
        width: 100%;
        max-width: 100%;
      }
      #list.nowrap{
        white-space: nowrap;
      }
      #secondlist{
        overflow: auto;
        max-width: 250px;
        white-space: nowrap;
      }
      .list-item{
        display: inline-block;
        width: 50px;
        height: 50px;
        margin: 2px;
        background: purple;
      }
      .list-item.odd{
        background: Violet;
      }
      
#help-pane{
  display:none;
  flex: 0 0 0px;
  background:red;
}
#help-pane.visible{
  display:inherit;
  flex:0 0 180px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="body">
 <div id="Shell">
      <div id="left">
          <div id="nav">
            - menu -
          </div>
          <div id="help-toggle">
            help toggle
          </div>
          <div id="nav-toggle">
            nav toggle
          </div>
          <div id="list-toggle">
            list whitespace toggle
          </div>
      </div>
      <div id="mid">
          <div id="mid-top">
                - mid top -
          </div>
          <div id="mid-bottom">
               - mid bottom- <br><br>
               <div id="list">
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
               </div>
               <hr>
               <div id="secondlist">
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
                 <div class="list-item">&nbsp;</div>
                 <div class="list-item odd">&nbsp;</div>
               </div>
          </div>
      </div>
 </div>
 <div id="help-pane" class="visible">
   - help-pane -
 </div>
</div>
76
PieBie