Büyük Resmi Div'de Ortala


175

Ben sadece css kullanarak bir div içinde büyük boy bir görüntüyü merkezlemek için sıralamak için çalışıyorum.

Sıvı bir düzen kullanıyoruz, bu nedenle görüntü kaplarının genişliği sayfa genişliğine göre değişir (div yüksekliği sabittir). Görüntü bir div içinde yer alır ve görüntüye sayfada bakıyormuş gibi görünmesi için bir iç metin kutusu gölgesine değer verir.

Görüntünün kendisi, çevredeki div'i mümkün olan en geniş değerinde dolduracak şekilde boyutlandırılmıştır (tasarımın bir max-widthdeğeri vardır).

Görüntü çevredeki div'den daha küçükse yapmak oldukça kolaydır:

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

Ancak görüntü div'den daha büyük olduğunda, sol kenardan başlar ve merkezden sağa doğru (kullanıyoruz overflow: hidden).

Bir atayabiliriz width=100%, ancak tarayıcılar görüntüleri ve web tasarım merkezlerini yüksek kaliteli görüntüler etrafında yeniden boyutlandırmak için berbat bir iş çıkarır.

Görüntüyü ortalayarak ilgili overflow:hiddenher iki kenarı eşit şekilde kesecek herhangi bir fikir var mı?


2
@Tom bu sorunu hiç çözdünüz mü? Şu anda aynı sorunla karşılaşıyorum. :)
ctrlplusb

Görüntü genişliklerinizin farklı olduğunu varsayıyorum.
otherDewi

Yanıtlar:


366

Böyle bir şey deneyin. Bu, her iki boyutundan bağımsız olarak, ebeveyne göre büyük bir öğeyi ortada dikey ve yatay olarak ortalamalıdır.

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

}

4
harika: bu herhangi bir öğeyle çalışır. html 5 video ile bile ... teşekkürler!
taseenb

3
Bunu anladığım gibi çalışır: çünkü görüntüden (2 * 9999 piksel x 2 * 9999 piksel) daha büyük bir öğe oluşturur (umarım) ve bu öğenin içinde görüntüyü ortalar (kenar boşluğu: otomatik). Görüntü 2 * 9999 pikseli aşmadığı sürece çalışması gerekir.
Michael Krupp

16
Neden -100%üst / sağ / alt / sol için kullanmıyorsunuz ? Bununla konteynerin tam anlamıyla herhangi bir genişliği olabilir.
Simon

15
Evet ben de -100%sorunu yaşadım ^^. Btw: eklersen min-widthve min-heightiçinde 100%size temelde olsun background-size: cover;-> resim etiketleriyle davranışı jsfiddle
Simon

3
@HarrisonPowers Ebeveynin sabit ya da dinamik olsun, elbette bir yüksekliği olması gerekir. Başka bir içerik div değerini dolduruyorsa da çalışacaktır (örneğin metin gibi).
hyounis

162

Bu eski bir Q, ancak flexbox veya mutlak pozisyonu olmayan modern bir çözüm böyle çalışır.

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

Peki neden çalışıyor?
İlk bakışta% 50 sağa, sonra% 50 tekrar sola kaydığımız anlaşılıyor. Bu sıfır kaymaya neden olur, ne olacak?
Ancak% 50 aynı değildir, çünkü bağlam önemlidir. Eğer göreli birimlerini kullanan ise, bir kenar bölgesinin genişliğinin yüzdesi olarak hesaplanır üst % 50 bağlı olacaktır dönüşümü ise, elemanın aynı öğeye .

CSS eklemeden önce bu durum var

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

İlave tarzı ile margin-left: 50%sahip olduğumuz

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

       a is 50% width of P

Ve transform: translateX(-50%)sola doğru kayıyor

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

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

Maalesef bu sadece yatay merkezleme için işe yarar çünkü marjin yüzdesi hesaplaması her zaman genişliğe göredir. Yani sadece margin-leftve margin-rightaynı zamanda margin-topvemargin-bottom genişliği ile ilgili olarak hesaplanır.

Tarayıcı uyumluluğu sorun olmamalı: https://caniuse.com/#feat=transforms2d


Dikey hizalama için çalışmıyor (.inner büyük yüksekliğe sahip olduğunda o omuza Dış)
cronfy

1
@cronfy No. dikey olarak çalışmaz, çünkü genişliğinmargin-top: 50% % 50'si olacaktır . yüksekliği istediğiniz gibi değil.
yunzen

2
bu en şık çözüm
Souhaieb Besbes

bir süre bir çözüm aramak, en iyi, en basit çözüm; Şerefe
lauWM

2
Bu saf sihirbaz büyüsü. Teşekkür ederim! Safari ve Chrome'da mükemmel bir şekilde çalışır ( -webkit-transform: translateX(-50%);iyi bir önlem için eklenmiştir )
Nick Schneble

22

Div'ın içine büyük bir div koyun, bunu ortalayın ve görüntüyü o divın içine ortalayın.

Bu yatay olarak ortalar:

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/

Dikey olarak ortalamak için aynısını iç div için de kullanabilirsiniz, ancak görüntünün kesinlikle içine yerleştirmek için yüksekliğe ihtiyacınız olacaktır.


Bu, görüntünün sol kenarı "imageContainer" içinde ortalanmış olarak sona erdi. Yukarıda yorumladığım gibi, görüntü kabımız div sıvı yüksekliği ve sabit yüksekliktir.
Tom

1
@Tom: widthKapsayıcıdaki ayarı kaldırırsam, üst öğenin genişliği olur ve sayfa görüntüden daha dar olsa bile, yani sağ kenarın gizleneceği kadar sol kenarın görüntüsü ortalanır : jsfiddle.net/Guffa/L9BnL/2
Guffa

İlham için teşekkürler. .İmageCenter için position: relative kullanıyorum. Bu şekilde ana konteynere göre pozisyona ihtiyacım yok.
user3153298

Bu soru için birçok akıllı hile var ve hepsinin dezavantajları var. Bazıları "daha iyi" çalışır, ancak anlaşılması kolay değildir. Bu çözüm mükemmel bir anlam ifade ediyor, görüntü kırpılan daha geniş bir div içinde normal olarak ortalanıyor. Yanlış hissettiriyor, ancak kesinlikle web-fizik yasalarını çiğnemeden çalışıyor. Bu seçeneği, biraz kirli hissetse bile, anlaşılması zor diğer birkaç hileye göre seçtim.
Radley Sustaire

9

Oyunun sonlarına doğru, ama bu yöntemin son derece sezgisel olduğunu gördüm. 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>

3
Güzel! Ayrıca basitleştirilebilir. Hile display: flexüst kapta ve align-self: centergörüntüde yapılır. İşte optimize edilmiş bir versiyon: codepen.io/anon/pen/dWKyey
caiosm1005

5

Resim etiketine sabit veya açık bir genişlik veya yükseklik kullanmayın. Bunun yerine kodlayın:

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

ör .: http://jsfiddle.net/xwrvxser/1/


1
Bu daha sonra kaçınmaya çalıştıklarına inandığım görüntünün etrafında boşluk bırakıyor.
Eoin

3

Ben bir div / düğüm arka plan bir görüntü yapmak büyük bir hayranıyım - o zaman sadece background-position: centerekran boyutu ne olursa olsun ortalamak için özniteliği kullanabilirsiniz


9
Bu, görüntüleri kullanmanın erişilebilir bir yolu değildir. Dekoratif görüntüler için iyi çalışabilir, ancak bilgilendirici herhangi bir görüntü farklı metne ihtiyaç duyar.
user2532030

0

Genişlik ve yükseklik sadece örneğin:

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

Ana div öğenizin sol ve üst kısmı, ekranınızın penceresinin en üstünde ve solunda değilse sizin için çalışması gerekir. Benim için çalışıyor.


Bir fark yaratmadı. Yükseklik ana div ne olacağına sabitlenirken, genişliğin akışkan olması nedeniyle bir şey olup olmadığından emin değilim.
Tom

2
Görüntü kaptan küçükse bu teknik işe yarar.
otherDewi

0

Bunu esnek olmayan, daha zarif bir çözüm olarak buldum:

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

0

@ Yunzen'in büyük cevabı üzerine inşa etmek:

Bu konuyu arayan birçok kişinin büyük bir resmi "kahraman" arka plan resmi olarak, örneğin bir ana sayfada kullanmaya çalıştığını tahmin ediyorum. Bu durumda, genellikle resmin üzerinde metin görünmesini ve mobil cihazlarda iyi ölçeklendirilmesini isterler.

İşte böyle bir arka plan görüntüsü için mükemmel CSS ( <img>etikette kullanın ):

/* 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;

-1

Kullanabileceğiniz bir seçenek, object-fit: coverbiraz davranmasıdır background-size: cover. Nesne sığdırma hakkında daha fazla bilgi .

Aşağıdaki tüm JS'yi yoksay, bu sadece demo için.

Buradaki anahtar, görüntüyü bir sargı içine yerleştirmeniz ve aşağıdaki özellikleri vermeniz gerektiğidir.

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

Aşağıda, ambalajın yüksekliğini / genişliğini değiştirdiğiniz ve oyunda gördüğünüz bir demo oluşturdum. Görüntü her zaman dikey ve yatay olarak ortalanır. Ana genişliğinin ve yüksekliğinin% 100'ünü alacak ve gerilmeyecek / ezilmeyecektir. Bu, görüntünün en boy oranının korunduğu anlamına gelir. Değişiklikler bunun yerine yakınlaştırılarak / uzaklaştırılarak uygulanır.

Tek dezavantajı object-fittam o işi yapmaz IE11 üzerinde.

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.