Bagaimana cara mengatur margin atau padding sebagai persentase tinggi wadah induk?

236

Saya telah memeras otak saya untuk menciptakan perataan vertikal di css menggunakan yang berikut ini

.base{
        background-color:green;
	    width:200px;
	    height:200px;
	    overflow:auto;
	    position:relative;
	}

    .vert-align{
		padding-top:50%;
		height:50%;
	}
<!-- and used the following div structure. -->

    <div class="base">
       <div class="vert-align">
    	   Content Here
       </div>
    </div>

Sementara ini tampaknya bekerja untuk kasus ini, saya terkejut bahwa ketika saya menambah atau mengurangi lebar div basis saya, perataan vertikal akan patah. Saya mengharapkan bahwa ketika saya mengatur properti padding-top, itu akan mengambil padding sebagai persentase dari ketinggian wadah induk, yang merupakan dasar dalam kasus kami, tetapi nilai di atas 50 persen dihitung sebagai persentase dari lebar. :(

Apakah ada cara untuk mengatur padding dan / atau margin sebagai persentase dari tinggi, tanpa menggunakan JavaScript?

Ryan
sumber

Jawaban:

223

Cara mengatasinya adalah bahwa ya, padding vertikal dan marjin yang relatif lebar, tetapi topdan bottom tidak.

Jadi cukup tempatkan div di dalam yang lain, dan di dalam div, gunakan sesuatu seperti top:50%(ingat positionhal-hal jika masih tidak berhasil)

Camilo Martin
sumber
3
topberfungsi bagus untuk mengubah ukuran berdasarkan tinggi browser / jendela. Bagaimana kalau punya div di bawah div itu? Bagaimana Anda bisa cleardiv ke-2 berada di bawah div yang digeser ke bawah oleh top:50%??
Federico
Belajar sth baru. Tidak tahu padding dan margin vertikal relatif terhadap lebar sebelumnya. Terima kasih.
shaosh
5
Juga dimungkinkan untuk menambahkan div 'spacer' dengan tinggi persentase yang ditetapkan. Tampaknya sedikit kotor tetapi berhasil. lihat jawaban ini .
WCByrne
4
Apa yang abadi @%! ^? Mengapa margin dan bantalan vertikal relatif terhadap lebar ? APA? Mengapa keputusan itu dibuat?
temporary_user_name
Jawaban Anda sangat tidak proporsional dipilih dibandingkan dengan jawaban alain di bawah ini, yang memberikan solusi umum, dan saya merasa sangat membantu dan hampir tidak melihatnya. top: 50%tidak terlalu berguna jika Anda perlu menyelaraskan konten dengan pusatnya sendiri.
okovko
35

Jawaban untuk pertanyaan yang sedikit berbeda: Anda bisa menggunakan vhunit untuk menempelkan elemen ke tengah viewport :

.centerme {
    margin-top: 50vh;
    background: red;
}

<div class="centerme">middle</div>
willoller
sumber
Mengapa jawaban ini tidak dinilai lebih tinggi? Apakah ada yang salah dengan menggunakan vh?
AlanH
3
Itu karena itu bukan jawaban yang disesuaikan dengan pertanyaan awal, itu adalah trik yang berguna yang hanya berfungsi dalam beberapa kasus terkait.
willoller
menggunakan vhhampir sama dengan persentase ... bahkan lebih buruk dalam beberapa kasus. Jawaban ini tidak relevan dengan pertanyaan
vsync
33

Berikut adalah dua opsi untuk meniru perilaku yang dibutuhkan. Bukan solusi umum, tetapi dapat membantu dalam beberapa kasus. Spasi vertikal di sini dihitung berdasarkan ukuran elemen luar, bukan induknya, tetapi ukuran ini sendiri dapat relatif terhadap induk dan dengan cara ini jarak akan relatif juga.

<div id="outer">
    <div id="inner">
        content
    </div>
</div>

Opsi pertama: gunakan elemen pseudo, di sini jarak vertikal dan horisontal relatif ke luar. Demo

#outer::before, #outer::after {
    display: block;
    content: "";
    height: 10%;
}
#inner {
    height: 80%;
    margin-left: 10%;
    margin-right: 10%;
}

Memindahkan jarak horizontal ke elemen luar membuatnya relatif terhadap induk dari bagian luar. Demo

#outer {
    padding-left: 10%;
    padding-right: 10%;
}

Opsi kedua: gunakan penentuan posisi absolut. Demo

#outer {
    position: relative;
}
#inner {
    position: absolute;
    left: 10%;
    right: 10%;
    top: 10%;
    bottom: 10%;
}
pengguna
sumber
10

Untuk membuat elemen anak diposisikan secara absolut dari elemen induknya, Anda perlu mengatur posisi relatif pada elemen induk DAN posisi absolut pada elemen turunan.

Kemudian pada elemen anak 'top' adalah relatif terhadap ketinggian induk. Jadi, Anda juga perlu 'menerjemahkan' anak ke atas 50% dari tinggi badannya sendiri.

.base{
    background-color: green;
    width: 200px;
    height: 200px;
    overflow: auto;
    position: relative;
}
    
.vert-align {
    position: absolute;
    top: 50%;
    transform: translate(0, -50%);
}
    <div class="base">
        <div class="vert-align">
            Content Here
        </div>
    </div>

Ada solusi lain menggunakan kotak fleksibel.

.base{
    background-color:green;
    width: 200px;
    height: 200px;
    overflow: auto;
    display: flex;
    align-items: center;
}
<div class="base">
    <div class="vert-align">
        Content Here
    </div>
</div>

Anda akan menemukan keuntungan / kerugian bagi keduanya.

Alain
sumber
1
Menggunakan translate adalah satu-satunya cara nyata untuk memindahkan suatu elemen secara vertikal relatif terhadap ukurannya sendiri.
Eran Goldin
Terima kasih untuk ini. Ini harus menjadi jawaban yang dipilih.
Wessam El Mahdy
6

Ini dapat dicapai dengan writing-modeproperti. Jika Anda mengatur elemen writing-modeke mode penulisan vertikal, sepertivertical-lr , nilai persentase turunannya untuk padding dan margin, di kedua dimensi, menjadi relatif terhadap tinggi daripada lebar.

Dari spec :

. . . persentase pada properti margin dan padding, yang selalu dihitung sehubungan dengan lebar blok yang mengandung dalam CSS2.1, dihitung sehubungan dengan ukuran sebaris dari blok yang berisi di CSS3.

Definisi ukuran sebaris :

Pengukuran dalam dimensi sebaris: mengacu pada lebar fisik (dimensi horizontal) dalam mode penulisan horizontal, dan ketinggian fisik (dimensi vertikal) dalam mode penulisan vertikal.

Contoh, dengan elemen yang dapat diubah ukurannya, di mana margin horizontal relatif terhadap lebar dan margin vertikal relatif terhadap tinggi.

.resize {
  width: 400px;
  height: 200px;
  resize: both;
  overflow: hidden;
}

.outer {
  height: 100%;
  background-color: red;
}

.middle {
  writing-mode: vertical-lr;
  margin: 0 10%;
  width: 80%;
  height: 100%;
  background-color: yellow;
}

.inner {
  writing-mode: horizontal-tb;
  margin: 10% 0;
  width: 100%;
  height: 80%;
  background-color: blue;
}
<div class="resize">
  <div class="outer">
    <div class="middle">
      <div class="inner"></div>
    </div>
  </div>
</div>

Menggunakan mode penulisan vertikal dapat sangat berguna dalam situasi di mana Anda ingin rasio aspek suatu elemen tetap konstan, tetapi ingin ukurannya untuk skala berkorelasi dengan tinggi dan bukannya lebar.

James T
sumber
Ini, IMO, akan menjadi solusi yang lebih elegan, tetapi (pada 2018-05-05), mode penulisan vertikal tidak didukung dengan baik . Semoga itu berubah segera.
zanerock
1
@zanerock Saya cukup yakin bahwa tabel compat MDN sudah usang. Sebagai contoh, dikatakan bahwa Safari membutuhkan -webkit-awalan, tetapi menurut caniuse itu tidak memerlukan awalan sejak Safari 11. Apakah Anda mencobanya dengan peramban yang tidak berfungsi?
James T
1
Tidak, saya harus mengakui bahwa saya hanya berasumsi itu bagus, bahkan otomatis.
zanerock
4

Cara lain untuk memusatkan teks satu baris adalah:

.parent{
  position: relative;
}

.child{
   position: absolute;
   top: 50%;
   line-height: 0;
}

atau hanya

.parent{
  overflow: hidden; /* if this ins't here the parent will adopt the 50% margin of the child */
}

.child{
   margin-top: 50%;
   line-height: 0;
}
rawiro
sumber
0

Bantalan 50% tidak akan memusatkan anak Anda, itu akan menempatkannya di bawah pusat. Saya pikir Anda benar-benar menginginkan padding-top 25%. Mungkin Anda hanya kehabisan ruang karena konten Anda semakin tinggi? Anda juga sudah mencoba mengatur margin-top bukan padding-top?

EDIT: Nevermind, kata situs w3schools

% Menentukan bantalan dalam persen dari lebar elemen yang mengandung

Jadi mungkin selalu menggunakan lebar? Saya tidak pernah memperhatikan.

Apa yang Anda lakukan dapat dilakukan menggunakan display: table though (setidaknya untuk browser modern). Tekniknya dijelaskan di sini .

SPIFF
sumber
1
Terima kasih Spliff. Saya mengerti bahwa 50% saya tidak akan memusatkan konten div. Saya sebenarnya hanya memiliki satu baris teks yang harus dipusatkan secara vertikal. Terima kasih banyak untuk tautannya!
Ryan
3
Jika hanya satu baris teks yang Anda anggap menggunakan besar sekali line-height, yaitu, membuat 200px garis-tinggi?
SpliFF
@Ryan untuk memusatkan teks secara vertikal, lihat stackoverflow.com/questions/8865458/…
pengguna
link anda rusak
quemeful
0

Ini adalah bug yang sangat menarik. (Menurut pendapat saya, ini adalah bug) Temuan bagus!

Mengenai cara mengaturnya, saya akan merekomendasikan jawaban Camilo Martin. Tapi untuk alasannya , aku ingin menjelaskan ini sedikit jika kalian tidak keberatan.


Dalam spesifikasi CSS yang saya temukan:


Persentase 'padding' : merujuk pada lebar blok yang mengandung

... yang aneh, tapi oke.

Jadi, dengan orangtua width: 210pxdan anak padding-top: 50%, saya mendapatkan nilai yang dihitung / dihitung padding-top: 96.5px- yang bukan yang diharapkan105px .

Itu karena di Windows (saya tidak yakin tentang OS lain), ukuran scrollbar umum adalah per default 17px × 100%(atau 100% × 17pxuntuk bilah horizontal). Itu 17pxdikurangi sebelum menghitung 50%, karenanya 50% of 193px = 96.5px.

WoodrowShigeru
sumber
Ada alasan untuk spek, dan ini menjelaskan lebih baik: hongkiat.com/blog/calculate-css-percentage-margins
manikanta