Я пытаюсь вложить два дочерних элемента в оболочку, которая указывает боковые поля, поэтому между его содержимым и сторонами экрана есть пространство, когда дисплей узкий, и max-width
, когда дисплей широкий.
У второго дочернего элемента есть некоторое переполнение, которое должно быть видно, в то время как первый дочерний элемент должен оставаться строго в пределах поля содержимого оболочки. После удаления первого дочернего элемента второй дочерний элемент ведет себя так, как хотелось бы. Когда я добавляю первый дочерний элемент, он, кажется, полностью игнорирует поля обертки, растягивая поле содержимого обертки и ломая вместе с ним второго дочернего элемента.
Применение overflow: hidden
к обертке устраняет проблему полей, но обрезает второй дочерний элемент. Применение полей к первому дочернему элементу не привело к его сворачиванию с родителем, поскольку он находится в новом контексте форматирования блока.
Единственный обходной путь, который я нашел до сих пор, это сделать:
.wrapper {
> * {
margin-left: 1.5rem;
margin-right: 1.5rem;
}
}
и увеличьте максимальную ширину обертки на 3rem, но я надеялся, что есть какое-то решение, которое не требует от меня смещения поля от обертки к ее дочерним элементам.
https://codepen.io/HybridCore/pen/jjoWmd
body {
background-color: #000;
color: #FFF;
display: flex;
justify-content: center;
}
.wrapper {
margin: 0 1.5rem;
max-width: 40rem;
width: 100%;
}
.fit_content_box {
display: flex;
align-items: center;
}
.L {
min-width: 0;
flex: 1 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.R {
margin-left: 1rem;
height: 1rem;
width: 1rem;
background-color: #FFF;
}
.overflow {
display: flex;
justify-content: space-between;
}
.overflow>div {
width: 0;
display: flex;
justify-content: center;
}
<body>
<div class = "wrapper">
<div class = "fit_content_box">
<p class = "L">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 = "R"></div>
</div>
<div class = "overflow">
<div>
<p>0</p>
</div>
<div>
<p>12</p>
</div>
<div>
<p>24</p>
</div>
</div>
</div>
</body>
@TarunLalwani, это не решает проблему. Смотрите ответ Темани Афиф ниже.
Похоже, что источником проблемы является white-space: nowrap
, который применяется к элементу контента (.L
) внутри первого дочернего элемента (.fit_content_box
).
.L {
border: solid 1px #FF0000;
min-width: 0;
flex: 1 0;
overflow: hidden;
white-space: nowrap; <--- trouble maker
text-overflow: ellipsis;
}
Если вы удалите эту строку кода, ваши боковые поля на .wrapper
будут работать как положено.
Итак, ключевые вопросы:
white-space
внучатого потомка (.L
) сворачивает боковые поля прародителя (.wrapper
)?white-space
сворачивает боковые поля, когда они применяются к родителю (.fit_content_box
)?overflow
применительно к прародителю (.wrapper
) со значением, отличным от visible
, позволяет полям оставаться неизменными для внучатого потомка (.L
)?Вы написали:
Applying the margins to the first child didn't make it collapse with the parent since it's in a new block formatting context.
На самом деле, это не проблема обычного схлопывания маржи, потому что:
Мы говорим о горизонтальных полях, горизонтальные поля никогда не схлопываются и
Мы работаем внутри гибкого контейнера, и файл поля внутри гибкого контейнера никогда не схлопываются.
Таким образом, хотя полное понимание проблемы может заключаться в контексте блочного (или гибкого) форматирования, я не уверен, что именно поэтому поля родителя не схлопываются.
Это то, что я понял по этому вопросу. Я сделаю больше исследований, когда у меня будет время. Или, может быть, кто-то еще может взять его отсюда.
Я понимаю, что overflow: hidden
обрезает содержимое до заполнения (не содержимое, по крайней мере, глядя на MDN и определение уровня 3 модуля переполнения CSS). Однако я не понимаю, почему игнорируется поле обертки. Я думал, что два дочерних элемента находятся строго в поле содержимого оболочки с точки зрения размещения и будут изменять размер, чтобы соответствовать этому полю содержимого. Судя по тому, как я себе это представляю, на поле обертки не должно быть никакого влияния.
Да, это хороший момент. Я еще раз просмотрел ваш вопрос и пересмотрел свой ответ.
Название изменено, чтобы отразить ваш ответ. Я попытался сделать еще несколько тестов, но не получил результатов. Как ни странно, кажется, что он уважает поля своих предшественников только в том случае, если это элемент body и ничего больше (ваше первоначальное предложение о том, к чему применить поле). Не уверен, является ли это ошибкой реализации, ошибкой в спецификации или предполагаемым поведением.
Мой первоначальный ответ предлагал набивка, а не поле для элемента body
. Держу пари, что это предполагаемое поведение. Возможно, это ошибка, но поведение одинаково во всех основных браузерах (я тестировал Chrome, FF и Edge).
добавил ответ
Не стесняйтесь принять ответ @TemaniAfif, если хотите. Он разгадал загадку.
У вас в основном две проблемы:
width:100%
для обертки, и это не учитывает маржу, поэтому логически у вас будет переполнение, а поскольку тело является гибким контейнером с justify-content:center
, маржа будет переполняться одинаково с обеих сторон, поэтому вы думаете, что это не применяется.min-width
ограничение flexbox, что вынуждает вас установить width:100%
, думая, что это хорошее решение. Это же ограничение также предотвращает сжатие элемента ниже указанного вами значения 100% (связано: Почему гибкий элемент ограничен родительским размером?)Чтобы исправить это, вам нужно удалить width:100%
из оболочки и вместо этого рассмотреть min-width:0
. Вы также можете удалить min-width
, примененный к .L
, и вам нужно учитывать flex-shrink:0
на .R
(или заменить его ширину на min-width
)
body {
background-color: #000;
color: #FFF;
display: flex;
justify-content: center;
}
.wrapper {
margin: 0 1.5rem;
max-width: 40rem;
min-width:0;
}
.fit_content_box {
display: flex;
align-items: center;
}
.L {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.R {
margin-left: 1rem;
flex-shrink:0;
height: 1rem;
width: 1rem;
background-color: #FFF;
}
.overflow {
display: flex;
justify-content: space-between;
}
.overflow>div {
width: 0;
display: flex;
justify-content: center;
}
<body>
<div class = "wrapper">
<div class = "fit_content_box">
<p class = "L">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 = "R"></div>
</div>
<div class = "overflow">
<div>
<p>0</p>
</div>
<div>
<p>12</p>
</div>
<div>
<p>24</p>
</div>
</div>
</div>
</body>
Если вы хотите, чтобы элемент оставался как минимум равным max-width
, когда есть небольшое количество текста, добавьте flex-grow:1
:
body {
background-color: #000;
color: #FFF;
display: flex;
justify-content: center;
}
.wrapper {
margin: 0 1.5rem;
max-width: 40rem;
min-width:0;
flex-grow:1;
}
.fit_content_box {
display: flex;
align-items: center;
}
.L {
flex-grow:1;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.R {
margin-left: 1rem;
flex-shrink:0;
height: 1rem;
width: 1rem;
background-color: #FFF;
}
.overflow {
display: flex;
justify-content: space-between;
}
.overflow>div {
width: 0;
display: flex;
justify-content: center;
}
<body>
<div class = "wrapper">
<div class = "fit_content_box">
<p class = "L">Lorem ipsum dolor sit e dolor sit e</p>
<div class = "R"></div>
</div>
<div class = "overflow">
<div>
<p>0</p>
</div>
<div>
<p>12</p>
</div>
<div>
<p>24</p>
</div>
</div>
</div>
</body>
Чтобы лучше проиллюстрировать (1), вот еще один пример с переполненным полем, которое вы вряд ли заметите:
.container {
width:200px;
margin:auto;
display:flex;
justify-content:center;
}
.box {
height:50px;
width:100%;
background:red;
}
<div class = "container">
<div class = "box" style = "margin:0 5966px">a_long_text_to_avoid_the_shrink</div>
</div>
<div class = "container">
<div class = "box">a_long_text_to_avoid_the_shrink</div>
</div>
Вы можете видеть, что у нас есть длинный текст, заставляющий наш элемент не сжиматься (ограничение минимальной ширины), элемент принимает полную ширину, и мы центрируем содержимое. Это приведет к переполнению поля, как если бы поля не было.
Если вы нарушите одно правило, вы увидите эффект маржи.
Удалите длинный текст:
.container {
width:200px;
margin:auto;
display:flex;
justify-content:center;
}
.box {
width:100%;
height:50px;
background:red;
}
<div class = "container">
<div class = "box" style = "margin:0 5966px">a long text to avoid the shrink</div>
</div>
<div class = "container">
<div class = "box">a long text to avoid the shrink</div>
</div>
Снять центровку:
.container {
width:200px;
margin:auto;
display:flex;
}
.box {
width:100%;
height:50px;
background:red;
}
<div class = "container">
<div class = "box" style = "margin:0 5966px">a_long_text_to_avoid_the_shrink</div>
</div>
<div class = "container">
<div class = "box">a_long_text_to_avoid_the_shrink</div>
</div>
Сделайте разные поля с каждой стороны
.container {
width:200px;
margin:auto;
display:flex;
justify-content:center;
}
.box {
width:100%;
height:50px;
background:red;
}
<div class = "container">
<div class = "box" style = "margin:0 500px 0 400px">a_long_text_to_avoid_the_shrink</div>
</div>
<div class = "container">
<div class = "box">a_long_text_to_avoid_the_shrink</div>
</div>
(2) white-space
создает ограничение минимальной ширины, предотвращающее сжатие элемента.
Вот пример для иллюстрации:
.body {
display: flex;
justify-content: center;
margin: 10px 100px;
border: 2px solid red;
}
.wrapper {
border: 1px solid;
margin: 0 20px;
}
.box {
display:flex;
}
The below is a logical behavior where the text will wrap and the margin are respected
<div class = "body">
<div class = "wrapper">
<div class = "box">
<div>some long text here some long text here some long text here some long text here</div>
</div>
</div>
</div>
Let's add white-space:nowrap. We add a min-width contraint since we said to the text to never wrap thus our flex element will not shrink and overflow.
<div class = "body">
<div class = "wrapper">
<div class = "box">
<div style = "white-space:nowrap">some long text here some long text here some long text here some long text here</div>
</div>
</div>
</div>
If we add width:100% we force its width to be the same as the container BUT the margin aren't included and are kept outside (the text will logically overflow)
<div class = "body">
<div class = "wrapper" style = "width:100%">
<div class = "box">
<div style = "white-space:nowrap">some long text here some long text here some long text here some long text here</div>
</div>
</div>
</div>
Now if we add min-width:0 we remove the constaint of minimum sizing and we can see the margin again even if we keep width:100% because the element will shrink by default
<div class = "body">
<div class = "wrapper" style = "width:100%;min-width:0">
<div class = "box">
<div style = "white-space:nowrap">some long text here some long text here some long text here some long text here</div>
</div>
</div>
</div>
Хитрость заключается в том, что мы центрируем элемент и применяем одно и то же поле с обеих сторон, что создаст иллюзию сворачивающегося поля, но это просто одинаковое переполнение поля с обеих сторон.
Давайте немного изменим поле с одной стороны, чтобы увидеть небольшое смещение с другой стороны:
.body {
display: flex;
justify-content: center;
margin: 10px 100px;
border: 2px solid red;
}
.wrapper {
border: 1px solid;
margin: 0 20px 0 40px;
}
.box {
display:flex;
}
The below is a logical behavior where the text will wrap and the margin are respected
<div class = "body">
<div class = "wrapper">
<div class = "box">
<div>some long text here some long text here some long text here some long text here</div>
</div>
</div>
</div>
Let's add white-space:nowrap. We add a min-width contraint since we said to the text to never wrap thus our flex element will not shrink and overflow.
<div class = "body">
<div class = "wrapper">
<div class = "box">
<div style = "white-space:nowrap">some long text here some long text here some long text here some long text here</div>
</div>
</div>
</div>
If we add width:100% we force its width to be the same as the container BUT the margin aren't included and are kept outside (the text will logically overflow)
<div class = "body">
<div class = "wrapper" style = "width:100%">
<div class = "box">
<div style = "white-space:nowrap">some long text here some long text here some long text here some long text here</div>
</div>
</div>
</div>
Now if we add min-width:0 we remove the constaint of minimum sizing and we can see the margin again even if we keep width:100% because the element will shrink by default
<div class = "body">
<div class = "wrapper" style = "width:100%;min-width:0">
<div class = "box">
<div style = "white-space:nowrap">some long text here some long text here some long text here some long text here</div>
</div>
</div>
</div>
Причина, по которой я делаю width: 100%
, заключается в том, что обертка будет занимать как минимум максимальную ширину, если это позволяет место. Если содержимое .L не переполняется, оболочка схлопывается по ширине. Вот пример пера: codepen.io/HybridCore/pen/rXxaby
В основном я хочу, чтобы оболочка поддерживала максимальную ширину, если это позволяет окно просмотра, независимо от того, достаточно ли .L текста, чтобы подтолкнуть оболочку к максимальной ширине.
@HybridCore это просто, просто добавьте к нему flex-grow: 1;
, чтобы позволить ему расти, не используйте width:100%
Классическая min-width
проблема по умолчанию (о котором я так много писал!). Я полностью упустил из виду гибкий контейнер в элементе body
. Спасибо за ваше время на это. Отличный ответ.
@Michael_B, зачем устанавливать
width: 0
, который вызывает проблему? codepen.io/tarunlalwani/pen/voNGNw