Поле дочірнього елемента переміщує батьківський елемент


414

У мене є div( батько ), який містить іншого div( дитина ). Батько - це перший елемент, в bodyякому немає конкретного стилю CSS. Коли я встановив

.child
{
    margin-top: 10px;
}

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

Моє DOCTYPEналаштовано на XHTML Transitional.

Що я тут пропускаю?

редагувати 1
Мій батько повинен мати строго визначені розміри, оскільки він має фон, який повинен відображатися під ним зверху вниз (ідеальний піксель). Тож встановлення вертикальних запасів на ньому - це не вихід .

редагувати 2
Така поведінка однакова як для FF, IE, так і для CR.


188
така поведінка не має сенсу, як це колись. Мардж, припустимо, залишається всередині батьків. Не рухати батьків. Хто пише ці правила.
Мухаммед Умер

10
+2 для останнього коментаря. серйозно це правило мене помиляє. "60% часу, коли це працює кожен раз" - це запаси.
Кейсі Дуейн

29
Я повністю згоден з двома останніми коментаторами. Це божевільно. Що цікаво, те, що додавання границі 1px до батьків змушує працювати правильно, однак це означає, що у вас є межа ... якщо така очікувана поведінка, то це смішно
erdomester

1
Це також може допомогти вам :) stackoverflow.com/questions/35337043 / ...
Bhojendra Rauniyar

5
Це нагадує мені за замовчуванням правило розміру коробки: " Нам потрібно відправити коробку. Коробка не повинна бути більше 100 см. Нам потрібно 10 см прокладки всередині коробки, щоб наш вміст не зламався під час доставки. Давайте зробимо коробка 120см! »Який жарт.
Нолонар

Відповіді:


492

Знайдено альтернативу в дочірніх елементах з полями в межах DIVs Ви також можете додати:

.parent { overflow: auto; }

або:

.parent { overflow: hidden; }

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

.parent {
    padding-top: 1px;
    margin-top: -1px;
}

Оновлення за популярним запитом: Вся суть поля, що згортається, - це обробка текстового вмісту. Наприклад:

h1, h2, p, ul {
  margin-top: 1em;
  margin-bottom: 1em;
}
<h1>Title!</h1>
<div class="text">
  <h2>Title!</h2>
  <p>Paragraph</p>
</div>
<div class="text">
  <h2>Title!</h2>
  <p>Paragraph</p>
  <ul>
    <li>list item</li>
  </ul>
</div>

Оскільки браузер згортає поля, текст відображатиметься так, як ви очікували, а <div>теги обгортки не впливають на поля. Кожен елемент гарантує, що він має відстань навколо нього, але інтервал не збільшиться вдвічі. Поля <h2>і <p>не збігатиметься, але ковзає одна до одної (вони згортаються). Те саме відбувається з елементом <p>і <ul>.

На жаль, при сучасних конструкціях ця ідея може вкусити вас, коли ви явно хочете контейнер. Це називається новим контекстом форматування блоку в CSS speak. overflowАбо запас трюк дасть вам це.


41
Я хочу знати, чому це відбувається, що це добре для когось. В якій ситуації мала бути ця «особливість».
Мухаммед Умер

2
@MuhammadUmer, це стосується текстового вмісту. Наприклад, серія <h2>, таким чином <p>, <ul>не отримає дивних прогалин або "подвійних" запасів.
vdboor

7
Чи можете ви навести якийсь приклад. Скажімо, у мене є фоновий документ. З h1, h2 і p в ньому. Тепер я хочу трохи перенести h1 вниз, щоб він не був наближеним до верхнього краю фонового поділу, але не розгортав сам елемент h1. Я думаю, додамо верхню маржу. Що очевидно. але коли я це роблю, славний фон вирішує рухатись донизу. Як це особливість. Як це допомагає в інтервалі між h1, h2 та p. Допоможіть мені зрозуміти, що ви говорите.
Мухаммед Умер

1
Я додав для вас приклад
vdboor

3
Я б очікував, що це додасть більше маржі. руйнування запасів - це найнеприємніша річ у моїй кар’єрі розвитку. якщо я покладу 2 діви один біля одного, margin: 5px 10px;ідентифікатор очікує 2 діви 5 px зверху і 20px між ними, не 5 px зверху та 10px між ними. якщо я хотів, щоб 10 пікс між ними вказали ідентифікатор margin: 5px 5px;. Я щиро бажаю, щоб було корінне правило, яке я міг би встановити, що зупинило б усі запаси. я ненавиджу, що мені доводиться вдвічі перевищувати розмір поля на папері, щоб змусити їх насправді робити те, що, до речі, хочу на екрані. і це головне ... яка катастрофа
Дж. Л. Гріффін

50

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

Щоб отримати потрібну поведінку, вам потрібно:

.child {
    margin-top: 0;
}

.parent {
    padding-top: 10px;
}

3
Додавання кордону до батьків також вплине на маржу дитини, спробуйте.parent {border: solid 1px;}
okw

1
Поле не додає до прокладки ... воно застосовується окремо. Але візуальний ефект той самий.
Brilliand

1
Що робити, якщо ви хочете максимальну маржу…? Насправді не рішення.
гонорар

3
Як сказала таксіла - це насправді не рішення, якщо потрібна максимальна маржа. Відповідь vdboor підходить краще.
Joey Morani

1
Є купа рішень, просто потрібно бути достатньо креативними. Ура. :-)
Славік Мельцер

23

Хоча всі відповіді вирішують це питання, але вони випливають із компромісами / коригуваннями / компромісами

  • floats, Ви повинні плавати елементами
  • border-top, Це відсуває батьківський принаймні на 1 піксель вниз, який потім слід відрегулювати, вводячи -1pxзапас для самого батьківського елемента. Це може створити проблеми, коли у батьків вже є margin-topвідносні одиниці.
  • padding-top, такий же ефект, як і використання border-top
  • overflow: hidden, Неможливо використовувати, коли батько повинен відображати переповнений вміст, як-от спадне меню
  • overflow: auto, Вводить смуги прокрутки для батьківського елемента, який (навмисно) переповнює вміст (наприклад, тіні або трикутник наконечника інструменту)

Вирішити проблему можна за допомогою псевдоелементів CSS3 наступним чином

.parent::before {
  clear: both;
  content: "";
  display: table;
  margin-top: -1px;
  height: 0;
}

https://jsfiddle.net/hLgbyax5/1/


margin-top: -1pxвидається зайвим. Але мені це подобається.
Flimm

3
Власне, і те, margin-top: -1pxі height: 0здається непотрібним. Тестували в Chrome. Але найкраще рішення.
NinjaFart

Цей метод здебільшого працює, але не дотримується нижнього поля останнього елемента в контейнері. Це не рівне виправлення для переповнення: приховано; наприклад.
Майкл Джованні Пумо

1
@MichaelGiovanniPumo відповідь можна змінити, щоб вона працювала з нижньою межею останнього елемента, використовуючи.parent:after...
Ejaz

Це, безумовно, правильна відповідь сьогодні. Працює бездоганно (надягайте це як після, так і раніше), сподіваюся, люди наважуються прокрутити повз інших!
fgblomqvist


9

батьківський елемент не повинен бути порожнім, принаймні ставити &nbsp;перед дочірнім елементом.


2
так, іноді тільки це може допомогти ... або краще поставити щось подібне: <div style = 'width: 0; height: 0'> & nbsp; </div>
Pigalev Pavel


2

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


2

Акуратне CSS-рішення

Використовуйте наступний код, щоб додати бездоганну первістку до ненавмисно рухомого діва:

.parent:before
{content: '';position: relative;height: 0px;width: 0px;overflow: hidden;white-space: pre;}

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

Підтримка псевдоелементів широко поширена: Firefox 3+, Safari 3+, Chrome 3+, Opera 10+ та IE 8+. Це буде працювати в будь-якому сучасному веб-переглядачі (будьте обережні з новішим ::before, який не підтримується в IE8).

Контекст

Якщо у першого дочірнього елемента елемента є a margin-top, батьків буде коригувати його положення як спосіб згортання надлишкової межі. Чому? Це просто так.

З огляду на таку проблему:

<style type="text/css">
div {position: relative;}
.parent {background-color: #ccc;}
.child {margin-top: 40px;}
</style>

<div class="parent"><!--This div moves 40px too-->
    <div class="child">Hello world!</div>
</div>

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

<style type="text/css">
div {position: relative;}
.parent {background-color: #ccc;}
.child {margin-top: 40px;}
.fix {position: relative;white-space: pre;height: 0px;width: 0px;overflow: hidden;}
</style>

<div class="parent"><!--This div won't move anymore-->
    <div class="fix"></div>
    <div class="child">Hello world!</div>
</div>

Там, де position: relative;забезпечується правильне розташування фіксації. Завдяки цьому white-space: pre;вам не потрібно додавати жодний вміст - наприклад, пробіл - до виправлення. І height: 0px;width: 0px;overflow: hidden;гарантує, що ви ніколи не побачите виправлення.

Вам може знадобитися додати line-height: 0px;або max-height: 0px;переконатися, що висота фактично дорівнює нулю в старовинних браузерах IE (я не впевнений). І необов’язково ви можете додати <!--dummy-->його до старих браузерів IE, якщо це не працює.

Коротше кажучи, ви можете зробити все це лише за допомогою CSS (що знімає необхідність додавати фактичне дочірнє дерево до дерева HTML DOM):

<style type="text/css">
div {position: relative;}
.parent {background-color: #ccc;}
.child {margin-top: 40px;}

.parent:before {content: '';position: relative;height: 0px;width: 0px;overflow: hidden;white-space: pre;}
</style>

<div class="parent"><!--This div won't move anymore-->
    <div class="child">Hello world!</div>
</div>

Використовуйте це рішення лише в тому випадку, коли ви відчайдушно і не можете встановити будь-який спеціальний CSS для існуючих елементів - інакше використовуйте реальне рішення: встановити overflow: hidden;для батьків.
Єті

2

Щоб запобігти "Div parent", використовуйте поле "Div child":
У батьків використовуйте ці css:

  • Поплавок
  • Прокладки
  • Кордон
  • Переповнення

1

marginЕлементів міститься всередині .childруйнуються.

<html>
<style type="text/css" media="screen">
    #parent {background:#dadada;}
    #child {background:red; margin-top:17px;}
</style>
<body>
<div id="parent">

    <p>&amp;</p>

    <div id="child">
        <p>&amp;</p>    
    </div>

</div>
</body>
</html>

У цьому прикладі pвідбувається отримання marginстилю браузера за замовчуванням. За замовчуванням для веб-переглядача font-sizeзазвичай 16 пікселів. Маючи margin-topбільше 16 пікс., #childВи починаєте помічати, що це переміщення позиції.


1

У мене була ця проблема теж, але я вважав за краще запобігти хакерству негативної маржі, тому я поставив

<div class="supercontainer"></div>

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


1

Цікаво, що моє улюблене рішення цієї проблеми поки не згадується: використання floats.

html:

<div class="parent">
    <div class="child"></div>
</div>

css:

.parent{width:100px; height:100px;}
.child{float:left; margin-top:20px; width:50px; height:50px;}

дивіться тут: http://codepen.io/anon/pen/Iphol

зауважте, що у випадку, якщо вам потрібна динамічна висота на батьківщині, вона також повинна плавати, тому просто замініть height:100px;наfloat:left;


1

Альтернативне рішення, яке я знайшов ще до того, як зрозумів правильну відповідь, було додати прозорий кордон до батьківського елемента.

У вашому полі будуть використані додаткові пікселі ...

.parent {
    border:1px solid transparent;
}

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