Предотвратить переполнение гибкого контейнера вдоль поперечной оси - PullRequest
2 голосов
/ 11 мая 2019

В приведенном ниже примере я хочу расположить элемент с идентификатором child, поэтому его правый верхний угол соответствует правому верхнему углу элемента с идентификатором container. Другими словами, желательно, чтобы child торчал влево и вниз от container, а его правый и верхний края были выровнены по container.

.

Однако, как видите, child сжимается до ширины container. Но не полностью - во втором примере ясно, что child сжимается до некоторого предела, а затем начинает вести себя как нужно (т.е. перемещается влево относительно container).

Может кто-нибудь объяснить, какие магические силы вовлечены в такое поведение и как я могу указать, что child не должен сжиматься ниже своего собственного размера?

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

  <div id="container" style="position: relative; width: 100px; height: 100px; left: 50px; border: 1px solid red">
      <div id="child" style="position: absolute; display:flex; flex-direction: column; right: 0px; border: 1px solid blue">
        <div style="
display:flex">
          <div style="flex: 1 0 auto">Long text 1</div>
          <div style="flex: 0 0 auto">Long text 2</div>
        </div>
        <div style="display:flex">
          <div style="flex: 1 0 auto">Long text 1</div>
          <div style="flex: 0 0 auto">Long text 2</div>
        </div>
      </div>
  </div>
  <hr>
  <div id="container" style="position: relative; width: 50px; height: 100px; left: 50px; border: 1px solid red">
      <div id="child" style="position: absolute; display:flex; flex-direction: column; right: 0px; border: 1px solid blue">
        <div style="
display:flex">
          <div style="flex: 1 0 auto">Long text 1</div>
          <div style="flex: 0 0 auto">Long text 2</div>
        </div>
        <div style="display:flex">
          <div style="flex: 1 0 auto">Long text 1</div>
          <div style="flex: 0 0 auto">Long text 2</div>
        </div>
      </div>
  </div>
  <hr>
  <div id="container" style="position: relative; width: 50px; height: 100px; left: 50px; border: 1px solid red">
      <div id="child" style="position: absolute; display:flex; flex-direction: column; right: 0px; border: 1px solid blue">
        <div style="white-space: nowrap;">This is just&nbsp;ridiculous</div>
        <div style="
display:flex">
          <div style="flex: 1 0 auto">Long text 1</div>
          <div style="flex: 0 0 auto">Long text 2</div>
        </div>
        <div style="display:flex">
          <div style="flex: 1 0 auto">Long text 1</div>
          <div style="flex: 0 0 auto">Long text 2</div>
        </div>
      </div>
  </div>

1 Ответ

1 голос
/ 11 мая 2019

Немного сложно объяснить, но здесь поведение сжимается до соответствия абсолютного элемента контролирует ширину вашего элемента.Из спецификации мы имеем:

Расчет ширины сжатия для подгонки аналогичен вычислению ширины ячейки таблицы с использованием алгоритма автоматической компоновки таблицы.Грубо говоря: вычислите предпочтительную ширину, отформатировав содержимое без разрывов строк, кроме тех, где происходят явные разрывы строк, а также вычислите предпочтительную минимальную ширину, например, попробовав все возможные разрывы строк .CSS 2.1 не определяет точный алгоритм.В-третьих, вычислите доступную ширину: это определяется путем определения «ширины» после установки «влево» (в случае 1) или «вправо» (в случае 3) на 0.

Тогда сжатие доширина подгонки: min(max(preferred minimum width, available width), preferred width).

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

Чтобы лучше понять, давайте удалим некоторые свойства:

#container {
  animation:change 5s linear infinite alternate;
}

@keyframes change {
  from {
    width:300px;
  }
  to {
    width:50px;
  }
}
<div id="container" style="position: relative; height: 100px; left: 50px; border: 1px solid red">
      <div id="child" style="position: absolute; display:flex; flex-direction: column; right: 0px; border: 1px solid blue">
        <div style="
display:flex">
          <div style="/*flex: 1 0 auto*/">Long text 1</div>
          <div style="/*flex: 0 0 auto*/">Long text 2</div>
        </div>
  
      </div>
  </div>

Вы можете ясно видеть, как абсолютный элемент будет соответствовать его содержанию (предпочтительной ширине), и когда будет меньше места, текст начнет переноситься, пока мы не достигнемпредпочтительная минимальная ширина, и элемент перестанет дрожать.Это предел, который у вас есть.

Добавление свойств flex это ничего не изменит, поскольку эти свойства не будут влиять на поведение ширины их родительского элемента, но они будут учитывать эту ширину для выполнения необходимых вычислений (расти, уменьшаться и т. д.)

#container {
  animation:change 5s linear infinite alternate;
}

@keyframes change {
  from {
    width:300px;
  }
  to {
    width:50px;
  }
}
<div id="container" style="position: relative; height: 100px; left: 50px; border: 1px solid red">
      <div id="child" style="position: absolute; display:flex; flex-direction: column; right: 0px; border: 1px solid blue">
        <div style="
display:flex">
          <div style="/*flex: 1 0 auto*/">Long text 1</div>
          <div style="/*flex: 0 0 auto*/">Long text 2</div>
        </div>
  
      </div>
  </div>
  <div id="container" style="position: relative; height: 100px; left: 50px; border: 1px solid red">
      <div id="child" style="position: absolute; display:flex; flex-direction: column; right: 0px; border: 1px solid blue">
        <div style="
display:flex">
          <div style="flex: 1 0 auto">Long text 1</div>
          <div style="flex: 0 0 auto">Long text 2</div>
        </div>
  
      </div>
  </div>

Вы можете четко заметить, что у нас одинаковая ширина в обоих случаях, и во втором примере мы просто сказали нашим элементам не сжиматься, поэтому у нас будет переполнение:


В третьем примере, добавив white-space: nowrap;, вы просто увеличили предпочтительную минимальную ширину, так как отключили разрыв строки, поэтому браузер будет считать предпочтительную минимальную ширину равной предпочтительной ширине:

#container {
  animation:change 5s linear infinite alternate;
}

@keyframes change {
  from {
    width:300px;
  }
  to {
    width:50px;
  }
}
<div id="container" style="position: relative; height: 100px; left: 50px; border: 1px solid red">
      <div id="child" style="position: absolute; display:flex; flex-direction: column; right: 0px; border: 1px solid blue">
        <div style="
display:flex;white-space:nowrap">
          <div style="/*flex: 1 0 auto*/">Long text 1</div>
          <div style="/*flex: 0 0 auto*/">Long text 2</div>
        </div>
  
      </div>
  </div>
  <div id="container" style="position: relative; height: 100px; left: 50px; border: 1px solid red">
      <div id="child" style="position: absolute; display:flex; flex-direction: column; right: 0px; border: 1px solid blue">
        <div style="
display:flex;white-space:nowrap">
          <div style="flex: 1 0 auto">Long text 1</div>
          <div style="flex: 0 0 auto">Long text 2</div>
        </div>
  
      </div>
  </div>

Поскольку вы используете flexbox, вы можете отрегулировать выравнивание, чтобы контролировать переполнение текста и сделать его слева:

#container {
  animation:change 5s linear infinite alternate;
}

@keyframes change {
  from {
    width:300px;
  }
  to {
    width:50px;
  }
}
  <div id="container" style="position: relative; height: 100px; left: 50px; border: 1px solid red">
      <div id="child" style="position: absolute; display:flex; flex-direction: column; right: 0px; border: 1px solid blue">
        <div style="
display:flex;justify-content:flex-end;">
          <div style="flex: 1 0 auto">Long text 1</div>
          <div style="flex: 0 0 auto">Long text 2</div>
        </div>
  
      </div>
  </div>

как я могу указать, что дочерний элемент не должен сжиматься ниже его собственного размера?

Проблема заключается в том, что дочерний элемент(абсолютный элемент) не имеет собственного размера, и его размер определяется алгоритмом сжатия к размеру.Единственный способ - убедиться, что предпочтительная минимальная ширина достаточно велика, чтобы избежать нежелательного сжатия (например, при использовании white-space:nowrap)

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