Skaluj obraz, aby pasował do obwiedni

117

Czy istnieje rozwiązanie tylko CSS umożliwiające skalowanie obrazu do ramki ograniczającej (zachowując współczynnik proporcji)? Działa to, jeśli obraz jest większy niż kontener:

img {
  max-width: 100%;
  max-height: 100%;
}

Przykład:

Ale chcę przeskalować obraz, aż wymiar będzie stanowił 100% kontenera.

Thomas Guillory
źródło
Czy masz na myśli wysokość: 100% i szerokość: 100%? czy masz pożądany wymiar, do którego chcesz dotrzeć? w przeciwnym razie możesz również rozciągnąć obraz i zmusić go do osiągnięcia tych wymiarów.
mikevoermans
@mikevoermans Spójrz na moje dwa pierwsze przykłady: chcę rozciągnąć obraz, aż jeden z wymiarów osiągnie 100%, a drugi <= 100%
Thomas Guillory
@jacktheripper Oczywiście zachowując proporcje ...
Thomas Guillory
@gryzzly Przykłady mówią same za siebie! Gdyby spojrzeli na przykłady, było to oczywiste.
Thomas Guillory,
@Artimuz Zupełnie się nie zgadzam. Trzy odpowiedzi na Twoje pytania (w tym moje) sugerują, że NIE było to oczywiste.
Khan

Odpowiedzi:

94

Uwaga: mimo że jest to akceptowana odpowiedź, poniższa odpowiedź jest dokładniejsza i jest obecnie obsługiwana we wszystkich przeglądarkach, jeśli masz możliwość korzystania z obrazu tła.

Nie, nie ma jedynego sposobu CSS, aby to zrobić w obu kierunkach. Możesz dodać

.fillwidth {
    min-width: 100%;
    height: auto;
}

Aby element zawsze miał 100% szerokości i automatycznie skalował wysokość do współczynnika proporcji lub odwrotnie:

.fillheight {
    min-height: 100%; 
    width: auto;
}

aby zawsze skalować do maksymalnej wysokości i względnej szerokości. Aby zrobić jedno i drugie, musisz określić, czy współczynnik proporcji jest wyższy, czy niższy niż jego kontener, a CSS nie może tego zrobić.

Powodem jest to, że CSS nie wie, jak wygląda strona. Z góry ustala zasady, ale dopiero potem renderuje się elementy i wiesz dokładnie, z jakimi rozmiarami i proporcjami masz do czynienia. Jedynym sposobem na wykrycie tego jest JavaScript.


Chociaż nie szukasz rozwiązania JS, i tak dodam, jeśli ktoś może go potrzebować. Najłatwiejszym sposobem radzenia sobie z tym za pomocą JavaScript jest dodanie klasy na podstawie różnicy w stosunku. Jeśli stosunek szerokości do wysokości pudełka jest większy niż obrazu, dodaj klasę „fillwidth”, w przeciwnym razie dodaj klasę „fillheight”.

Stephan Muller
źródło
7
Właściwie jest rozwiązanie: ustawienie rozmiaru tła CSS3 na zawiera. Zobacz moją odpowiedź.
Thomas Guillory
Masz całkowitą rację. Mimo że minęło półtora roku, zredagowałem swój post.
Stephan Muller
4
Zakładam, że jest to poprawna odpowiedź na zadane pytanie, czyli jaki jest kod CSS dla tagu img. Jest to istotne, ponieważ semantycznie tag img jest treścią, a obraz jako tło elementu div nie. Podczas gdy niektóre okoliczności sprawiają, że jest to niepraktyczne (jeśli nie znasz stosunku obrazu do kontenera), w innych jest to w sam raz. Dzięki.
duncanwilcox
173

Dzięki CSS3 jest rozwiązanie!

Rozwiązaniem jest umieścić obraz jako background-image, a następnie ustawić background-sizesię contain.

HTML

<div class='bounding-box'>
</div>

CSS

.bounding-box {
  background-image: url(...);
  background-repeat: no-repeat;
  background-size: contain;
}

Przetestuj tutaj: http://www.w3schools.com/cssref/playit.asp?filename=playcss_background-size&preval=contain

Pełna zgodność z najnowszymi przeglądarkami: http://caniuse.com/background-img-opts

Aby wyrównać element div do środka, możesz użyć tej odmiany:

.bounding-box {
  background-image: url(...);
  background-size: contain;
  position: absolute;
  background-position: center;
  background-repeat: no-repeat;
  height: 100%;
  width: 100%;
}
Thomas Guillory
źródło
1
Niezłe, chociaż moja odpowiedź nie jest błędna (pytałeś konkretnie o img), to jest świetne rozwiązanie i powinienem był o tym pomyśleć. Jedynym problemem jest to, że IE 8 jest nadal tak szeroko stosowany, że nie chciałbym jeszcze na nim polegać, ale mimo to niezły haczyk.
Stephan Muller,
6
Ustaw go na „okładka”, jeśli nie chcesz używać czarnych pasków: background-size: include;
arxpoetica
3
Należy zauważyć, że można wprowadzić adres URL obrazu z HTML: <div class=image style="background-image: url('/images/foo.jpg');"></div>. Wszystkie inne style należy stosować za pomocą CSS.
Andrey Mikhaylov - lolmaus
14
Powiedziałbym, że to straszne podejście. Zmieniając go na obraz tła, usuwasz semantyczne znaczenie obrazu w kodzie HTML.
animuson
14
@animuson: To nadal mi pomogło, ponieważ używam HTML / CSS do drukowanych raportów i nie mogłem dać
zdziwienia na
37

Oto hakerskie rozwiązanie, które odkryłem:

#image {
    max-width: 10%;
    max-height: 10%;
    transform: scale(10);
}

Spowoduje to dziesięciokrotne powiększenie obrazu, ale ograniczy go do 10% ostatecznego rozmiaru - w ten sposób ograniczając go do pojemnika.

W przeciwieństwie do background-imagerozwiązania sprawdzi się to również z <video>elementami.

Interaktywny przykład:

Vladimir Panteleev
źródło
1
Uwielbiam to rozwiązanie. Nie tylko faktycznie odpowiada na pytanie (wiem, co za myśl), ale działa pięknie we wszystkich nowoczesnych przeglądarkach bez konieczności uciekania się do Javascript!
ndm13
2
Chciałbym zobaczyć coś takiego. W moim teście złożenia img w pojemniku IMG 400x400 po prostu staje przyciętymi w narożniku
cyberwombat
3
Niezła odpowiedź! @Yashua Musisz dodać, transform-origin: top leftaby zatrzymać kadrowanie. / Zombie
XwipeoutX
Znakomity. Moim jedynym zmartwieniem byłaby możliwa utrata jakości obrazu w źle zakodowanej przeglądarce, ale teoretycznie powinno działać dobrze!
Codemonkey
Ciekawe, ale nie działa w Chrome. Daje przycięty wiersz obrazu.
MattK,
23

Dziś wystarczy powiedzieć object-fit: include. Wsparcie to wszystko oprócz IE: http://caniuse.com/#feat=object-fit

Glenn Maynard
źródło
3
IE ma obecnie tylko około 16% udziału w rynku w momencie pisania tego (12.09.2016 10:56) i nadal maleje, więc jest to dla mnie najlepsza odpowiedź: D
Zhang
8
Nie edytuj odpowiedzi innych osób, aby naprawić rzeczy inne niż literówki lub uszkodzone linki. Nie powiedziałbym czegoś dziecinnego w rodzaju „Jest polifill dla przeglądarek bzdur” w odpowiedzi TAK i nie podoba mi się, że moja odpowiedź została zredagowana tak, aby wyglądała tak, jak to powiedziałem. jeśli chcesz użyć swoich słów, umieść je we własnej odpowiedzi.
Glenn Maynard
Powiedziałbym, że to nie IE jest problemem, ale Edge. Według Caniuse object-fitjest nadal w fazie rozwoju.
BairDev
To powinna być jedna z najczęściej wybieranych odpowiedzi w 2017 r. I dalej ... Zgodnie z powyższym linkiem caniuse, 90% wszystkich użytkowników na całym świecie korzysta teraz z przeglądarki, która to obsługuje
fgblomqvist
Właśnie opublikowałem odpowiedź, która działa object-fit
zi
8

html:

    <div class="container">
      <img class="flowerImg" src="flower.jpg">
    </div>

css:

.container{
  width: 100px;
  height: 100px;
}


.flowerImg{
  width: 100px;
  height: 100px;
  object-fit: cover;
  /*object-fit: contain;
  object-fit: scale-down;
  object-position: -10% 0;
  object-fit: none;
  object-fit: fill;*/
}
Deke
źródło
5

Możesz to osiągnąć dzięki czystemu CSS i pełnej obsłudze przeglądarek, zarówno dla obrazów w pionie, jak i w poziomie w tym samym czasie.

Oto fragment, który działa w przeglądarkach Chrome, Firefox i Safari (zarówno przy użyciu object-fit: scale-down, jak i bez niego):

figure {
  margin: 0;
}

.container {
  display: table-cell;
  vertical-align: middle;
  width: 80px;
  height: 80px;
  border: 1px solid #aaa;
}

.container_image {
  display: block;
  max-width: 100%;
  max-height: 100%;
  margin-left: auto;
  margin-right: auto;
}

.container2_image2 {
  width: 80px;
  height: 80px;
  object-fit: scale-down;
  border: 1px solid #aaa;
}
Without `object-fit: scale-down`:

<br>
<br>

<figure class="container">
  <img class="container_image" src="https://i.imgur.com/EQgexUd.jpg">
</figure>

<br>

<figure class="container">
  <img class="container_image" src="https://i.imgur.com/ptO8pGi.jpg">
</figure>

<br> Using `object-fit: scale-down`:

<br>
<br>

<figure>
  <img class="container2_image2" src="https://i.imgur.com/EQgexUd.jpg">
</figure>

<br>

<figure>
  <img class="container2_image2" src="https://i.imgur.com/ptO8pGi.jpg">
</figure>

gabrielmaldi
źródło
2

Inne rozwiązanie bez obrazu tła i bez potrzeby stosowania kontenera (chociaż należy znać maksymalne rozmiary ramki ograniczającej):

img{
  max-height: 100px;
  max-width: 100px;
  width: auto;    /* These two are added only for clarity, */
  height: auto;   /* as the default is auto anyway */
}


Jeśli wymagane jest użycie kontenera, wówczas maksymalna szerokość i maksymalna wysokość mogą być ustawione na 100%:

img {
    max-height: 100%;
    max-width: 100%;
    width: auto; /* These two are added only for clarity, */
    height: auto; /* as the default is auto anyway */
}

div.container {
    width: 100px;
    height: 100px;
}

Do tego miałbyś coś takiego:

<table>
    <tr>
        <td>Lorem</td>
        <td>Ipsum<br />dolor</td>
        <td>
            <div class="container"><img src="image5.png" /></div>
        </td>
    </tr>
</table>
xerxeArt
źródło
1

Ten przykład przedstawia proporcjonalne rozciągnięcie obrazu w celu dopasowania do całego okna. Improwizacją do powyższego poprawnego kodu jest dodanie$( window ).resize(function(){});

function stretchImg(){
    $('div').each(function() {
      ($(this).height() > $(this).find('img').height()) 
        ? $(this).find('img').removeClass('fillwidth').addClass('fillheight')
        : '';
      ($(this).width() > $(this).find('img').width()) 
        ? $(this).find('img').removeClass('fillheight').addClass('fillwidth')
        : '';
    });
}
stretchImg();

$( window ).resize(function() {
    strechImg();
});

Są dwa warunki warunkowe. Pierwsza z nich sprawdza, czy wysokość obrazu jest mniejsza niż div i stosuje .fillheightklasę, podczas gdy następna sprawdza szerokość i stosuje .fillwidthklasę. W obu przypadkach druga klasa jest usuwana za pomocą.removeClass()

Oto CSS

.fillwidth { 
   width: 100%;
   max-width: none;
   height: auto; 
}
.fillheight { 
   height: 100vh;
   max-width: none;
   width: auto; 
}

Możesz zamienić 100vhna, 100%jeśli chcesz rozciągnąć obraz w div. Ten przykład przedstawia proporcjonalne rozciągnięcie obrazu w celu dopasowania do całego okna.

Panie JCRP
źródło
OP specjalnie poprosił o podejście tylko do CSS.
Colt McCormack
0

Czy chcesz skalować w górę, ale nie w dół?

div {
    border: solid 1px green;
    width: 60px;
    height: 70px;
}

div img {
    width: 100%;
    height: 100%;
    min-height: 500px;
    min-width: 500px;
    outline: solid 1px red;
}

Nie powoduje to jednak blokady współczynnika kształtu.

ericosg
źródło
5
Postaraj się trochę bardziej wyrazić swoje oczekiwania przed odrzuceniem czyjejś odpowiedzi. Zwłaszcza, gdy odpowiedzieli na Twoje pytanie, zanim wyjaśnisz pytanie, wprowadzając zmiany.
Khan
2
Postaraj się też być bardziej uprzejmy. Nikt ci nie pomoże, jeśli będziesz mówić w ten sposób.
Misha Reyzlin
@Artimuz Przepraszam, jeśli cię nie poprowadziłem, ale wydawało mi się niejasne, że chcesz zachować proporcje, dlatego właśnie to skomentowałem. Zauważysz również, że wkleiłem fragment Twojego kodu z przykładów. Uważam, że utrzymanie wysokości: auto; zrobi to za Ciebie, jeśli określisz szerokość.
ericosg
0

Użyłem tabeli do wyśrodkowania obrazu wewnątrz pudełka. Zachowuje proporcje i skaluje obraz w sposób całkowicie wewnątrz pudełka. Jeśli obraz jest mniejszy niż ramka, jest wyświetlany tak, jak jest w środku. Poniższy kod używa pola o szerokości 40 pikseli i wysokości 40 pikseli. (Nie jestem pewien, jak dobrze to działa, ponieważ usunąłem go z innego, bardziej złożonego kodu i trochę uprościłem)

CSS:

.SmallThumbnailContainer
{
    display: inline-block; position: relative;
    float: left;    
    width: 40px;
    height: 40px;
    border: 1px solid #ccc;
    margin: 0px; padding: 0px;
}
.SmallThumbnailContainer { width: 40px; margin: 0px 10px 0px 0px; } 
.SmallThumbnailContainer tr { height: 40px; text-align: center; }
.SmallThumbnailContainer tr td { vertical-align: middle; position: relative; width: 40px;  }
.SmallThumbnailContainer tr td img { overflow: hidden; max-height: 40px; max-width: 40px; vertical-align: middle; margin: -1px -1px 1px -1px; }

HTML:

<table class="SmallThumbnailContainer" cellpadding="0" cellspacing="0">
    <tr><td>
        <img src="thumbnail.jpg" alt="alternative text"/>
    </td></tr>
    </table>
Antti
źródło
0

Najczystszy i najprostszy sposób na zrobienie tego:

Najpierw trochę CSS:

div.image-wrapper {
    height: 230px; /* Suggestive number; pick your own height as desired */
    position: relative;
    overflow: hidden; /* This will do the magic */
    width: 300px; /* Pick an appropriate width as desired, unless you already use a grid, in that case use 100% */
}
img {
    width: 100%;
    position: absolute;
    left: 0;
    top: 0;
    height: auto;
}

HTML:

<div class="image-wrapper">
  <img src="yourSource.jpg">
</div>

To powinno załatwić sprawę!

Robert Eetheart
źródło
0

Pomogło mi to:

.img-class {
  width: <img width>;
  height: <img height>;
  content: url('/path/to/img.png');
}

Następnie na elemencie (możesz użyć javascript lub zapytań o media, aby dodać responsywność):

<div class='img-class' style='transform: scale(X);'></div>

Mam nadzieję że to pomoże!

bman93
źródło
-3
.boundingbox {
    width: 400px;
    height: 500px;
    border: 2px solid #F63;
}
img{
    width:400px;
    max-height: 500px;
    height:auto;
}

Edytuję swoją odpowiedź, aby dokładniej wyjaśnić moje rozwiązanie, ponieważ mam głos negatywny.

Po ustawieniu stylów, jak pokazano powyżej w css, teraz następujący element HTML HTML będzie pokazywał obraz zawsze dopasowany do szerokości i dostosuje wysokość do szerokości. W ten sposób obraz zostanie przeskalowany, aby dopasować go do obwiedni zadanej w pytaniu.

<div class="boundingbox"><img src="image.jpg"/></div>
zeeawan
źródło
Ta odpowiedź działa tylko wtedy, gdy pudełko jest wyższe niż szerokie.
XwipeoutX