Как заставить flexbox не использовать больше места, чем контейнер? - PullRequest
0 голосов
/ 18 мая 2018

Я создаю модал и хочу, чтобы он центрировался на моей странице и рос органически, но только до тех пор, пока он не достигнет определенной ширины и высоты.

Я центрирую этот модал (.modal) с помощью flexbox,и он отлично работает.

Внутри этого модального у меня есть еще один flexbox (.modal-content), с телом (.modal-content__body) и элементом нижнего колонтитула (.modal-content__footer).Я хочу, чтобы тело росло до тех пор, пока целое .modal не достигнет моего max-height, и в этот момент я хочу, чтобы modal-content__body начал прокручивать вертикально.

Иерархия HTML:

.modal-container // Full screen
  .modal // Centred box with max-width and max-height
    .modal-content // The content of the modal
      .modal-content__body // Potentially growing content
      .modal-content__footer

Я не могу заставить .modal-content не переполниться.Он просто игнорирует высоту родительского элемента (.modal) и увеличивается, чтобы обеспечить место для содержимого.

Если я удаляю дополнительный div .modal-content и просто объединяем .modalс .modal-content он работает как положено , но поскольку я использую фреймворк (Angular), я не могу изменить способ инкапсуляции HTML-элементов.

(ПРИМЕЧАНИЕ : если я установлю max-height: -webkit-fill-available; на .modal-content, оно будет работать, но это свойство плохо поддерживается, поэтому я не могу его использовать)

Вот код, демонстрирующий проблему:

/* Centers the child */
.modal-container {
  display: flex;
  align-items: center;
  justify-content: center;
}


/* The box in the middle, that should grow
   organically, but be restricted as well */
.modal,
.modal-content--merged-with-modal {
  width: 30rem;
  max-width: calc(50vw - 3rem);
  max-height: calc(100vh - 3rem);
  /* Irrelevant styling */
  background: rgba(255, 255, 255, 0.6);
  border-radius: 3px;
  line-height: 1.5rem;
}

.modal-content {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.modal-content__body {
  flex: 1;
  min-height: 0;
  overflow-y: scroll;
  /* Irrelevant styling */
  padding: 0.75rem;
  background: rgba(0, 0, 255, 0.1);
}

.modal-content__footer {
  /* Irrelevant styling */
  border-top: 1px solid silver;
  background: rgba(0, 255, 0, 0.1);
  padding: 0.75rem;
}


/* Irrelevant styling to present the problem */

html {
  font-family: arial, sans-serif;
  font-size: 16px;
}

main {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
}

section {
  flex: 1;
  background: rgba(255, 0, 0, 0.1);
}
<main>

  <section class="modal-container">
    <div class="modal-content modal-content--merged-with-modal">
      <div class="modal-content__body">
        <code>BODY // </code> srollable<br>
        <br> Container resizes as expected when<br> the container height is reduced.<br>
        <br> In this case, the modal is the same<br> element, as the flexbox handling<br> the body and the footer.<br> .
        <br> .
        <br> .
        <br> .
        <br> .
        <br> .
        <br>
      </div>
      <div class="modal-content__footer">
        <code>FOOTER // </code> Works
      </div>
    </div>
  </section>

  <section class="modal-container">
    <div class="modal">

      <div class="modal-content">
        <div class="modal-content__body">
          <code>BODY // </code>simply grows<br>
          <br> Container overflows when<br> the container height is reduced.<br>
          <br> In this case, the modal <strong>contains</strong><br> the flexbox, that handles the<br> body and the footer.<br> .
          <br> .
          <br> .
          <br> .
          <br> .
          <br> .
          <br>
        </div>
        <div class="modal-content__footer">
          <code>FOOTER // </code> Doesn't work
        </div>
      </div>

    </div>
  </section>

</main>

Ответы [ 2 ]

0 голосов
/ 18 мая 2018

Чтобы свойство overflow работало, требуется фиксированное ограничение длины.

С MDN :

Чтобы эффект overflow имел эффект, контейнер уровня блока должен иметь либо установленную высоту (height или max-height), либо white-space, установленный вnowrap.

В вашем коде нет ограничения по высоте для .modal-content__body (где установлен overflow):

.modal-content__body {
    flex: 1;
    min-height: 0;
    overflow-y: scroll;
}

Также нет высотыограничение на родительский элемент:

.modal-content {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

flex-basis: 0 - соответствующий компонент flex: 1 в .modal-content__body - недостаточно для запуска условия переполнения.Но посмотрите, что произойдет, если вы переключитесь на flex-basis: 100px

/* Centers the child */
.modal-container {
  display: flex;
  align-items: center;
  justify-content: center;
}
  
/* The box in the middle, that should grow
   organically, but be restricted as well */
.modal, .modal-content--merged-with-modal {
  width: 30rem;
  max-width: calc(50vw - 3rem);
  max-height: calc(100vh - 3rem);

  /* Irrelevant styling */
  background: rgba(255, 255, 255, 0.6);
  border-radius: 3px;
  line-height: 1.5rem;
}
  
  
.modal-content {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
  
.modal-content__body {
  flex: 1 0 100px; /* new for demo 1 */
  min-height: 0;
  overflow-y: scroll;

  /* Irrelevant styling */
  padding: 0.75rem;
  background: rgba(0, 0, 255, 0.1);
}
  
  
.modal-content__footer {
  /* Irrelevant styling */
  border-top: 1px solid silver;
  background: rgba(0, 255, 0, 0.1);
  padding: 0.75rem;
}
  
  
  
/* Irrelevant styling to present the problem */
html {
  font-family: arial, sans-serif;
  font-size: 16px;
}
main {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  
  display: flex;
}
section {
  flex: 1;
  background: rgba(255, 0, 0, 0.1);
}
<main>
  <section class="modal-container">
    <div class="modal">
      <div class="modal-content">
        <div class="modal-content__body">
          <code>BODY // </code>simply grows<br>
          <br> Container overflows when<br> the container height is reduced.<br>
          <br> In this case, the modal <strong>contains</strong><br> the flexbox, that handles the<br> body and the footer.<br> .
          <br> .
          <br> .
          <br> .
          <br> .
          <br> .
          <br>
        </div>
        <div class="modal-content__footer">
          <code>FOOTER // </code> Doesn't work
        </div>
      </div>
    </div>
  </section>
</main>

Прокрутка работает.Ограничение высоты имело значение.

Вот потенциальное решение:

Поскольку высота .modal (родительский) и modal-content (дочерний) одинаковы, переместите размерыот родителя к ребенку.Это приближает ограничение высоты достаточно близко к элементам содержимого, чтобы вызвать переполнение.

Вместо этого:

.modal {
    width: 30rem;
    max-width: calc(50vw - 3rem);
    max-height: calc(100vh - 3rem);
}

.modal-content {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

Попробуйте это:

.modal {    }

.modal-content {
    display: flex;
    flex-direction: column;
    min-height: 0;
    width: 30em;
    max-width: calc(50vw - 3rem);
    max-height: calc(100vh - 3rem);
}

/* Centers the child */
.modal-container {
  display: flex;
  align-items: center;
  justify-content: center;
}
  
/* The box in the middle, that should grow
   organically, but be restricted as well */
.modal, .modal-content--merged-with-modal {


  /* Irrelevant styling */
  background: rgba(255, 255, 255, 0.6);
  border-radius: 3px;
  line-height: 1.5rem;
}
  
  
.modal-content {
  display: flex;
  flex-direction: column;
  min-height: 0;   
     width: 30rem;
     max-width: calc(50vw - 3rem);
     max-height: calc(100vh - 3rem);
}
  
.modal-content__body {
  flex: 1;
  min-height: 0;
  overflow-y: scroll;

  /* Irrelevant styling */
  padding: 0.75rem;
  background: rgba(0, 0, 255, 0.1);
}
  
  
.modal-content__footer {
  /* Irrelevant styling */
  border-top: 1px solid silver;
  background: rgba(0, 255, 0, 0.1);
  padding: 0.75rem;
}
  
  
  
/* Irrelevant styling to present the problem */
html {
  font-family: arial, sans-serif;
  font-size: 16px;
}
main {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  
  display: flex;
}
section {
  flex: 1;
  background: rgba(255, 0, 0, 0.1);
}
<main>

  <section class="modal-container">
    <div class="modal">

      <div class="modal-content">
        <div class="modal-content__body">
          <code>BODY // </code>simply grows<br>
          <br>
          Container overflows when<br>
          the container height is reduced.<br>
          <br>
          In this case, the modal <strong>contains</strong><br>
          the flexbox, that handles the<br>
          body and the footer.<br>
          .<br>
          .<br>
          .<br>
          .<br>
          .<br>
          .<br>
        </div>
        <div class="modal-content__footer">
          <code>FOOTER // </code> Doesn't work
        </div>
      </div>

    </div>
  </section>

</main>
0 голосов
/ 18 мая 2018

Простое решение - сделать .modal гибкий контейнер с направлением колонки.

/* Centers the child */
.modal-container {
  display: flex;
  align-items: center;
  justify-content: center;
}
  
/* The box in the middle, that should grow
   organically, but be restricted as well */
.modal, .modal-content--merged-with-modal {
  width: 30rem;
  max-width: calc(50vw - 3rem);
  max-height: calc(100vh - 3rem);

  /* Irrelevant styling */
  background: rgba(255, 255, 255, 0.6);
  border-radius: 3px;
  line-height: 1.5rem;
}
  
  
.modal-content {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
  
.modal-content__body {
  flex: 1;
  min-height: 0;
  overflow-y: scroll;

  /* Irrelevant styling */
  padding: 0.75rem;
  background: rgba(0, 0, 255, 0.1);
}
  
  
.modal-content__footer {
  /* Irrelevant styling */
  border-top: 1px solid silver;
  background: rgba(0, 255, 0, 0.1);
  padding: 0.75rem;
}
.modal {
  display:flex;
  flex-direction:column;
}
  
  
/* Irrelevant styling to present the problem */
html {
  font-family: arial, sans-serif;
  font-size: 16px;
}
main {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  
  display: flex;
}
section {
  flex: 1;
  background: rgba(255, 0, 0, 0.1);
}
<main>

  <section class="modal-container">
    <div class="modal-content modal-content--merged-with-modal">
      <div class="modal-content__body">
        <code>BODY // </code> srollable<br>
        <br>
        Container resizes as expected when<br>
        the container height is reduced.<br>
        <br>
        In this case, the modal is the same<br>
        element, as the flexbox handling<br>
        the body and the footer.<br>
        .<br>
        .<br>
        .<br>
        .<br>
        .<br>
        .<br>
      </div>
      <div class="modal-content__footer">
        <code>FOOTER // </code> Works
      </div>
    </div>
  </section>

  <section class="modal-container">
    <div class="modal">

      <div class="modal-content">
        <div class="modal-content__body">
          <code>BODY // </code>simply grows<br>
          <br>
          Container overflows when<br>
          the container height is reduced.<br>
          <br>
          In this case, the modal <strong>contains</strong><br>
          the flexbox, that handles the<br>
          body and the footer.<br>
          .<br>
          .<br>
          .<br>
          .<br>
          .<br>
          .<br>
        </div>
        <div class="modal-content__footer">
          <code>FOOTER // </code> Doesn't work
        </div>
      </div>

    </div>
  </section>

</main>

Почему?

Первоначально .modal был элементом блока с набором max-height и значением по умолчаниюповедение переполнения (при переполнении) visible, и вы столкнулись с проблемой переполнения.

Делая .modal гибкий контейнер, вы вводите эффект shrink , какпо умолчанию у элемента Flex будет flex-shrink:1, поэтому его высота не будет превышать высоту контейнера Flex (он будет уменьшен для соответствия), и вы получите нужный результат.

Вы можете установитьflex-shrink:0 до .modal-content, и вы увидите ту же проблему переполнения, как если бы не было display:flex.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...