Margin pada elemen anak memindahkan elemen induk

415

Saya memiliki div( orang tua ) yang berisi div( anak ) lain. Induk adalah elemen pertama bodytanpa gaya CSS tertentu. Ketika saya mengatur

.child
{
    margin-top: 10px;
}

Hasil akhirnya adalah bahwa bagian atas anak saya masih sejajar dengan orang tua. Alih-alih digeser anak untuk 10px ke bawah, orang tua saya bergerak 10px ke bawah.

Saya DOCTYPEdiatur ke XHTML Transitional.

Apa yang kulewatkan di sini?

sunting 1
Orang tua saya perlu memiliki dimensi yang ditentukan secara ketat karena memiliki latar belakang yang harus ditampilkan di bawahnya dari atas ke bawah (pixel perfect). Jadi pengaturan margin vertikal di atasnya adalah jalan .

sunting 2
Perilaku ini sama pada FF, IE dan juga CR.

Robert Koritnik
sumber
188
perilaku ini tidak masuk akal apa pun itu. Margin seharusnya tetap di dalam orang tua. Tidak memindahkan orang tua. Siapa yang menulis aturan ini.
Muhammad Umer
10
+2 untuk komentar terakhir. serius aturan ini menggangguku. "60% dari waktu kerjanya setiap kali" - itu margin.
Casey Dwayne
29
Saya sangat setuju dengan dua komentator terakhir. Ini gila. Yang menarik adalah menambahkan perbatasan 1px ke induk membuatnya berfungsi dengan baik, namun ini berarti Anda memiliki perbatasan ... jika ini adalah perilaku yang diharapkan maka ini konyol
erdomester
1
Ini juga dapat membantu Anda :) stackoverflow.com/questions/35337043/…
Bhojendra Rauniyar
5
Ini mengingatkan saya pada aturan ukuran kotak standar: " Kita perlu mengirim sebuah kotak. Kotak harus tidak lebih besar dari 100cm. Kita perlu 10cm bantalan di dalam kotak untuk memastikan konten kami tidak rusak selama pengiriman. Mari kita buat kotak 120cm! "Lelucon.
Nolonar

Jawaban:

492

Menemukan alternatif di elemen Anak dengan margin dalam DIVs Anda juga dapat menambahkan:

.parent { overflow: auto; }

atau:

.parent { overflow: hidden; }

Ini mencegah margin untuk runtuh . Perbatasan dan bantalan melakukan hal yang sama. Karenanya, Anda juga dapat menggunakan yang berikut untuk mencegah keruntuhan margin atas:

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

Perbarui dengan permintaan populer: Inti dari margin yang runtuh adalah menangani konten tekstual. Sebagai contoh:

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>

Karena browser menciutkan margin, teks akan muncul seperti yang Anda harapkan, dan <div>tag pembungkus tidak memengaruhi margin. Setiap elemen memastikan ada spasi di sekitarnya, tetapi spasi tidak akan digandakan. Margin <h2>dan <p>tidak akan menjumlahkan, tetapi geser satu sama lain (mereka runtuh). Hal yang sama terjadi pada elemen <p>dan <ul>.

Sayangnya, dengan desain modern, ide ini dapat menggigit Anda ketika Anda secara eksplisit menginginkan sebuah wadah. Ini disebut konteks pemformatan blok baru di CSS. The overflowatau marjin trik akan memberikan itu.

vdboor
sumber
41
Saya ingin tahu mengapa ini terjadi apa gunanya ini bagi siapa pun. Situasi apa yang dimaksud dengan 'fitur' ini.
Muhammad Umer
2
@MuhammadUmer, nah ini ada hubungannya dengan konten teks. Sebagai contoh, serangkaian <h2>, <p>, <ul>akan tidak mendapatkan celah aneh atau "double" margin dengan cara ini.
vdboor
7
Bisakah Anda memberi contoh. Katakanlah saya memiliki div sebagai latar belakang. Dengan h1, h2 dan p di dalamnya. Sekarang saya ingin memindahkan h1 sedikit sehingga tidak begitu dekat dengan tepi atas div latar belakang, namun tidak memperluas elemen h1 itu sendiri. Saya pikir akan menambah margin atas. Yang jelas. tetapi ketika saya melakukan itu, latar belakang yang mulia memutuskan untuk turun dengannya. Bagaimana ini adalah fitur. Bagaimana ini membantu dalam jarak antara h1, h2, dan p. Bantu saya melihat apa yang Anda katakan.
Muhammad Umer
1
Saya telah menambahkan contoh untuk Anda
vdboor
3
saya berharap untuk menambahkan lebih banyak margin. mengecilkan margin sejauh ini merupakan hal yang paling menjengkelkan dalam karier pengembangan saya. jika saya meletakkan 2 divs di sebelah satu sama lain dengan margin: 5px 10px;id berharap 2 divs 5 px dari atas dan 20px di antara mereka tidak 5 px dari atas dan 10px di antara mereka. jika saya ingin 10 px di antara mereka id telah ditentukan margin: 5px 5px;. sejujurnya saya berharap ada aturan root yang bisa saya tempatkan yang akan menghentikan semua margin runtuh. Saya benci bahwa saya harus menggandakan ukuran margin di atas kertas untuk membuat mereka benar-benar melakukan apa yang saya inginkan di layar. dan hal utama ini ... benar-benar bencana
JL Griffin
50

Ini adalah perilaku normal (setidaknya di antara implementasi browser). Margin tidak mempengaruhi posisi anak dalam kaitannya dengan induknya, kecuali jika induknya memiliki padding, dalam hal ini sebagian besar browser kemudian akan menambahkan margin anak ke padding orangtua.

Untuk mendapatkan perilaku yang Anda inginkan, Anda perlu:

.child {
    margin-top: 0;
}

.parent {
    padding-top: 10px;
}
Ben James
sumber
3
Menambahkan batas ke orang tua akan mempengaruhi margin anak juga, coba.parent {border: solid 1px;}
okw
1
Margin tidak menambah padding ... itu berlaku secara terpisah. Tetapi efek visualnya sama.
Brilliand
1
Bagaimana jika Anda ingin margin atas ...? Bukan solusi.
feeela
3
Seperti kata feeela - ini bukan solusi jika margin atas diperlukan. Jawaban vdboor lebih cocok.
Joey Morani
1
Ada banyak solusi, Anda hanya perlu cukup kreatif. Bersulang. :-)
Slavik Meltser
24

Meskipun semua jawaban memperbaiki masalah tetapi mereka datang dengan trade-off / penyesuaian / kompromi seperti

  • floats, Anda harus mengapung elemen
  • border-top, Ini mendorong induk setidaknya 1px ke bawah yang kemudian harus disesuaikan dengan memperkenalkan -1pxmargin ke elemen induk itu sendiri. Ini dapat membuat masalah ketika orang tua sudah memiliki margin-topunit relatif.
  • padding-top, efek yang sama seperti menggunakan border-top
  • overflow: hidden, Tidak dapat digunakan ketika orang tua harus menampilkan konten yang meluap, seperti menu drop down
  • overflow: auto, Memperkenalkan bilah gulir untuk elemen induk yang (secara sengaja) meluap konten (seperti bayangan atau segitiga ujung pahat)

Masalah ini dapat diatasi dengan menggunakan elemen pseudo CSS3 sebagai berikut

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

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

Ejaz
sumber
margin-top: -1pxtampaknya tidak perlu. Tapi saya suka ini.
Flimm
3
Sebenarnya, keduanya margin-top: -1pxdan height: 0tampaknya tidak perlu. Diuji di Chrome. Tapi solusi terbaik.
NinjaFart
Metode ini sebagian besar bekerja, tetapi tidak akan menghormati margin bawah untuk elemen terakhir dalam wadah. Ini bukan perbaikan yang sama untuk meluap: disembunyikan; sebagai contoh.
Michael Giovanni Pumo
1
@MichaelGiovanniPumo jawabannya dapat dimodifikasi agar berfungsi dengan margin bawah elemen terakhir dengan menggunakan.parent:after...
Ejaz
Ini pastinya jawaban yang benar saat ini. Bekerja dengan sempurna (letakkan di kedua setelah dan sebelum), saya berharap orang berani menggulir yang lain!
fgblomqvist
13

tambahkan gaya display:inline-blockke elemen anak

Атанас Димитров
sumber
9

elemen induk tidak boleh kosong setidaknya diletakkan &nbsp;sebelum elemen anak.

George SEDRA
sumber
2
ya, kadang-kadang hanya ini yang dapat membantu ... atau lebih baik meletakkan sesuatu seperti ini: <div style = 'width: 0; height: 0'> & nbsp; </div>
Pigalev Pavel
7

Inilah yang bekerja untuk saya

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

.child {
margin-top:260px;
}

http://jsfiddle.net/97fzwuxh/

erdomester
sumber
2

Saya menemukan itu, di dalam .css Anda> jika Anda mengatur properti tampilan elemen div ke inline-block itu memperbaiki masalah. dan margin akan berfungsi seperti yang diharapkan.

vincent thorpe
sumber
2

Solusi khusus CSS yang rapi

Gunakan kode berikut untuk menambahkan anak pertama tanpa konten ke div bergerak yang tidak disengaja:

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

Keuntungan dari metode ini adalah Anda tidak perlu mengubah CSS elemen apa pun yang ada, dan karena itu memiliki dampak minimal pada desain. Di sebelah ini, elemen yang ditambahkan adalah elemen pseudo, yang tidak ada di pohon DOM.

Dukungan untuk elemen semu tersebar luas: Firefox 3+, Safari 3+, Chrome 3+, Opera 10+, dan IE 8+. Ini akan berfungsi di browser modern apa pun (hati-hati dengan yang lebih baru ::before, yang tidak didukung di IE8).

Konteks

Jika anak pertama dari suatu elemen memiliki margin-top, orang tua akan menyesuaikan posisinya sebagai cara meruntuhkan margin yang berlebihan. Mengapa? Seperti itu saja.

Diberikan masalah berikut:

<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>

Anda dapat memperbaikinya dengan menambahkan anak dengan konten, seperti ruang sederhana. Tapi kita semua benci menambahkan ruang untuk apa yang hanya masalah desain. Karena itu, gunakan white-spaceproperti untuk konten palsu.

<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>

Di mana position: relative;memastikan posisi perbaikan yang benar. Dan white-space: pre;membuat Anda tidak perlu menambahkan konten apa pun - seperti ruang kosong - untuk memperbaikinya. Dan height: 0px;width: 0px;overflow: hidden;pastikan Anda tidak akan pernah melihat perbaikannya.

Anda mungkin perlu menambah line-height: 0px;atau max-height: 0px;memastikan ketinggian sebenarnya nol di browser IE kuno (saya tidak yakin). Dan opsional Anda bisa menambahkannya <!--dummy-->di browser IE lama, jika tidak berfungsi.

Singkatnya, Anda dapat melakukan semua ini hanya dengan CSS (yang menghilangkan kebutuhan untuk menambahkan anak yang sebenarnya ke pohon 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>
Yeti
sumber
Hanya gunakan solusi ini jika Anda putus asa, dan Anda tidak dapat mengatur CSS khusus untuk elemen yang ada - jika tidak gunakan solusi nyata: set overflow: hidden;untuk orang tua.
Yeti
2

Untuk mencegah "Div parent" gunakan margin "div child":
Pada parent gunakan css ini:

  • Mengapung
  • Lapisan
  • Berbatasan
  • Meluap
bingo
sumber
1

The marginunsur yang terkandung dalam .childruntuh.

<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>

Dalam contoh ini, pmenerima margindari gaya default browser. Default browser font-sizebiasanya 16px. Dengan memiliki margin-toplebih dari 16px pada #childAnda mulai memperhatikan posisi itu bergerak.

25 jam
sumber
1

Saya punya masalah ini juga tetapi lebih suka untuk mencegah hacks margin negatif, jadi saya meletakkan

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

di sekelilingnya semua yang memiliki bantalan bukan margin. Tentu saja ini berarti lebih banyak divitis tetapi mungkin cara paling bersih untuk menyelesaikannya dengan benar.

Zyl
sumber
1

Menariknya solusi favorit saya untuk masalah ini belum disebutkan di sini: menggunakan pelampung.

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;}

lihat di sini: http://codepen.io/anon/pen/Iphol

Perhatikan bahwa jika Anda memerlukan tinggi dinamis pada induk, ia juga harus mengambang, jadi cukup ganti height:100px;denganfloat:left;

schellmax
sumber
1

Solusi alternatif yang saya temukan sebelum saya tahu jawaban yang benar adalah menambahkan perbatasan transparan ke elemen induk.

Kotak Anda akan menggunakan piksel tambahan ...

.parent {
    border:1px solid transparent;
}
SandRock
sumber
0

Menggunakan topalih-alih margin-topadalah solusi lain yang mungkin, jika perlu.

lamplightdev
sumber