Pusatkan Gambar Oversized di Div

175

Saya telah mencoba memilah bagaimana memusatkan gambar yang terlalu besar dalam div menggunakan css saja.

Kami menggunakan tata letak yang cair, sehingga lebar wadah gambar bervariasi seperti lebar halaman (ketinggian div diperbaiki). Gambar duduk di dalam div, dengan nilai sebuah kotak bayangan inset sehingga muncul seolah-olah Anda melihat melalui halaman di gambar.

Gambar itu sendiri telah berukuran untuk mengisi div sekitarnya pada nilai seluas mungkin (desain memiliki max-widthnilai).

Sangat mudah dilakukan jika gambar lebih kecil dari div sekitarnya:

margin-left: auto;
margin-right: auto;
display: block; 

Tetapi ketika gambar lebih besar dari div itu hanya mulai di tepi kiri dan dari pusat ke kanan (kami menggunakan overflow: hidden).

Kami dapat menetapkan width=100%, tetapi browser melakukan pekerjaan yang buruk untuk mengubah ukuran gambar dan desain web berpusat pada citra berkualitas tinggi.

Adakah ide untuk memusatkan gambar sehingga overflow:hiddenmemotong kedua sisi secara merata?

Tom
sumber
2
Apakah Anda pernah memecahkan masalah ini @ Tom? Saya mengalami masalah yang sama saat ini. :)
ctrlplusb
Saya berasumsi bahwa lebar gambar Anda bervariasi.
otherDewi

Jawaban:

365

Coba sesuatu seperti ini. Ini harus memusatkan elemen besar di tengah secara vertikal dan horizontal sehubungan dengan induknya, tidak peduli ukurannya.

.parent {
    position: relative;
    overflow: hidden;
    //optionally set height and width, it will depend on the rest of the styling used
}

.child {
    position: absolute;
    top: -9999px;
    bottom: -9999px;
    left: -9999px;
    right: -9999px;
    margin: auto;

}
hyounis
sumber
4
Hebat: ini bekerja dengan elemen apa pun. bahkan dengan video html 5 ... terima kasih!
taseenb
3
Seperti yang saya pahami: ini berfungsi karena ia menciptakan elemen (semoga) lebih besar dari gambar (2 * 9999px x 2 * 9999px) dan memusatkan gambar di dalam elemen tersebut (margin: auto). Jadi selama gambar tidak melebihi 2 * 9999px itu harus berfungsi.
Michael Krupp
16
Mengapa tidak digunakan -100%untuk atas / kanan / bawah / kiri? Dengan itu wadah itu bisa memiliki lebar apa pun .
Simon
15
Ya saya juga pernah mengalami -100%masalah ini ^^. Btw: jika Anda menambahkan min-widthdan min-heightdari 100%Anda pada dasarnya mendapatkan background-size: cover;perilaku dengan tag gambar -> jsfiddle
Simon
3
@ HarrisonPowers Yah orang tua harus memiliki ketinggian tentunya, apakah itu tetap atau dinamis. Ini juga akan berfungsi jika beberapa konten lain mengisi div yang menyebabkannya memiliki ketinggian (seperti teks misalnya).
hyounis
162

Ini adalah Q lama, tetapi solusi modern tanpa flexbox atau posisi benar-benar berfungsi seperti ini.

margin-left: 50%;
transform: translateX(-50%);

Jadi mengapa ini berhasil?
Pada pandangan pertama tampaknya kita menggeser 50% ke kanan dan kemudian 50% ke kiri lagi. Itu akan menghasilkan nol shift, jadi apa?
Tetapi 50% tidak sama, karena konteks itu penting. Jika Anda menggunakan unit relatif, margin akan dihitung sebagai persentase dari lebar elemen induk , sedangkan transformasi akan menjadi 50% relatif terhadap elemen yang sama .

Kami memiliki situasi ini sebelum kami menambahkan CSS

       +-------------------------------------------+
       | Parent element P of E                     |
       |                                           |
       +-----------------------------------------------------------+
       | Element E                                                 |
       +-----------------------------------------------------------+
       |                                           |
       +-------------------------------------------+

Dengan gaya tambahan yang margin-left: 50%kami miliki

       +-------------------------------------------+
       | Parent element P of E                     |
       |                                           |
       |                     +-----------------------------------------------------------+
       |                     | Element E                                                 |
       |                     +-----------------------------------------------------------+
       |                     |                     |
       +---------------------|---------------------+
       |========= a ========>|

       a is 50% width of P

Dan transform: translateX(-50%)bergeser kembali ke kiri

       +-------------------------------------------+
       | Parent element P of E                     |
       |                                           |
+-----------------------------------------------------------+
| Element E                 |                               |
+-----------------------------------------------------------+
|<============ b ===========|                      |
       |                    |                      |
       +--------------------|----------------------+
       |========= a =======>|

       a is 50% width of P
       b is 50% width of E

Sayangnya ini hanya berfungsi untuk pemusatan horizontal karena perhitungan persentase margin selalu relatif terhadap lebar. Yaitu tidak hanya margin-leftdan margin-right, tetapi juga margin-topdanmargin-bottom dihitung sehubungan dengan lebar.

Kompatibilitas browser seharusnya tidak menjadi masalah: https://caniuse.com/#feat=transforms2d

Yunzen
sumber
Ini tidak berfungsi untuk penjajaran vertikal (ketika .inner memiliki tinggi yang lebih besar .outer)
cronfy
1
@cronfy No. secara vertikal tidak akan berfungsi, karena margin-top: 50%akan menjadi 50% dari lebar . bukan ketinggian yang diinginkan.
yunzen
2
itu adalah solusi yang paling elegan
Souhaieb Besbes
mencari solusi untuk sementara waktu, terbaik, paling sederhana; Cheers
lauWM
2
Ini adalah sihir penyihir murni. Terima kasih! Berfungsi sempurna di Safari dan Chrome (dengan tambahan -webkit-transform: translateX(-50%);ukuran yang baik)
Nick Schneble
22

Letakkan div besar di dalam div itu, tengah itu, dan tengah gambar di dalam div itu.

Ini berpusat secara horizontal:

HTML:

<div class="imageContainer">
  <div class="imageCenterer">
    <img src="http://placekitten.com/200/200" />
  </div>
</div>

CSS:

.imageContainer {
  width: 100px;
  height: 100px;
  overflow: hidden;
  position: relative;
}
.imageCenterer {
  width: 1000px;
  position: absolute;
  left: 50%;
  top: 0;
  margin-left: -500px;
}
.imageCenterer img {
  display: block;
  margin: 0 auto;
}

Demo: http://jsfiddle.net/Guffa/L9BnL/

Untuk memusatkannya secara vertikal juga, Anda dapat menggunakan yang sama untuk div bagian dalam, tetapi Anda akan membutuhkan ketinggian gambar untuk menempatkannya di dalamnya.

Guffa
sumber
Ini berakhir dengan tepi kiri gambar terpusat di dalam "imageContainer". Seperti yang saya komentari di atas, div penampung gambar kami adalah lebar cairan dan tinggi tetap.
Tom
1
@ Tom: Jika saya menghapus widthpengaturan pada wadah, itu akan menjadi lebar induk, dan gambar berada di tengah bahkan jika halaman lebih sempit daripada gambar, yaitu sebanyak tepi kiri dan tepi kanan akan disembunyikan : jsfiddle.net/Guffa/L9BnL/2
Guffa
Terima kasih atas inspirasinya. Saya menggunakan posisi: relatif untuk .imageCenter. Dengan cara ini saya tidak memerlukan posisi: relatif untuk wadah induk.
user3153298
Ada banyak trik pintar untuk pertanyaan ini dan mereka semua punya kelemahan. Beberapa bekerja "lebih baik" tetapi sama sekali tidak mudah dimengerti. Solusi ini sangat masuk akal, gambar dipusatkan secara normal di div yang lebih luas yang sedang dipangkas. Rasanya salah, tapi pasti berhasil tanpa melanggar hukum fisika web. Saya memilih opsi ini daripada beberapa trik lain yang sangat sulit untuk dipahami, meskipun rasanya sedikit kotor.
Radley Sustaire
9

Terlambat dalam permainan, tetapi saya menemukan metode ini sangat intuitif. https://codepen.io/adamchenwei/pen/BRNxJr

CSS

.imageContainer {
  border: 1px black solid;

  width: 450px;
  height: 200px;
  overflow: hidden;
}
.imageHolder {
  border: 1px red dotted;

  height: 100%;
  display:flex;
  align-items: center;
}
.imageItself {
  height: auto;
  width: 100%;
  align-self: center;

}

HTML

<div class="imageContainer">
  <div class="imageHolder">
    <img class="imageItself" src="http://www.fiorieconfetti.com/sites/default/files/styles/product_thumbnail__300x360_/public/fiore_viola%20-%202.jpg" />
  </div>
</div>
Ezeewei
sumber
3
Bagus! Itu bisa disederhanakan juga. Caranya dilakukan dengan display: flexpada wadah induk dan align-self: centerpada gambar. Berikut adalah versi yang dioptimalkan: codepen.io/anon/pen/dWKyey
caiosm1005
5

Jangan gunakan lebar atau tinggi tetap atau eksplisit untuk tag gambar. Alih-alih, buat kode:

      max-width:100%;
      max-height:100%;

mis: http://jsfiddle.net/xwrvxser/1/

leatherjacket4
sumber
1
Ini kemudian meninggalkan ruang di sekitar gambar yang saya percaya mereka coba hindari.
Eoin
3

Saya penggemar berat membuat gambar latar belakang div / node - maka Anda bisa menggunakan background-position: centeratribut untuk memusatkannya terlepas dari ukuran layar

Shain Lafazan
sumber
9
Ini bukan cara yang dapat diakses untuk menggunakan gambar. Ini mungkin berfungsi dengan baik untuk gambar dekoratif, tetapi gambar apa pun yang informatif membutuhkan teks alternatif.
user2532030
0

Lebar dan tinggi hanya sebagai contoh:

parentDiv{
    width: 100px;
    height: 100px;
    position:relative; 
}
innerDiv{
    width: 200px;
    height: 200px;
    position:absolute; 
    margin: auto;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
}

Ini harus bekerja untuk Anda jika bagian kiri dan atas div orang tua Anda bukan bagian paling atas dan kiri dari jendela layar Anda. Ini bekerja untuk saya.

Панайот Толев
sumber
Sepertinya tidak membuat perbedaan. Tidak yakin apakah itu ada hubungannya dengan fakta bahwa lebarnya adalah cairan, sementara tingginya ditetapkan pada apa yang akan menjadi div induk.
Tom
2
Teknik ini berfungsi jika gambar lebih kecil dari wadah.
otherDewi
0

Saya menemukan ini menjadi solusi yang lebih elegan, tanpa fleksibel:

.wrapper {
    overflow: hidden;
}
.wrapper img {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    /* height: 100%; */ /* optional */
}
Cezar D.
sumber
0

Membangun jawaban hebat @ yunzen:

Saya menduga banyak orang yang mencari topik ini mencoba menggunakan gambar besar sebagai gambar latar belakang "pahlawan", misalnya di beranda. Dalam hal ini, mereka sering ingin teks muncul di atas gambar dan menurunkannya pada perangkat seluler.

Berikut ini adalah CSS yang sempurna untuk gambar latar belakang tersebut (gunakan pada <img>tag):

/* Set left edge of inner element to 50% of the parent element */
margin-left: 50%;

/* Move to the left by 50% of own width */
transform: translateX(-50%);

/* Scale image...(101% - instead of 100% - avoids possible 1px white border on left of image due to rounding error */
width: 101%;

/* ...but don't scale it too small on mobile devices - adjust this as needed */
min-width: 1086px;

/* allow content below image to appear on top of image */
position: absolute;
z-index: -1;

/* OPTIONAL - try with/without based on your needs */
top: 0;

/* OPTIONAL - use if your outer element containing the img has "text-align: center" */
left: 0;
Dave Koo
sumber
-1

Salah satu opsi yang dapat Anda gunakan adalah object-fit: coverberperilaku seperti background-size: cover. Lebih lanjut tentang objek-fit .

abaikan semua JS di bawah ini, itu hanya untuk demo.

Kuncinya di sini adalah bahwa Anda perlu mengatur gambar di dalam pembungkus dan memberikannya properti berikut.

.wrapper img {
  height: 100%;
  width: 100%;
  object-fit: cover;
}

Saya telah membuat demo di bawah ini di mana Anda mengubah tinggi / lebar pembungkus dan melihat bermain. Gambar akan selalu terpusat secara vertikal dan horizontal. Ini akan mengambil 100% dari lebar dan tinggi induknya, dan tidak akan diregangkan / tergencet. Ini berarti bahwa rasio aspek gambar dipertahankan. Perubahan diterapkan dengan cara memperbesar / memperkecil.

Satu-satunya downside object-fitadalah bahwa itu tidak berfungsi pada IE11.

// for demo only
const wrapper = document.querySelector('.wrapper');
const button = document.querySelector('button');
const widthInput = document.querySelector('.width-input');
const heightInput = document.querySelector('.height-input');


const resizeWrapper = () => {
  wrapper.style.width = widthInput.value + "px";
  wrapper.style.height = heightInput.value + "px";
}

button.addEventListener("click", resizeWrapper);
.wrapper {
  overflow: hidden;
  max-width: 100%;
  margin-bottom: 2em;
  border: 1px solid red;
}

.wrapper img {
  display: block;
  height: 100%;
  width: 100%;
  object-fit: cover;
}
<div class="wrapper">
  <img src="https://i.imgur.com/DrzMS8i.png">
</div>


<!-- demo only -->
<lable for="width">
  Width: <input name="width" class='width-input'>
</lable>
<lable for="height">
  height: <input name="height" class='height-input'>
</lable>
<button>change size!</button>

volt
sumber