Почему этот элемент встроенного блока перемещается вниз?


238

Ниже приведен мой код, и я хочу понять, почему #firstDiv толкается вниз всеми браузерами. Я действительно хочу понять внутреннюю работу того факта, что его толкают вниз, а не тянут его вверх тем или иным способом. (а я умею выравнивать свои верхушки :))

И я знаю, что это переполнение: скрытое, которое вызывает его, но не уверен, почему это толкает этот div вниз.

body {
  width: 350px;
  margin: 0px auto;
}

#container {
  border: 15px solid orange;
}

#firstDiv {
  border: 10px solid brown;
  display: inline-block;
  width: 70px;
  overflow: hidden;
}

#secondDiv {
  border: 10px solid skyblue;
  float: left;
  width: 70px;
}

#thirdDiv {
  display: inline-block;
  border: 5px solid yellowgreen;
}
<div id="container">
  <div id="firstDiv">FIRST</div>
  <div id="secondDiv">SECOND</div>
  <div id="thirdDiv">THIRD
    <br>some more content<br> some more content
  </div>
</div>

http://jsfiddle.net/WGCyu/ .

Ответы:


361

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

Прежде всего, мы должны установить, что это реальный вопрос? Вот почему inline-blockэлемент " " толкается вниз.

Теперь мы начинаем понимать это и сначала убираем беспорядок.

1 - Почему бы не дать всем трем элементам одинаковую ширину границы? Давайте дадим это.

2 - Имеет ли плавающий элемент какую-либо связь с выталкиваемым вниз элементом inline-block? Нет, это не имеет к этому никакого отношения.

Итак, мы полностью удалили этот div . И вы наблюдаете такое же поведение выталкиваемого вниз элемента inline-block.

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

Базовая линия 'inline-block' является базовой линией его последнего блока строки в нормальном потоке, если только у него нет ни блоков in-flow line, либо если его свойство 'overflow' не имеет вычисленного значения, отличного от 'visible', в В этом случае базовой линией является нижний край поля.

Если вы не уверены в базовых показателях, вот краткое объяснение в простых словах.

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

Итак, мы можем сказать, что все символы, кроме «gjpqy», написаны полностью выше базовой линии, в то время как некоторая часть этих символов написана ниже базовой линии.

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

4 - Почему бы не добавить некоторые символы в наши элементы div, чтобы найти их базовые линии в элементе div? Здесь некоторые символы добавлены в div для уточнения базовой линии .

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

i) Если для рассматриваемого inline-block его свойство переполнения установлено в visible (что по умолчанию, поэтому устанавливать его не нужно). Тогда его базовая линия будет базовой линией содержащего блока линии.

ii) Если у рассматриваемого inline-блока свойство переполнения установлено на ДРУГОЕ, чем видимое. Тогда его нижнее поле будет находиться на базовой линии линии вмещающего ящика.

  • Первый пункт в деталях

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

Что ж, теперь я утверждаю, что у них одинаковые базовые показатели? ПРАВО?

5 - Тогда почему бы не перекрыть их и посмотреть, подходят ли они друг другу? Итак, я привожу третий div-слева: 35px; проверить, имеют ли они сейчас ту же базовую линию ?

Теперь мы доказали нашу первую точку зрения.

  • Второй пункт в деталях

Что ж, после объяснения первой точки вторая точка легко усваивается, и вы видите, что у первого элемента div, у которого свойство переполнения установлено на значение, отличное от visible (hidden), есть нижнее поле на базовой линии линии.

Теперь вы можете сделать пару экспериментов, чтобы проиллюстрировать это.

  1. Установить первый переполнение div: видимый (или удалить его вообще) .
  2. Установить переполнение второго div: кроме видимого .
  3. Установите оба переполнения div: кроме видимого .

Теперь верни свой беспорядок и посмотри, все ли у тебя хорошо.

  1. Верните ваш плавающий div (конечно, нужно
    увеличить ширину тела). Вы видите, что это не имеет никакого эффекта.
  2. Верните те же странные поля .
  3. Установите для зеленого div переполнение: видно, как вы задали в своем вопросе (это смещение происходит из-за увеличения ширины границы с 1 до 5 пикселей, поэтому, если отрегулировать отрицательный угол влево, вы увидите, что проблем нет)
  4. Теперь удалите дополнительные символы, которые я добавил, чтобы помочь в понимании . (и конечно удалить отрицательный левый)
  5. Наконец, уменьшите ширину тела, потому что нам больше не нужен более широкий.

И теперь мы вернулись туда, откуда начали.

Надеюсь, я ответил на ваш вопрос.


1
Спасибо за такое великолепное объяснение, но я не понял вашу точку зрения: «Тогда его базовая линия будет базовой линией содержащего блока линии». Это то же самое, что и базовая линия линии, как вы пояснили во втором пункте?
Шон Тейлор,

2
Поздний ответ. Я только что заметил ту же проблему, и я просто хотел поблагодарить Гэри Линдала за объяснение NICE.
TimSPQR

+1 ntgCleaner Несмотря на то, что я ценю хорошие ответы, у Гэри Линдала так много прочитанного, и я пропускаю только те несколько строк, где написано «Решение: XY»
Базовый кодер

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

@ntgCleaner спасибо мужик .. даже после всех объяснений я не смог заставить его работать. но ваш комментарий сделал это :)
supersan

330

Значением по умолчанию для vertical-alignCSS является baseline& это правило, которое также применяется при inline-blockчтении этого http://www.brunildo.org/test/inline-block.html

Напишите vertical-align:topв своем inline-blockDIV.

Проверьте это http://jsfiddle.net/WGCyu/1/


3
Вы читали мой вопрос? Я никогда не просил исправить проблему.
Шон Тейлор

23
@ShawnTaylor: название вопроса очень вводит в заблуждение. Мы инстинктивно читаем заголовок, затем снимаем код, если он есть. Мы редко читаем фактический текст. Это плохая привычка, но вы, вероятно, должны понимать, почему это происходит. : P
Purag

@sandeep: что касается вашего редактирования, то почему firstDiv выровнен по верху, даже если из него
Шон Тейлор,

@sandeep: Ссылка, которую вы предоставили, является информативной, но не помогает в этом вопросе, поскольку не описывает поведение в display:inline-blockсочетании с float:left/right.
Зета

2
@ThomasMcCabe Вряд ли; если кто-то публикует плохой ответ, его следует опровергнуть, чтобы показать будущим зрителям, что с ним что-то не так, независимо от их благих намерений. Тем не менее, я не думаю, что этот ответ когда-либо заслуживал отрицательного ответа; даже в своем первоначальном виде он предоставил ключевую часть головоломки, опущенную в принятом ответе: выравнивание базовой линии - это не единственный способ выравнивания элементов по вертикали, и что при изменении vertical-alignсвойства ни одна из сложностей, описанных в принятый ответ применяется.
Марк Амери


9

Посмотреть этот альтернативный пример. Причина такого поведения описана в модуле CSS3: строка: 3.2. Упаковка Line Box [1] :

Как правило, начальный край линейного блока касается начального края содержащего его блока, а конечный край касается конечного края содержащего его блока. Однако плавающие блоки могут находиться между краем содержащего блока и краем линейного блока. Таким образом, хотя линейные блоки в одном и том же контексте встроенного форматирования, как правило, имеют одно и то же продвижение встроенной последовательности (таковое для содержащего блока), они могут варьироваться, если доступное пространство встроенной последовательности уменьшается из-за поплавков [...]

Как видите, третий элемент перемещается вниз, хотя у него нет overflowсвойства. Причина должна быть где-то еще, чтобы найти. Второе поведение, которое вы заметили, описано в Каскадных таблицах стилей, редакция 1, уровень 2 (CSS 2.1). Спецификация: 9.5 Float [2] :

Поскольку поплавок не находится в потоке, непозиционированные блоки блоков, созданные до и после блока поплавка, движутся вертикально, как если бы поплавок не существовал. Тем не менее, текущий и последующие линейные блоки, созданные рядом с плавающей точкой, сокращаются по мере необходимости, чтобы освободить место для поля поля с плавающей точкой.

Все ваши display:inline-block;div используют baselineв этом случае специальный вид 10.8. Вычисления высоты строки: свойства 'line-height' и 'vertical-align' (самый конец) [3] :

Базовая линия 'inline-block' является базовой линией его последнего блока строки в нормальном потоке, если только у него нет ни блоков in-flow line, либо если его свойство 'overflow' не имеет вычисленного значения, отличного от 'visible', в В этом случае базовой линией является нижний край поля.

Поэтому, когда вы используете плавающие элементы и inline-blockэлементы, плавающий элемент будет сдвинут в сторону, а встроенное форматирование будет пересчитано в соответствии с 1 . С другой стороны, следующие элементы укорачиваются, если они не подходят. Поскольку вы уже работаете с минимальным пространством, другого способа изменить ваши элементы, кроме нажатия на них, нет 2 . В этом случае самый высокий элемент будет определять размер вашего упаковочного div, определяя таким образом baseline 3 , в то время как с другой стороны изменение положения и ширины, указанное в 2, не может быть применено к таким элементам с минимальной разнесенной максимальной высотой. В этом случае будет поведение, как в моей самой первой демонстрации.

И, наконец, причина, по которой вы не overflow:hiddenсможете #firstDivстолкнуться с нижним краем #container, хотя я не смог найти причину в разделе 11 . Без overflow:hiddenэтого работает как исключено и определено 2 и 3 . демонстрация

TL; DR: очень внимательно посмотрите на рекомендации W3 и реализации в браузере. По моему скромному мнению, плавающие элементы демонстрируют неожиданное поведение, если вы не знаете всех изменений, которые они вносят в окружающие вас элементы. Вот еще одна демонстрация, которая показывает общую проблему с поплавками.


3
Этот «стандарт» - невероятный беспорядок. Удивительно, что они смогли заставить этот материал вести себя согласованно во всех браузерах. Ой, подождите, нет, они никогда не могли этого сделать.
Трийнко

6

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

Во-первых, нам нужно понять, что inline-blockесть. Определение в MDN говорит:

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

Чтобы понять, что здесь происходит, нам нужно посмотреть vertical-align, и это значение по умолчанию baseline.

визуализация вертикального положения
На этой иллюстрации у вас есть эта цветовая диаграмма:
синий: базовая линия
красный: верх и низ высоты строки
Зеленый: верх и низ встроенного поля содержимого.

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

Посмотрите на эту визуализацию, где я нарисовал базовую линию на примере, где первый встроенный контейнер имеет некоторый текст, а следующий пустой:

Исходная линия нарисована

Если вы специально выровняете один элемент по верху, вы действительно скажете, что выровняли верх этого элемента по верху линейного блока.

Это может быть легче понять на примере.

div {
    display: inline-block;
    width: 100px;
    height: 150px;
    background: gray;
    vertical-align: baseline;
}
div#middle {
    vertical-align: top;
    height: 50px
}
   
div#right {
    font-size: 30px;
    height: 100px
}
<div id="left">
  <span>groovy</span>
</div>
<div id="middle">groovy</div>

<div id="right">groovy</div>

В результате я добавил синюю базовую линию и красную рамку для строки: что здесь происходит, так это то, что высота рамки строки зависит от того, как выложено содержимое всей строки. Это означает, что для расчета верхнего выравнивания сначала необходимо рассчитать базовые выравнивания. Элемент имеет , так что это не используется для базового позиционирования. но и расположены вертикально так, чтобы их базовые линии были выровнены. Когда это сделано, высота линейного блока увеличилась, потому что элемент был немного увеличен в результате увеличения размера шрифта. Затем можно рассчитать верхнюю позицию для элемента, и это вдоль верхней части линейного блока.Объяснил вертикальное выравнивание
#middlevertical-align:top#left#right#right#middle


1

проблема в том, что вы применили float: left на втором div. который заставляет второй div идти слева и ваш первый div падает и идет после вашего второго div. Если вы примените float: left в первом div, ваша проблема исчезнет.

Переполнение: скрытый не вызывает проблем для вашего макета, переполнение: скрытый влияет только на внутренние элементы div, он не имеет ничего общего с другими элементами, которые находятся снаружи.


Ну, если его толкают, потому что он идет вторым после плавающего div, то почему ThirdDiv не идет вниз?
Шон Тейлор

потому что третий div имеет второй div перед ним, который не имеет float: left;
Пал Сингх

Но где упомянуто это правило, что если какой-то div придет после плавающего div, то он упадет вниз? Я проверил w3.org.
Шон Тейлор

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

Нет, я не голосовал отрицательно, и да, ваш ответ не заслуживает отрицания. Просто проголосовал наверх.
Шон Тейлор

0

Попробуйте добавить padding:0;к телу и удалить поля ваших div.

Добавьте background-color:*anyцвет помимо фона *, чтобы проверить разницу.


Отредактируйте ответ для форматирования кода. Вы можете отформатировать код, добавив символ `перед началом кода и после окончания кода. как codeнапример: background-color:any color
ДЖИНО ШАДЖИ

0

Попробуйте сделать все свойства CSS всех элементов одинаковыми.

У меня была похожая проблема, и, исправляя ее, я обнаружил, что добавляю свойство Element со шрифтом в Div Element.

После удаления этого элемента со свойством Font выравнивание всех DIV было нарушено. Чтобы исправить это, я установил свойство Font для всех элементов DIV так же, как и для элемента, который в него помещен.

В следующем примере элемент Dropped класса ".dldCuboidButton" определен с font-size: 30 px.

Поэтому я добавил то же свойство в остальные классы, т.е. .cuboidRecycle, .liCollect, .dldCollect, которые используются элементами DIV. Таким образом, все элементы DIV следуют одним и тем же измерениям до и после добавления элемента в него.

.cuboidRecycle {
    height:40px; 
    width:'20px; float:right';
    overflow:'none';
    background-color:#cab287;
    color:#ffffff; 
    border-radius:8px; 
    text-align:'center'; 
    vertical-align:'top';
    display: inline-block;
    font-size: 30px; /* Set a font-size */
}


.liCollect {
    height:40px; 
    width:'20px; float:right';
    overflow:'none';
    background-color:#cab287;
    color:#ffffff; 
    border-radius:8px; 
    text-align:'center'; 
    vertical-align:'top';
    display: inline-block;
    font-size: 30px; /* Set a font-size */
}

.dldCollect {
    height:40px; 
    width:'20px; float:right';
    overflow:'none';
    background-color:#009933;
    color:#ffffff; 
    border-radius:8px; 
    text-align:'center'; 
    vertical-align:'top';
    display: inline-block;
    font-size: 30px; /* Set a font-size */
}


.dldCuboidButton {
    background-color:  #7c6436;
    color: white; /* White text */
    font-size: 30px; /* Set a font-size */
    border-radius: 8px;
    margin-top: 1px;
  }

Вот пример HTML, динамически созданного с использованием вышеуказанного CSS.

$("div#tabs").append(
  "<div id='" + newTabId + "'>#" + uniqueId + 
  "<input type=hidden id=hdn_tmsource_" + uniqueId + "  value='" + divTmpfest + "'>" + 
  "<input type=hidden id=leCuboidInfo_" + uniqueId + " value=''>" + 
  "<div id='" + divRecycleCuboid + "' class=cuboidRecycle ondrop='removeDraggedCuboids(event, ui)'  ondragover='allowDrop(event)'><font size='1' color='red'> Trash bin </font></div>" +
  "<div id='" + divDropLeCuboid  + "' class=liCollect ondrop='dropForLinkExport(event)'  ondragover='allowDrop(event)'><font size='1' color='red'>Drop Template Manifest Cuboid here</font></div>" +
  "<div id='" + divDropDwldCuboid  + "' class=dldCollect ondrop='dropForTMEntry(event)'  ondragover='allowDrop(event)'><font size='1' color='red'>Drop Template Cuboids here..</font></div>" +
  "</div>" 
);
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.