Почему этот элемент inline-block перемещается вниз? - PullRequest
229 голосов
/ 14 февраля 2012

Ниже приведен мой код, и я хочу понять, что почему #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/.

Ответы [ 8 ]

344 голосов
/ 15 февраля 2012

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Первая точка в деталях

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

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

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

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

  • Вторая точка в деталях

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

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

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

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

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

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

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

317 голосов
/ 14 февраля 2012

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

Напишите vertical-align:top в вашем inline-block DIV.

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

30 голосов
/ 10 июля 2015

Просто используйте vertical-align:top;

Демо

8 голосов
/ 14 февраля 2012

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

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

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

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

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

Базовая линия «встроенного блока» является базовой линией его последней строковой ячейки в нормальном потоке, если только у него нет ни строковых линейных блоков, либо если его свойство «переполнения» имеет вычисленное значение, отличное от «видимой» ', в этом случае базовой линией является нижний край поля.

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

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

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

3 голосов
/ 15 августа 2018

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

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

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

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

vertical position visualizations
На этой иллюстрации у вас есть диаграмма цвета:
Синий: базовый уровень
Красный: верх и низ линии-высота
Зеленый: верх и низ окна встроенного содержимого.

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

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

Baseline drawn

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

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

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>

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

1 голос
/ 14 февраля 2012

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

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

0 голосов
/ 04 марта 2018

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

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

После удаления этого элемента со свойством 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>" 
);
0 голосов
/ 19 сентября 2017

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

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

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