Wyrównaj obraz w pionie w elemencie div z elastyczną wysokością

135

Mam następujący kod, który konfiguruje kontener, którego wysokość zmienia się wraz z szerokością, gdy przeglądarka jest zmieniana (aby zachować kwadratowy współczynnik proporcji).

HTML

<div class="responsive-container">
    <div class="dummy"></div>
    <div class="img-container">
        <IMG HERE>
    </div>
</div>

CSS

.responsive-container {
    position: relative;
    width: 100%;
    border: 1px solid black;
}

.dummy {
    padding-top: 100%; /* forces 1:1 aspect ratio */
}

.img-container {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}

Jak mogę wyrównać w pionie IMG wewnątrz kontenera? Wszystkie moje obrazy mają zmienną wysokość, a kontener nie może mieć stałej wysokości / wysokości linii, ponieważ jest responsywny ... Proszę o pomoc!

user1794295
źródło
1
Oto proste rozwiązanie typu flexbox: stackoverflow.com/a/31977476/3597276
Michael Benjamin

Odpowiedzi:

381

Oto technika wyrównywania elementów w wierszu wewnątrz elementu nadrzędnego , w poziomie i w pionie w tym samym czasie:

Wyrównanie w pionie

1) W tym podejściu tworzymy inline-block(pseudo) element jako pierwsze (lub ostatnie) dziecko rodzica i ustawiamy jego heightwłaściwość na tak, 100%aby przyjmowała całą wysokość jego rodzica .

2) Ponadto dodawanie vertical-align: middlezachowuje elementy inline (-block) na środku przestrzeni między wierszami. Tak więc dodajemy tę deklarację CSS do pierwszego dziecka i naszego elementu ( obrazu ) zarówno.

3) Wreszcie, aby usunąć znak odstępu między elementami inline (-block) , możemy ustawić rozmiar czcionki rodzica na zero o font-size: 0;.

Uwaga: W dalszej części użyłem techniki zastępowania obrazu Nicolasa Gallaghera .

Jakie są korzyści?

  • Kontener ( element nadrzędny ) może mieć wymiary dynamiczne.
  • Nie ma potrzeby jawnego określania wymiarów elementu obrazu.

  • Możemy łatwo zastosować to podejście do wyrównania <div>elementu również w pionie ; które mogą mieć dynamiczną zawartość (wysokość i / lub szerokość). Pamiętaj jednak, że musisz ponownie ustawić font-sizewłaściwość, divaby wyświetlić tekst wewnętrzny. Demo online .

<div class="container">
    <div id="element"> ... </div>
</div>
.container {
    height: 300px;
    text-align: center;  /* align the inline(-block) elements horizontally */
    font: 0/0 a;         /* remove the gap between inline(-block) elements */
}

.container:before {    /* create a full-height inline block pseudo=element */
    content: ' ';
    display: inline-block;
    vertical-align: middle;  /* vertical alignment of the inline element */
    height: 100%;
}

#element {
    display: inline-block;
    vertical-align: middle;  /* vertical alignment of the inline element */
    font: 16px/1 Arial sans-serif;        /* <-- reset the font property */
}

Wyjście

Wyrównaj w pionie element w jego kontenerze

Responsywny kontener

Ta sekcja nie odpowie na pytanie, ponieważ OP wie już, jak utworzyć responsywny kontener. Jednak wyjaśnię, jak to działa.

Aby wysokość elementu kontenera zmieniała się wraz z jego szerokością (z zachowaniem proporcji), możemy użyć wartości procentowej dla góry / dołupadding właściwości .

Wartość procentowa w górnej / dolnej wyściółki lub marginesie jest w stosunku do szerokości, zawierającego blok.

Na przykład:

.responsive-container {
  width: 60%;

  padding-top: 60%;    /* 1:1 Height is the same as the width */
  padding-top: 100%;   /* width:height = 60:100 or 3:5        */
  padding-top: 45%;    /* = 60% * 3/4 , width:height =  4:3   */
  padding-top: 33.75%; /* = 60% * 9/16, width:height = 16:9   */
}

Oto demo online . Skomentuj linie od dołu i zmień rozmiar panelu, aby zobaczyć efekt.

Możemy również zastosować tę paddingwłaściwość do fikcyjnego elementu potomnego lub :before/ :afterpseudoelementu, aby osiągnąć ten sam wynik. Ale uwaga , że w tym przypadku wartość procentowa na paddingto w stosunku do szerokości od .responsive-containersiebie.

<div class="responsive-container">
  <div class="dummy"></div>
</div>
.responsive-container { width: 60%; }

.responsive-container .dummy {
  padding-top: 100%;    /*  1:1 square */
  padding-top: 75%;     /*  w:h =  4:3 */
  padding-top: 56.25%;  /*  w:h = 16:9 */
}

Demo nr 1 .
Demo nr 2 (przy użyciu :afterpseudoelementu)

Dodawanie treści

Korzystanie z padding-topwłaściwości powoduje powstanie ogromnej przestrzeni na górze lub na dole treści, wewnątrz kontenera .

W celu ustalenia, że mamy owinąć Zawartość elementu owijającego, usunięcia tego elementu z dokumentu normalnym za pomocą pozycjonowania absolutnego , a na końcu rozszerzenie osłony (BU użyciu top, right, bottomi leftwłaściwości), aby wypełnić całe miejsce jego rodzica pojemnik .

No to ruszamy:

.responsive-container {
  width: 60%;
  position: relative;
}

.responsive-container .wrapper {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
}

Oto demo online .


Wszyscy razem

<div class="responsive-container">
  <div class="dummy"></div>

  <div class="img-container">
    <img src="http://placehold.it/150x150" alt="">
  </div>
</div>
.img-container {
  text-align:center; /* Align center inline elements */
  font: 0/0 a;       /* Hide the characters like spaces */
}

.img-container:before {
  content: ' ';
  display: inline-block;
  vertical-align: middle;
  height: 100%;
}

.img-container img {
  vertical-align: middle;
  display: inline-block;
}

Oto DEMO PRACY .

Oczywiście można uniknąć używania ::beforepseudoelementu w celu zapewnienia zgodności z przeglądarkami i utworzyć element jako pierwsze dziecko .img-container:

<div class="img-container">
    <div class="centerer"></div>
    <img src="http://placehold.it/150x150" alt="">
</div>
.img-container .centerer {
  display: inline-block;
  vertical-align: middle;
  height: 100%;
}

ZAKTUALIZOWANE DEMO .

Za pomocą max-* właściwości

W celu utrzymania wnętrza obrazu w oknie w dolnej szerokości, można ustawić max-heighti max-widthnieruchomość na zdjęcie:

.img-container img {
    vertical-align: middle;
    display: inline-block;
    max-height: 100%;  /* <-- Set maximum height to 100% of its parent */
    max-width: 100%;   /* <-- Set maximum width to 100% of its parent */
}

Oto ZAKTUALIZOWANA DEMO .

Hashem Qolami
źródło
1
Cześć Hashem, bardzo dziękuję za odpowiedź - działało to jak magia w przeglądarkach komputerowych, nawet przy zmianie rozmiaru na mniejsze szerokości. Ale niestety obrazy pojawiają się poza pozycją, poniżej elementu div kontenera, na urządzeniach mobilnych (Android v2.3.5). Masz jakiś pomysł na rozwiązanie tego problemu?
user1794295
3
@ user1794295 Przetestowałem to skrzypce na trzech urządzeniach z Androidem v2.3 (Galaxy S II, Galaxy Note, Motorola Droid 4) przez browserstack.com, wszystko działa tak, jak się spodziewałem, wynik można znaleźć tutaj: browserstack.com/screenshots /… . Prześlij zrzut ekranu lub przeprowadź konkretny test problemu. Pomogę tak, jak to możliwe.
Hashem Qolami
1
Cześć, oto kilka zrzutów ekranu: browserstack.com/screenshots/ ... - jak widać na mniejszych urządzeniach (np. Xperia, LG Nexus 4) obrazki pojawiają się pod kontenerami ... co się dzieje ?!
user1794295
3
@HashemQolami To jest najbardziej niesamowita rzecz CSS, odkąd zacząłem budować strony internetowe :).
Alexander Solonik
1
Dzięki za font-size: 0;!
Johannes Liebermann
47

Dzięki flexbox jest to łatwe:

SKRZYPCE

Po prostu dodaj następujące elementy do kontenera obrazu:

.img-container {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    display: flex; /* add */
    justify-content: center; /* add to align horizontal */
    align-items: center; /* add to align vertical */
}
Danield
źródło
2
To rozwiązanie działa i jest w moim przypadku dużo bardziej eleganckie. CSS3 Flex jest niesamowity!
Daniel Bonnell
2
To nie działa w Safari :( Myślę, że problem jest elastyczny
yennefer
1
@yennefer w przypadku safari użyj -webkit-prefiksu lub wypróbuj bibliotekę, taką jak prefixfree.js :)
QUB3X
To nie działa, gdy wysokość kontenera jest responsywna (w procentach).
jenlampton
1
Idealne rozwiązanie!
Nirus
16

Użyj tego css, ponieważ masz już do niego znaczniki:

.img-container {
    position: absolute;
    top: 50%;
    left: 50%;
}

.img-container > img {
  margin-top:-50%;
  margin-left:-50%;  
}

Oto działający JsBin: http://jsbin.com/ihilUnI/1/edit

To rozwiązanie działa tylko w przypadku kwadratowych obrazów (ponieważ procentowa wartość górnego marginesu zależy od szerokości kontenera, a nie od wysokości). W przypadku obrazów o losowych rozmiarach możesz wykonać następujące czynności:

.img-container {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%); /* add browser-prefixes */
}

Działające rozwiązanie JsBin: http://jsbin.com/ihilUnI/2/edit

Tibos
źródło
Przepraszam, nie działa dla mnie - to tylko zmniejszenie rozmiaru obrazów do połowy szerokości kontenera.
user1794295
2
Nie rozumiem, jak to się może stać z CSS, o którym wspomniałem. Proszę podać próbkę roboczą, którą widzę, abym mógł poprawić odpowiedź. PS:
Podałem
11

Możesz wyśrodkować obraz, zarówno w poziomie, jak iw pionie, używając margin: autoi pozycjonowania bezwzględnego. Również:

  1. Możliwe jest porzucenie dodatkowego znacznika za pomocą pseudoelementów.
  2. Możliwe jest wyświetlenie środkowej części DUŻYCH obrazów przy użyciu ujemnych wartości lewy, górny, prawy i dolny.

.responsive-container {
  margin: 1em auto;
  min-width: 200px;       /* cap container min width */
  max-width: 500px;       /* cap container max width */
  position: relative;     
  overflow: hidden;       /* crop if image is larger than container */
  background-color: #CCC; 
}
.responsive-container:before {
  content: "";            /* using pseudo element for 1:1 ratio */
  display: block;
  padding-top: 100%;
}
.responsive-container img {
  position: absolute;
  top: -999px;            /* use sufficiently large number */
  bottom: -999px;
  left: -999px;
  right: -999px;
  margin: auto;           /* center horizontally and vertically */
}
<p>Note: images are center-cropped on &lt;400px screen width.
  <br>Open full page demo and resize browser.</p>
<div class="responsive-container">
  <img src="http://lorempixel.com/400/400/sports/9/">
</div>
<div class="responsive-container">
  <img src="http://lorempixel.com/400/200/sports/8/">
</div>
<div class="responsive-container">
  <img src="http://lorempixel.com/200/400/sports/7/">
</div>
<div class="responsive-container">
  <img src="http://lorempixel.com/200/200/sports/6/">
</div>

Salman A
źródło
Dzięki! Twój .responsive-container img css był jedynym, który działał dla mnie.
Diogo Garcia
4

Spróbuj tego

  .responsive-container{
          display:table;
  }
  .img-container{
          display:table-cell;
          vertical-align: middle;
   }

źródło
Przepraszam, to nie działa, myślę, że mój .img-containerjest absolutnie ustawiony - jest to konieczne, aby zachować kwadratowy współczynnik kształtu / dynamiczną wysokość.
user1794295
2

Oto technika, która pozwala wyśrodkować KAŻDĄ treść zarówno w pionie, jak iw poziomie!

Zasadniczo potrzebujesz tylko dwóch pojemników i upewnij się, że Twoje elementy spełniają następujące kryteria.

Zewnętrzny pojemnik:

  • powinien mieć display: table;

Pojemnik wewnętrzny:

  • powinien mieć display: table-cell;
  • powinien mieć vertical-align: middle;
  • powinien mieć text-align: center;

Pole zawartości:

  • powinien mieć display: inline-block;

Jeśli używasz tej techniki, po prostu dodaj swój obraz (wraz z innymi treściami, które chcesz z nim połączyć) do pola zawartości.

Próbny :

body {
    margin : 0;
}

.outer-container {
    position : absolute;
    display: table;
    width: 100%;
    height: 100%;
    background: #ccc;
}

.inner-container {
    display: table-cell;
    vertical-align: middle;
    text-align: center;
}

.centered-content {
    display: inline-block;
    background: #fff;
    padding : 12px;
    border : 1px solid #000;
}

img {
   max-width : 120px;
}
<div class="outer-container">
   <div class="inner-container">
     <div class="centered-content">
        <img src="https://i.stack.imgur.com/mRsBv.png" />
     </div>
   </div>
</div>

Zobacz też to Fiddle !

John Slegers
źródło
2

Natknąłem się na ten wątek w poszukiwaniu rozwiązania, które:

  • wykorzystuje 100% szerokości danego obrazu
  • zachowuje proporcje obrazu
  • utrzymuje obraz wyrównany pionowo do środka
  • działa w przeglądarkach, które nie w pełni obsługują flex

Testując niektóre z rozwiązań zamieszczonych powyżej, nie znalazłem rozwiązania spełniającego wszystkie te kryteria, więc zestawiłem to proste, które może być przydatne dla innych osób, które muszą zrobić to samo:

.container {
  width: 30%;
  float: left;
  border: 1px solid turquoise;
  margin-right: 3px;
  margin-top: 3px;
}

.container:last-of-kind {
  margin-right: 0px;
}

.image-container {
  position: relative;
  overflow: hidden;
  padding-bottom: 70%;
  /* this is the desired aspect ratio */
  width: 100%;
}

.image-container img {
  position: absolute;
  /* the following 3 properties center the image on the vertical axis */
  top: 0;
  bottom: 0;
  margin: auto;
  /* uses image at 100% width (also meaning it's horizontally center) */
  width: 100%;
}
<div class="container">
  <div class="image-container">
    <img src="http://placehold.it/800x800" class="img-responsive">
  </div>
</div>

<div class="container">
  <div class="image-container">
    <img src="http://placehold.it/800x800" class="img-responsive">
  </div>
</div>

<div class="container">
  <div class="image-container">
    <img src="http://placehold.it/800x800" class="img-responsive">
  </div>
</div>

Przykład roboczy na JSFiddle

Alexandra
źródło
0

Próbować

HTML

<div class="responsive-container">
     <div class="img-container">
         <IMG HERE>
     </div>
</div>

CSS

.img-container {
    position: absolute;
    top: 0;
    left: 0;
height:0;
padding-bottom:100%;
}
.img-container img {
width:100%;
}
Paramasivan
źródło
0

Kod HTML

<div class="image-container"> <img src=""/> </div>

kod css

img
{
  position: relative;
  top: 50%;
  transform: translateY(-50%);
 }
William
źródło
Chociaż ten fragment kodu jest mile widziany i może zapewnić pewną pomoc, byłby znacznie ulepszony, gdyby zawierał wyjaśnienie, w jaki sposób odpowiada na pytanie. Bez tego Twoja odpowiedź ma znacznie mniejszą wartość edukacyjną - pamiętaj, że w przyszłości odpowiadasz na pytanie do czytelników, a nie tylko osoby, która pyta teraz! Proszę edytować swoje odpowiedzi, aby dodać wyjaśnienie, i dać wskazówkę co zastosować ograniczenia i założenia.
Toby Speight
0

Utwórz kolejny element div i dodaj do niego zarówno „dummy”, jak i „img-container”

Wykonaj HTML i CSS w następujący sposób

html , body {height:100%;}
.responsive-container { height:100%; display:table; text-align:center; width:100%;}
.inner-container {display:table-cell; vertical-align:middle;}
<div class="responsive-container">
    <div class="inner-container">
		<div class="dummy">Sample</div>
		<div class="img-container">
			Image tag
		</div>
	</div>	
</div>

Zamiast 100% dla „responsywnego kontenera” możesz podać żądaną wysokość.,

Odkryć
źródło