Чому цей стиль CSS margin-top не працює?


321

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

Що я очікував:
Що я очікував з запасом: 50px 50px 50px 50px;

Що я отримую:
Що я отримую з маржею: 50px 50px 50px 50px;

Код:

#outer {
    	width: 500px; 
    	height: 200px; 
    	background: #FFCCCC;
    	margin: 50px auto 0 auto;
    	display: block;
}
#inner {
    	background: #FFCC33;
    	margin: 50px 50px 50px 50px;
    	padding: 10px;
    	display: block;
}
<div id="outer">
  <div id="inner">
  	Hello world!
  </div>
</div>

W3Schools не мають пояснення, чому маржа поводиться таким чином.


4
ти намагався плавати внутрішнім?
Півень

6
гул .. З float:left;ним працює ... але навіщо це потрібно. Я не хочу, щоб він плавав. І чому маржа для лівих / правих працює?
jamietelin

44
Ласкаво просимо у світ веселощів алгоритму краху маржі CSS!
GordonM

10
W3Schools vs. W3CDocs ... Я думаю, що у нас є переможець. : D
enderskill

15
jsЗагадка про це, щоб врятувати наступного хлопця 25 секунд jsfiddle.net/kLeu9
CodyBugstein

Відповіді:


453

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

Ось відповідні моменти зі специфікації W3C:

8.3.1 Маржини згортання

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

Суміжний вертикальний край руйнується [...]

Два поля примикають, якщо і тільки якщо:

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

Ви можете виконати будь-що з наступного, щоб запобігти руйнуванню поля:

Причина, що описані вище варіанти запобігає руйнуванню поля, полягає в тому, що:

  • Поля між плаваючою коробкою та будь-яким іншим ящиком не руйнується (навіть між поплавком та його дітьми, що надходять у рух).
  • Межі елементів, які встановлюють нові контекстні формати блоку (наприклад, поплавці та елементи із 'переповненням', відмінним від 'видимого'), не руйнуються зі своїми дітьми в потоці.
  • Поля коробки вбудованого блоку не руйнуються (навіть не з дітьми, що надходять у рух).

Лівий і правий поля поводяться так, як ви очікували, оскільки:

Горизонтальні поля ніколи не руйнуються.



2
Ця відповідь хитається! Просто щось додати. Ваша цитата w3c говорить про це, але я зрозумів лише зараз. Тож для того, щоб зрозуміти для інших, ви також можете надати #outer межу.
driechel

Здається, ланка в плаваючому віці порушена
EP

@episanty: Ось що відбувається, коли ви посилаєтесь на коментар. Від’єднано.
BoltClock

Я знаю - просто хотів вас повідомити. Оскільки ви ♦ -зключений, я подумав, що ви можете скористатися коментарем - або змінити свою публікацію відповідно. Дякую за добру відповідь, до речі.
EP

92

Спробуйте скористатися display: inline-block;внутрішнім ділом.

#outer {
    width:500px; 
    height:200px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:block;
}
#inner {
    background:#FFCC33;
    margin:50px 50px 50px 50px;
    padding:10px;
    display:inline-block;
}

6
Хороша відповідь. Було б краще, якби це пояснило, чому ця зміна усуває проблему.
JohnFx

1
Гаразд, це химерно! Чому це працює? Яке логічне пояснення, чому це не працює так, як можна було б очікувати. Поля зліва / справа працює без display:inline-block;. При використанні також повертається те display:inline-block;, що ви втрачаєте ширину 100% на діві.
jamietelin

3
перемикання його на inline-block змушує браузер переоцінювати розмір div після його розміщення та інших правил.
Півень

Спробував це для моєї проблеми, зробив ефект сходів.
Джоні

1
display:inline-blockпрацював на мене. Дуже дякую.
starkeen

24

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

Рішення 1

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

це означає, що я можу додати float:leftдо #outerабо #inner demo1 .

також зауважте, що floatможе визнати недійсним autoмаржу.

Рішення 2

Межі елементів, які встановлюють нові контекстні формати блоку (наприклад, поплавці та елементи із 'переповненням', відмінним від 'видимого'), не руйнуються зі своїми дітьми в потоці.

крім visible, давайте введемо overflow: hiddenв #outer. І цей спосіб видається досить простим і гідним. Мені це подобається.

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    overflow: hidden;
}
#inner {
    background: #FFCC33;
    height: 50px;
    margin: 50px;
}

Рішення 3

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

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    position: absolute; 
}
#inner{
    background: #FFCC33;
    height: 50px;
    margin: 50px;
}

або

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    position: relative; 
}
#inner {
    background: #FFCC33;
    height: 50px;
    margin: 50px;
    position: absolute;
}

ці два методи порушать нормальний потік div

Рішення 4

Поля коробки вбудованого блоку не руйнуються (навіть не з дітьми, що надходять у рух).

те саме, що і @enderskill

Рішення 5

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

Це не має великого стосунку до питання, оскільки це руйнування між братами і сестрами. це, як правило, означає, якщо у верхній коробці є, margin-bottom: 30pxа в коробці рідних братів margin-top: 10px. Загальна маржа між ними 30pxзамість 40px.

Рішення 6

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

Це дуже цікаво, і я можу просто додати одну верхню межу

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    border-top: 1px solid red;

}
#inner {
    background: #FFCC33;
    height: 50px;
    margin: 50px;

}

А також <div>є рівнем блоку за замовчуванням, тому вам не доведеться оголошувати це спеціально. Вибачте за те, що не міг опублікувати більше 2 посилань та зображень через мою репутацію початківця. Принаймні ви знаєте, звідки виникає проблема наступного разу, коли ви бачите щось подібне.


14

Не знаєте, чому те, що у вас не працює, але ви можете додати

overflow: auto;

до зовнішньої діви.


Набір різних рішень цієї проблеми. Дякую! Ця відповідь у поєднанні з відповіддю @ BoltClock дає хорошу інформацію про те, чому це рішення працює.
jamietelin


11

Не точно впевнений чому, але змінивши внутрішній CSS на

display:inline-block;

здається, працює;


3

Не відповідає на "чому" (має бути чимось з / краєм), але здається, що найпростішим / найбільш логічним способом зробити те, що ви намагаєтесь, було б просто додати padding-topдо зовнішнього діла :

http://jsfiddle.net/hpU5d/1/

Незначна примітка - не слід встановлювати діви, display:block;якщо у вашому коді є щось інше, що скаже, що воно не блокується.



2

Я думаю , настройка положення властивість #inner справ до відносно може також допомогти досягти ефекту. Але все одно я спробував оригінальний код, вставлений у Питання про IE9 та останню версію Google Chrome, і вони вже дають бажаний ефект без будь-яких модифікацій.


2

Використовувати padding-top:50pxдля зовнішньої діви. Щось на зразок цього:

#outer {
    width:500px; 
    height:200px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:table;}

Примітка: підкладка збільшить розмір вашої діви. У цьому випадку, якщо важливий розмір вашого діва, я маю на увазі, якщо він повинен мати конкретну висоту. зменшити висоту на 50 пікс .:

#outer {
    width:500px; 
    height:150px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:table;}

1

Ви пробували! Важливо, перш за все, це змусить усе:

margin:50px 50px 50px 50px !important;

-1

Просто для швидкого виправлення спробуйте вплести дочірні елементи в такий divелемент -

<div id="outer">
   <div class="divadjust" style="padding-top: 1px">
      <div id="inner">
         Hello world!
      </div>
   </div>
</div>

Межа innerдіва не згортається через прокладку 1pxміж проміжками outerта innerдівом. Тож логічно ви матимете 1pxдодатковий простір разом із існуючим запасом innerdiv.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.