Mengapa gaya margin-top CSS ini tidak berfungsi?

321

Saya mencoba menambahkan nilai margin pada div di dalam div lain. Semua berfungsi dengan baik kecuali nilai tertinggi, tampaknya diabaikan. Tapi kenapa?

Apa yang saya harapkan:
Apa yang saya harapkan dengan margin: 50px 50px 50px 50px;

Apa yang saya dapatkan:
Yang saya dapatkan dengan margin: 50px 50px 50px 50px;

Kode:

#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 tidak memiliki penjelasan mengapa margin berperilaku seperti ini.

jamietelin
sumber
4
Apakah Anda mencoba melayang di bagian dalam?
Ayam jantan
6
hum .. Dengan float:left;ini berfungsi ... tapi mengapa ini diperlukan. Saya tidak ingin itu melayang. Dan mengapa margin untuk kiri / kanan berfungsi?
jamietelin
44
Selamat datang di dunia menyenangkan dari algoritma runtuhnya margin CSS!
GordonM
10
W3Schools vs W3CDocs ... Saya pikir kami memiliki pemenang. : D
enderskill
15
jsFiddle darinya, untuk menyelamatkan pria berikutnya 25 detik jsfiddle.net/kLeu9
CodyBugstein

Jawaban:

453

Anda sebenarnya melihat margin atas #innerelemen runtuh ke tepi atas #outerelemen, hanya menyisakan #outermargin yang utuh (meskipun tidak ditampilkan dalam gambar Anda). Tepi atas kedua kotak rata terhadap satu sama lain karena marginnya sama.

Berikut adalah poin yang relevan dari spesifikasi W3C:

8.3.1 Margin yang runtuh

Dalam CSS, margin yang berdekatan dari dua kotak atau lebih (yang mungkin atau mungkin bukan saudara kandung) dapat bergabung untuk membentuk margin tunggal. Margin yang menggabungkan cara ini dikatakan runtuh , dan margin gabungan yang dihasilkan disebut collapsed margin .

Berdampingan dengan runtuhnya margin vertikal [...]

Dua margin berdampingan jika dan hanya jika:

  • keduanya termasuk dalam kotak level blok in-flow yang berpartisipasi dalam konteks format blok yang sama
  • tidak ada kotak garis, tidak ada izin, tidak ada bantalan dan tidak ada perbatasan yang memisahkan mereka
  • keduanya milik tepi kotak yang berdekatan secara vertikal, yaitu membentuk salah satu dari pasangan berikut:
    • margin atas dari kotak dan margin atas dari anak in-flow pertamanya

Anda dapat melakukan salah satu dari yang berikut ini untuk mencegah margin dari runtuh:

Alasan opsi di atas mencegah margin dari runtuh adalah karena:

  • Margin antara kotak mengambang dan kotak lainnya tidak runtuh (bahkan antara float dan anak-anak in-flow-nya).
  • Margin elemen yang membentuk konteks pemformatan blok baru (seperti mengapung dan elemen dengan 'luapan' selain 'terlihat') tidak runtuh dengan anak-anak mereka yang mengalir.
  • Margin kotak inline-blok tidak runtuh (bahkan dengan anak-anak mereka yang sedang mengalir).

Margin kiri dan kanan berperilaku seperti yang Anda harapkan karena:

Margin horisontal tidak pernah runtuh.

BoltClock
sumber
2
Jawaban ini mengguncang! Hanya sesuatu untuk ditambahkan. Kutipan Anda tentang w3c mengatakannya, tetapi saya baru sadar sekarang. Jadi hanya untuk memperjelas bagi orang lain, Anda juga dapat memberi #outer perbatasan.
driechel
Tautan di Floating tampaknya rusak.
EP
@episanty: Itulah yang terjadi ketika Anda menautkan ke komentar. Tidak terhubung.
BoltClock
Saya tahu - hanya ingin memberi tahu Anda. Karena Anda diaktifkan --- saya pikir Anda mungkin ingin menghidupkan kembali komentar - atau mengubah posting Anda sesuai. Ngomong-ngomong, jawaban yang bagus.
EP
92

Coba gunakan display: inline-block;pada inner div.

#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;
}
enderskill
sumber
6
Jawaban yang bagus. Akan lebih baik jika dijelaskan mengapa perubahan ini memperbaiki masalah.
JohnFx
1
Ok, itu aneh! Mengapa itu berhasil? Apa penjelasan logis mengapa itu tidak berhasil seperti yang diharapkan. Margin kiri / kanan bekerja tanpa display:inline-block;. Juga diatur kembali ketika menggunakan display:inline-block;adalah bahwa Anda kehilangan lebar 100% pada div.
jamietelin
3
beralih ke blok inline memaksa browser untuk mengevaluasi kembali ukuran div setelah ditempatkan dan aturan lain diterapkan.
Ayam jantan
Mencobanya untuk masalah saya, membuat efek tangga.
Jonny
1
display:inline-blockbekerja untukku. Terima kasih banyak.
starkeen
24

Apa yang @BoltClock sebutkan cukup solid. Dan Di sini saya hanya ingin menambahkan beberapa solusi untuk masalah ini. periksa margin w3c_collapsing ini . Bagian hijau adalah pemikiran potensial bagaimana masalah ini dapat diselesaikan.

Solusi 1

Margin antara kotak mengambang dan kotak lainnya tidak runtuh (bahkan antara float dan anak-anak in-flow-nya).

itu berarti saya dapat menambahkan float:leftke salah satu #outeratau #inner demo1 .

juga pemberitahuan yang floatakan membatalkan automargin.

Solusi 2

Margin elemen yang membentuk konteks pemformatan blok baru (seperti mengapung dan elemen dengan 'luapan' selain 'terlihat') tidak runtuh dengan anak-anak mereka yang mengalir.

selain visible, mari dimasukkan overflow: hiddenke dalam #outer. Dan cara ini tampaknya cukup sederhana dan layak. Saya suka itu.

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

Solusi 3

Margin kotak yang benar-benar diposisikan tidak runtuh (bahkan dengan anak-anak mereka yang sedang mengalir).

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

atau

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

dua metode ini akan mematahkan aliran normal div

Solusi 4

Margin kotak inline-blok tidak runtuh (bahkan dengan anak-anak mereka yang sedang mengalir).

sama dengan @enderskill

Solusi 5

Margin bawah elemen level blok in-flow selalu runtuh dengan margin teratas dari saudara level blok in-flow berikutnya, kecuali jika saudara tersebut memiliki izin.

Ini tidak banyak berhubungan dengan pertanyaan karena itu adalah jatuhnya margin antara saudara kandung. itu umumnya berarti jika kotak atas memiliki margin-bottom: 30pxdan kotak saudara margin-top: 10px. Margin total di antara mereka 30pxbukan 40px.

Solusi 6

Margin atas elemen blok in-flow runtuh dengan margin top anak tingkat blok in-flow pertama jika elemen tidak memiliki batas atas, tidak ada bantalan atas, dan anak tidak memiliki izin.

Ini sangat menarik dan saya bisa menambahkan satu garis batas atas

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

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

}

Dan juga <div>adalah blok-level secara default, jadi Anda tidak perlu mendeklarasikannya dengan sengaja. Maaf karena tidak dapat memposting lebih dari 2 tautan dan gambar karena reputasi pemula saya. Setidaknya Anda tahu dari mana masalahnya berasal saat Anda melihat sesuatu yang serupa.

Qiang
sumber
14

Tidak yakin mengapa apa yang Anda miliki tidak berfungsi, tetapi Anda dapat menambahkan

overflow: auto;

ke div luar.

Brandon
sumber
Banyak solusi berbeda untuk masalah ini. Terima kasih! Jawaban ini dikombinasikan dengan jawaban @ BoltClock memberikan informasi yang baik tentang mengapa solusi ini berhasil.
jamietelin
12

Jika Anda menambahkan bantalan apa pun #outer, itu berfungsi.

Demo

#outer {
    width:500px; 
    height:200px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:block;
    padding-top:1px;
}
rak buku
sumber
11

Tidak begitu yakin mengapa, tetapi mengubah CSS bagian dalam menjadi

display:inline-block;

tampaknya berhasil;

Harriyott
sumber
3

Tidak menjawab "mengapa" (harus berupa sesuatu dengan margin yang runtuh), tetapi sepertinya cara termudah / paling logis untuk melakukan apa yang Anda coba lakukan adalah dengan hanya menambah padding-topdiv luar :

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

Catatan kecil - seharusnya tidak perlu mengatur div display:block;kecuali jika ada sesuatu yang lain dalam kode Anda mengatakan itu tidak boleh diblokir.

Dave
sumber
3

coba ini:

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

http://jsfiddle.net/7AXTf/

Semoga berhasil

Mustafa M Jalal
sumber
2

Saya kira pengaturan properti posisi dari div internal ke relatif juga dapat membantu mencapai efek. Tapi bagaimanapun saya mencoba kode asli yang disisipkan di Pertanyaan pada IE9 dan Google Chrome terbaru dan mereka sudah memberikan efek yang diinginkan tanpa modifikasi.

viditkothari
sumber
2

Gunakan padding-top:50pxuntuk div luar. Sesuatu seperti ini:

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

Catatan: bantalan akan menambah ukuran div Anda. Dalam hal ini jika ukuran div Anda penting, maksud saya jika itu harus memiliki ketinggian tertentu. kurangi ketinggian hingga 50px .:

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

Sudahkah Anda mencoba! Penting sebelumnya, itu akan memaksa segalanya:

margin:50px 50px 50px 50px !important;
atgr24869
sumber
-1

Hanya untuk perbaikan cepat, cobalah membungkus elemen anak Anda menjadi divelemen seperti ini -

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

Margin of innerdiv tidak akan runtuh karena padding 1pxdi-antara outerdan innerdiv. Jadi secara logis Anda akan memiliki 1pxruang tambahan bersama dengan margin innerdiv yang ada.

Mithilesh Tipkari
sumber