Чому цей елемент вбудованого блоку штовхається вниз?


238

Далі йде мій код, і я хочу зрозуміти, що чому #firstDiv висувається вниз усіма браузерами. Мені дуже хочеться зрозуміти внутрішню роботу того факту, чому його відштовхування вниз, а не тягнення вгору так чи інакше. (і я знаю, як вирівняти їх верхівки :))

І я знаю, що його переповнення: приховане, що викликає його, але не впевнений, що саме його штовхає цю діву вниз.

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 - Чи має плаваючий елемент який-небудь зв’язок з тим, що елемент вбудованого блоку штовхається вниз? Ні, це не має нічого спільного.

Отже, ми цю діву взагалі зняли . І ви є свідком тієї ж поведінки, що елемент вбудованого блоку відсувається вниз.

Тут настає черга деякої літератури, щоб зрозуміти уявлення про прямокутні поля та про те, як вони вишиковуються в одному рядку esp, уважно читайте останній абзац, оскільки там лежить відповідь на ваше запитання.

Базова лінія "вбудованого блоку" є базовою лінією останнього вікна рядка у звичайному потоці, якщо тільки у нього немає або вікон рядків в потоці, або якщо його властивість "переповнення" має обчислене значення, відмінне від "видимого", у у цьому випадку базовою лінією є нижній край краю.

Якщо ви не впевнені в базовій лінії, то ось коротке пояснення простими словами.

Усі символи, крім 'gjpqy', написані на базовій лінії, ви можете думати про базову лінію так, як якщо б ви намалювали просту горизонтальну лінію, таку ж, як підкреслення прямо під цими "випадковими символами", то це буде базовою лінією, але тепер, якщо ви пишете будь-який із "gjpqy" символів на тому ж рядку, то нижня частина цих символів опуститься нижче рядка.

Отже, ми можемо сказати, що всі символи, крім 'gjpqy', написані повністю вище базової лінії, а частина цих символів написана нижче базової лінії.

3 - Чому б не перевірити, де є базовою лінією нашої лінії? Я додав кілька символів, які показують базову лінію нашої лінії.

4 - Чому б також не додати деяких символів до наших дівок, щоб знайти їх у базовому рядку? Тут деякі символи додаються в divs для уточнення базової лінії .

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

i) Якщо у відповідного вбудованого блоку властивість переповнення встановлено як видиме (що за замовчуванням не потрібно встановлювати). Тоді його базовою лінією було б базове значення, що містить блок рядка.

ii) Якщо у відповідного вбудованого блоку властивість переповнення встановлено на ІНШИЙ, ніж видимий. Тоді його нижнє поле було б на базовій лінії рядка, що містить поле.

  • Перший момент у деталях

Тепер перегляньте це ще раз, щоб уточнити свою концепцію того, що відбувається із зеленим дівом . Якщо все-таки плутанина, то сюди додається більше символів, близьких до зеленого div, щоб встановити базову лінію, що містить блок, і зелений базовий рядок div вирівняний.

Ну, я зараз стверджую, що вони мають однаковий базовий рівень? ПРАВО?

5 - Тоді чому б не перекрити їх і не побачити, чи правильно вони підходять одна до одної? Отже, я приношу третій div -left: 35px; щоб перевірити, чи є у них однаковий базовий рівень зараз ?

Тепер ми підтвердили нашу першу точку.

  • Другий момент у деталях

Отже, після пояснення першої точки друга точка легко засвоюється, і ви бачите, що перший div, який має властивість переповнення, встановленого на інше, ніж видиме (приховане), має нижнє поле на базовій лінії рядка.

Тепер ви можете зробити кілька експериментів, щоб додатково проілюструвати це.

  1. Встановіть перше переповнення: видно (або видаліть його повністю) .
  2. Встановіть другий перелив діви: крім видимого .
  3. Встановіть переливання обох div: крім видимих .

А тепер поверніть свою занепокоєння і подивіться, чи все виглядає на вас добре.

  1. Принесіть назад свій плаваючий div (звичайно, потрібно
    збільшити деяку ширину тіла). Ви бачите, що це не впливає.
  2. Поверніть ті самі непарні поля .
  3. Встановити зелений div для переповнення: видно, коли ви ставите у своєму запитанні (це нерівність пов’язана із збільшенням ширини кордону з 1px до 5px, тому якщо відрегулювати мінус, ви побачите, що проблеми немає)
  4. Тепер видаліть додаткових символів, які я додав, щоб допомогти зрозуміти . (і звичайно видалити мінус зліва)
  5. Нарешті зменшіть ширину тіла, тому що нам більше не потрібна ширша.

І тепер ми повернулися до того, з чого почали.

Сподіваюся, я відповів на ваше запитання.


1
Дякую за таке чудове пояснення, але я не зрозумів вашу думку "Тоді його базовою лінією було б базове значення, що містить блок рядка". Це збігається з базовою лінією, яку ви прояснили у другій точці?
Шон Тейлор

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

+1 ntgCleaner Незважаючи на те, що я ціную гарні відповіді, Гері Ліндаля так багато читати, і мені не вистачає лише тих кількох рядків, де написано "Рішення: XY"
Основний кодер

Я знайшов це детальне пояснення неймовірно інформативним, дякую. Я деякий час боровся з однією концепцією, і склав оновлену Скрипку, яка може уточнити для інших.
jonsanders101

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

330

Значенням за замовчуванням vertical-alignу CSS є 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
Пураг

@sandeep: щодо вашого редагування, чому тоді firstDiv вирівнюється до верху навіть тоді, коли з нього видалено вертикальне вирівнювання
Shawn Taylor

@sandeep: Надане вами посилання є інформативним, але не допомагає в цьому питанні, оскільки не описує поведінку в display:inline-blockпоєднанні з float:left/right.
Зета

2
@ThomasMcCabe Навряд чи; якщо хтось опублікував погану відповідь, він заслуговує на те, щоб повідомити майбутнім глядачам, що з цим щось не так, незалежно від їхніх добрих намірів. При цьому, я не думаю, що ця відповідь ніколи не заслуговує скорочення; навіть у своєму первісному вигляді він надав ключовий фрагмент головоломки, опущений прийнятою відповіддю - те, що базове вирівнювання не є єдиним способом вертикального вирівнювання елементів, і що якщо ви зміните vertical-alignвластивість, жодна зі складностей, описаних у застосовується прийнята відповідь.
Марк Амері


9

Перегляньте цей альтернативний приклад. Причина такої поведінки описана в модулі CSS3: рядок: 3.2. Обертання лінійної коробки [1] :

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

Як бачите, третій елемент висувається вниз, хоча він не має overflowвластивості. Причину треба десь знайти. Друга поведінка, яку ви помічаєте, описана в каскадних таблицях стилів Рівень 2 Версія 1 (CSS 2.1) Специфікація: 9.5 поплавків [2] :

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

У цьому випадку всі ваші display:inline-block;діви використовують спеціальний вид 10.8 Розрахунки висоти рядків: властивості "висота лінії" та "вертикальне вирівнювання" (в самому кінці) [3] :baseline

Базова лінія "вбудованого блоку" є базовою лінією останнього вікна рядка у звичайному потоці, якщо тільки у нього немає або вікон рядків в потоці, або якщо його властивість "переповнення" має обчислене значення, відмінне від "видимого", у у цьому випадку базовою лінією є нижній край краю.

Отже, коли ви використовуєте плаваючі елементи та inline-blockелементи, плаваючий елемент буде висунутий убік, а вбудоване форматування буде перераховано відповідно до 1 . З іншого боку, наступні елементи скорочуються, якщо вони не підходять. Оскільки ви вже працюєте з мінімальною кількістю місця, немає іншого способу змінити свої елементи, ніж натискати на них 2 . У цьому випадку найвищий елемент визначатиме розмір вашої обгорткової ділянки, визначаючи, таким чином, baseline 3 , а з іншого боку, зміна положення та ширини, зазначені у 2, не може бути застосована до таких мінімально розташованих елементів максимальної висоти. У цьому випадку виникла поведінка, як у моїй першій демонстрації.

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

TL; DR: уважно ознайомтеся з рекомендаціями W3 та реалізаціями у браузері. На мою скромну думку, плаваючі елементи налаштовані демонструвати несподівану поведінку, якщо ви не знаєте всіх змін, які вони вносять до оточуючих вас елементів. Ось ще одна демонстрація, яка показує поширену проблему з floats.


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: зліва на другому розділі. що змушує другий дів вийти ліворуч, а ваш перший дів падає і приходить після другого. Якщо ви застосуєте float: ліворуч на першому діві також, ваша проблема не зникне.

переповнення: прихований не викликає проблем у вашій компоновці, переповнення: прихований впливає лише на внутрішні елементи дива, він не має нічого спільного з іншими елементами, які знаходяться зовні.


Добре, якщо його натискати, тому що він приходить другий після поплавця div, то чому 3rdDiv не йде вниз?
Шон Тейлор

тому що третій div має другий div перед ним, який не має плавати: left;
Пал Сінгх

Але де це правило згадується, що якщо якийсь дів прийде після плаваючого діва, то він знизиться вниз? Я перевірив w3.org.
Шон Тейлор

елемент, який не плаває, падає до базової лінії, і якщо ви провели негативний голос, ніж я повинен сказати, що це була найбільш логічна відповідь
Пал Сінгх

Ні, я не голосував негативно, і так, ваша відповідь не заслуговує негативної. Просто голосували вгору.
Шон Тейлор

0

Спробуйте додати padding:0;до тіла і зняти поле своїх дівок.

Додайте background-color:*anyколір вбік від фону *, щоб перевірити різницю.


Відредагуйте відповідь на код формату. Ви можете відформатувати код, додавши символ `перед запуском коду та після закінчення коду. в якості , codeнаприклад :. background-color:any color
JINO SHAJI

0

Спробуйте зробити всі властивості CSS усіх елементів однаковими.

У мене була подібна проблема, і під час виправлення цієї проблеми я виявив, що я перекидаю елемент Div Element з Div Element.

Після скидання цього елемента з властивістю шрифту вирівнювання всіх DIV було порушено. Щоб виправити це, я встановив властивість Font для всіх елементів DIV так само, як і елемент, який потрапляє в нього.

У наступному прикладі випадаючий елемент класу ".dldCuboidButton" визначений розміром шрифту: 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.