Почему внешний здесь не полностью окружает внутренний ?

#html #css

#HTML #css

Вопрос:

У меня здесь есть jsfiddle:https://jsfiddle.net/Lh7qbye2/7 /

И тестовая веб-страница здесь:https://shetline.com/test/test01.html

Вопрос в следующем: почему содержимое внутреннего не <div> предотвращает уменьшение внешнего <div> до размера, меньшего ширины внутреннего <div> , когда вы изменяете размер содержащего окна до узкого размера?

пример изображения внутреннего div, экранирующего внешний div

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

https://jsfiddle.net/Lh7qbye2/8/

https://shetline.com/test/test02.html

 

Я могу решить проблему для Chrome или Safari, используя:

width: fit-content;

…на внешнем <div> , но это не решает проблему для Firefox или Edge. Кроме того, MDN помечается fit-content как экспериментальный API:

Это экспериментальный API, который не следует использовать в производственном коде.

word-break: break-all на внешнем <div> вроде как помогает, но портит весь перенос слов. Если я попытаюсь компенсировать это, установив normal разрыв в тегах <p> и <button> , помощь, предоставляемая внешним break-all , исчезнет.

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

 

 body {
  margin: 4em;
}

.demo {
  background-color: #BFC;
  box-sizing: border-box;
  margin: 0;
  padding: 1em;
  position: relative;
  /* width: fit-content; // With this it works for Chrome or Safari, but not for Firefox or Edge. */
  /* word-break: break-all; // For some reason this sort of helps too, but of course messes up all word wrapping. */
  /* If I try to apply "word-break: normal" to <p> and <button> tags to compensate, the inner <div> leaks out again. */
}

.demo p:first-child {
  margin-top: 0;
}

.other-stuff {
  align-items: center;
  background-color: #AEB;
  display: flex;
}

button {
  margin-right: 1em;
}

.square {
  display: inline-block;
  background-color: #699;
  height: 80px;
  margin-right: 1em;
  min-width: 80px;
  width: 80px;
}

.circle {
  border-radius: 50px;
  display: inline-block;
  background-color: #969;
  height: 100px;
  margin-right: 1em;
  min-width: 100px;
  width: 100px;
}  
 <div class="demo">
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
  <div class="other-stuff">
    <button>Oneamp;nbsp;button</button>
    <div class="square"></div>
    <button>Anotheramp;nbsp;button</button>
    <div class="circle"></div>
    <button>Don'tamp;nbsp;click!</button>
  </div>
</div>  

Комментарии:

1. Вы могли бы добавить, flex-wrap: wrap чтобы элементы сгибания были обернуты, или вы могли бы добавить, overlfow: scroll чтобы их можно было прокручивать по горизонтали. В противном случае это ожидаемое поведение — больше нет места для элементов, которые должны поместиться, поэтому они выходят за пределы своего родительского контейнера.

2. Разве внешний div не должен просто перестать сжиматься, если его внутреннему содержимому требуется больше места? (Я объяснил ниже, почему flex-wrap — это не тот ответ, который я ищу.) Я почти уверен, что видел, как <div> ведут себя таким образом раньше, я просто не знаю, почему этого не происходит здесь.

3. поскольку ширина элемента block по умолчанию составляет 100% от его родительского элемента, поэтому его ширина не определяется его содержимым. Используйте встроенный блок, и вы получите то, что хотите

4. Спасибо, Темани! Опубликуйте это как официальный ответ, и я обязательно отмечу это как решение! 🙂

5. в качестве примечания, проблема начинается с other-stuff .. добавьте к нему фон, и вы увидите переполнение там

Ответ №1:

То, что вы хотите, можно сделать, используя комбинацию inline-block и min-width:100% . Ширина блочного элемента определяется на основе его родительского элемента (содержащего блок), в то время как inline-block ширина будет определяться его содержимым.

Добавление min-width:100% заставит его вести себя как элемент блока. в данном случае это не обязательно, поскольку у вас уже есть много контента, поэтому вы обязательно охватите всю ширину:

 body {
  margin: 4em;
}

.demo {
  background-color: #BFC;
  box-sizing: border-box;
  margin: 0;
  padding: 1em;
  position: relative;
  display:inline-block;
  min-width:100%;
}

.demo p:first-child {
  margin-top: 0;
}

.other-stuff {
  align-items: center;
  display: flex;
}

button {
  margin-right: 1em;
}

.square {
  display: inline-block;
  background-color: #699;
  height: 80px;
  margin-right: 1em;
  min-width: 80px;
  width: 80px;
}

.circle {
  border-radius: 50px;
  display: inline-block;
  background-color: #969;
  height: 100px;
  margin-right: 1em;
  min-width: 100px;
  width: 100px;
}  
 <div class="demo">
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
  <div class="other-stuff">
    <button>Oneamp;nbsp;button</button>
    <div class="square"></div>
    <button>Anotheramp;nbsp;button</button>
    <div class="circle"></div>
    <button>Don'tamp;nbsp;click!</button>
  </div>
</div>  

Уменьшите текст сверху и min-width:100% станет обязательным для использования во всю ширину.

Запустите фрагмент на всю страницу

 body {
  margin: 4em;
}

.demo {
  background-color: #BFC;
  box-sizing: border-box;
  margin: 0;
  padding: 1em;
  position: relative;
  display:inline-block;
}

.demo p:first-child {
  margin-top: 0;
}

.other-stuff {
  align-items: center;
  display: flex;
}

button {
  margin-right: 1em;
}

.square {
  display: inline-block;
  background-color: #699;
  height: 80px;
  margin-right: 1em;
  min-width: 80px;
  width: 80px;
}

.circle {
  border-radius: 50px;
  display: inline-block;
  background-color: #969;
  height: 100px;
  margin-right: 1em;
  min-width: 100px;
  width: 100px;
}  
 <div class="demo">
  <p>Lorem ipsum </p>
  <div class="other-stuff">
    <button>Oneamp;nbsp;button</button>
    <div class="square"></div>
    <button>Anotheramp;nbsp;button</button>
    <div class="circle"></div>
    <button>Don'tamp;nbsp;click!</button>
  </div>
</div>

<div class="demo" style="min-width:100%;">
  <p>Lorem ipsum </p>
  <div class="other-stuff">
    <button>Oneamp;nbsp;button</button>
    <div class="square"></div>
    <button>Anotheramp;nbsp;button</button>
    <div class="circle"></div>
    <button>Don'tamp;nbsp;click!</button>
  </div>
</div>  


Из спецификации:

Элементы на уровне блоков, не заменяемые в обычном потоке

Среди используемых значений других свойств должны соблюдаться следующие ограничения:

 'margin-left'   'border-left-width'   'padding-left'   'width'   'padding-right'   'border-right-width'   'margin-right' = width of containing block
  

Обратите внимание, что содержимое не играет никакой роли в определении ширины.

‘Встроенный блок’, не заменяемые элементы в обычном потоке

Если ‘width’ имеет значение ‘auto’, используемое значение — это ширина сжатия до подгонки

Вычисление ширины усадки по размеру аналогично вычислению ширины ячейки таблицы с использованием алгоритма автоматической компоновки таблицы. Грубо говоря: вычислите предпочтительную ширину путем форматирования содержимого без разрыва строк, кроме тех мест, где происходят явные разрывы строк, а также вычислите предпочтительную минимальную ширину, например, попробовав все возможные разрывы строк. В-третьих, найдите доступную ширину: в данном случае это ширина содержащего блока за вычетом используемых значений ‘margin-left’, ‘border-left-width’, ‘padding-left’, ‘padding-right’, ‘border-right-width’, ‘margin-right’ и ширины любых соответствующих полос прокрутки

ширина усадки равна: min(max(preferred minimum width, available width), preferred width)

Обратите внимание, как содержимое используется для определения ширины.


То же самое относится к любому отображаемому значению ( grid , flex , table и т.д.), И хитрость заключается в замене его inline-* эквивалентом ( inline-grid , inline-flex , inline-table и т.д.)

Комментарии:

1. До сегодняшнего дня у меня не было возможности попробовать это с Edge. К сожалению, с Edge использование inline-block не помогает, даже при добавлении width: 100% . То, что inline-block работает для меня, width: 100% не представляется необходимым.

2. @kshetline Я почти уверен, что у вас проблема, связанная с flexbox. Я не думаю, что встроенный блок может создать ошибку в Edge, но flexbox может

3. flex-box может быть частью проблемы, но я попытался изменить этот класс «other-stuff», чтобы использовать inline-flex, block, inline-block , и я попытался указать явную ширину и / или минимальную ширину … и внешнему div с классом «demo» все равно! Независимо от того, что я пробовал до сих пор, с Edge я не могу заставить div заботиться о ширине своего содержимого, независимо от того, что я пробовал.

4. @kshetline возможно, это заслуживает нового вопроса. Вероятно, вы обнаружили ошибку. Я не могу помочь, так как у меня нет Edge для тестирования

5. Или я могу просто подождать, пока текущий браузер Edge умрет естественной смертью 😁. Я попробовал эту проблему с Edge на основе Chromium, который сейчас находится в бета-версии, и там он работает просто отлично. Основная проблема, над которой я работаю, — это адаптивные макеты, и, вероятно, никто все равно не будет использовать Edge на крошечном экране.

Ответ №2:

Вам нужно использовать flex-wrap: wrap; , чтобы перенести содержимое на следующую строку.

Говоря это, поскольку вы используете фиксированную ширину для buttons , это ваш лучший вариант для экранов меньшего размера.

 body {
  margin: 4em;
}

.demo {
  background-color: #BFC;
  box-sizing: border-box;
  margin: 0;
  padding: 1em;
  position: relative;
}

.demo p:first-child {
  margin-top: 0;
}

.other-stuff {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
}

button {
  margin-right: 1em;
}

.square {
  display: inline-block;
  background-color: #699;
  height: 80px;
  margin-right: 1em;
  min-width: 80px;
  width: 80px;
}

.circle {
  border-radius: 50px;
  display: inline-block;
  background-color: #969;
  height: 100px;
  margin-right: 1em;
  min-width: 100px;
  width: 100px;
}  
 <div class="demo">
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
  <div class="other-stuff">
    <button>Oneamp;nbsp;button</button>
    <div class="square"></div>
    <button>Anotheramp;nbsp;button</button>
    <div class="circle"></div>
    <button>Don'tamp;nbsp;click!</button>
  </div>  

Комментарии:

1. Вы упускаете суть того, к чему я стремлюсь. Я не хочу, чтобы внутренний <div> обтекал больше и становился уже. (Во многих ситуациях это было бы желательно, да, но это не суть этого примера.) Я хочу, чтобы внешний <div> перестал сжиматься , когда он достигнет ширины внутреннего <div>.