Übergroßes Bild in Div

175

Ich habe versucht herauszufinden, wie ein übergroßes Bild innerhalb eines Divs nur mit CSS zentriert werden kann.

Wir verwenden ein flüssiges Layout, daher variiert die Breite der Bildcontainer mit der Seitenbreite (die Höhe von div ist fest). Das Bild befindet sich in einem Div, wobei ein eingefügter Boxshadow so bewertet wird, als ob Sie durch die Seite auf das Bild schauen.

Das Bild selbst wurde so dimensioniert, dass es das umgebende Div mit seinem größtmöglichen Wert ausfüllt (das Design hat eine max-width Wert).

Es ist ziemlich einfach, wenn das Bild kleiner als das umgebende Div ist:

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

Aber wenn das Bild größer als das Div ist, beginnt es einfach am linken Rand und ist außermittig rechts (wir verwenden) overflow: hidden ).

Wir könnten eine zuweisen width=100% , aber Browser machen einen miesen Job beim Ändern der Bildgröße, und das Webdesign konzentriert sich auf qualitativ hochwertige Bilder.

Irgendwelche Ideen zum Zentrieren des Bildes, damit overflow:hiddenbeide Kanten gleichmäßig abgeschnitten werden?

Tom
quelle
2
Haben Sie dieses Problem jemals bei Tom gelöst? Ich bin im Moment auf das gleiche Problem gestoßen. :)
ctrlplusb
Ich gehe davon aus, dass Ihre Bildbreiten variieren.
otherDewi

Antworten:

365

Versuchen Sie so etwas. Dies sollte jedes große Element in der Mitte vertikal und horizontal in Bezug auf sein übergeordnetes Element zentrieren, unabhängig von beiden Größen.

.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
quelle
4
wunderbar: das funktioniert mit jedem element. auch mit html 5 video ... danke!
Taseenb
3
So wie ich das verstehe: Es funktioniert, weil es ein Element erstellt (hoffentlich), das größer als das Bild ist (2 * 9999px x 2 * 9999px) und das Bild innerhalb dieses Elements zentriert (Rand: Auto). Solange das Bild 2 * 9999px nicht überschreitet, sollte es funktionieren.
Michael Krupp
16
Warum nicht -100%für oben / rechts / unten / links verwenden? Damit könnte der Container buchstäblich jede Breite haben.
Simon
15
Ja, ich habe das -100%Problem auch erlebt ^^. Übrigens: Wenn Sie hinzufügen min-widthund min-heightvon 100%Ihnen im Grunde ein background-size: cover;Verhalten mit Bild-Tags bekommen -> jsfiddle
Simon
3
@ HarrisonPowers Nun, der Elternteil muss natürlich eine Größe haben, egal ob fest oder dynamisch. Es funktioniert auch, wenn ein anderer Inhalt das Div ausfüllt, wodurch es eine Höhe hat (wie zum Beispiel Text).
Hyounis
162

Dies ist ein altes Q, aber eine moderne Lösung ohne Flexbox oder Positions absolut funktioniert so.

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

Warum funktioniert es also?
Auf den ersten Blick scheinen wir 50% nach rechts und dann wieder 50% nach links zu verschieben. Das würde zu einer Nullpunktverschiebung führen, na und?
Aber die 50% sind nicht gleich, weil der Kontext wichtig ist. Wenn Sie relative Einheiten verwenden, wird ein Rand als Prozentsatz der Breite des übergeordneten Elements berechnet , während die Transformation 50% relativ zum selben Element beträgt.

Wir haben diese Situation, bevor wir das CSS hinzufügen

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

Mit dem zusätzlichen Stil haben margin-left: 50%wir

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

       a is 50% width of P

Und die transform: translateX(-50%)Verschiebung zurück nach links

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

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

Leider funktioniert dies nur für die horizontale Zentrierung, da die Berechnung des Randprozentsatzes immer relativ zur Breite ist. Dh nicht nur margin-leftund margin-right, sondern auch margin-topundmargin-bottom werden in Bezug auf die Breite berechnet.

Die Browserkompatibilität sollte kein Problem sein: https://caniuse.com/#feat=transforms2d

Yunzen
quelle
Es funktioniert nicht für die vertikale Ausrichtung (wenn .inner eine größere Höhe als .outer hat)
cronfy
1
@cronfy Nein, vertikal funktioniert es nicht, da margin-top: 50%es 50% der Breite beträgt . nicht die gewünschte Höhe.
Yunzen
2
das ist bei weitem die eleganteste Lösung
Souhaieb Besbes
für eine Weile nach einer Lösung suchen, am besten, am einfachsten; Prost
lauWM
2
Das ist pure Zauberermagie. Danke dir! Funktioniert perfekt in Safari und Chrome (mit einem Zusatz -webkit-transform: translateX(-50%);für ein gutes Maß)
Nick Schneble
22

Setzen Sie ein großes Div in das Div, zentrieren Sie das und zentrieren Sie das Bild in diesem Div.

Dies zentriert es 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/

Um es auch vertikal zu zentrieren, können Sie dasselbe für das innere Div verwenden, aber Sie benötigen die Höhe des Bildes, um es absolut darin zu platzieren.

Guffa
quelle
Dies endete damit, dass der linke Rand des Bildes im "imageContainer" zentriert war. Wie ich oben kommentiert habe, ist unser Bildcontainer div die Flüssigkeitsbreite und die feste Höhe.
Tom
1
@ Tom: Wenn ich die widthEinstellung im Container entferne , entspricht dies der Breite des übergeordneten Elements , und das Bild wird zentriert, auch wenn die Seite schmaler als das Bild ist, dh so viel vom linken Rand wie vom rechten Rand ausgeblendet wird : jsfiddle.net/Guffa/L9BnL/2
Guffa
Danke für die Inspiration. Ich benutze position: relative für .imageCenter. Auf diese Weise brauche ich nicht die Position: relative für den übergeordneten Container.
user3153298
Diese Frage hat viele clevere Tricks und sie haben alle ihre Nachteile. Einige arbeiten "besser", sind aber überhaupt nicht leicht zu verstehen. Diese Lösung ist absolut sinnvoll. Das Bild wird normalerweise in einem breiteren Bereich zentriert, der zugeschnitten wird. Es fühlt sich falsch an, aber es funktioniert definitiv, ohne die Gesetze der Webphysik zu brechen. Ich habe diese Option einigen anderen sehr schwer verständlichen Tricks vorgezogen, auch wenn sie sich etwas schmutzig anfühlt.
Radley Sustaire
9

Spät zum Spiel, aber ich fand diese Methode äußerst intuitiv. 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
quelle
3
Nett! Es kann auch vereinfacht werden. Der Trick wird display: flexauf dem übergeordneten Container und align-self: centerauf dem Bild ausgeführt. Hier ist eine optimierte Version: codepen.io/anon/pen/dWKyey
caiosm1005
5

Verwenden Sie keine feste oder explizite Breite oder Höhe für das Bild-Tag. Codieren Sie es stattdessen:

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

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

Lederjacke4
quelle
1
Dies lässt dann Platz um das Bild herum, den sie meiner Meinung nach zu vermeiden versuchen.
Eoin
3

Ich bin ein großer Fan davon, ein Bild zum Hintergrund eines Div / Node zu machen - dann können Sie es einfach mit dem background-position: centerAttribut zentrieren, unabhängig von der Bildschirmgröße

Shain Lafazan
quelle
9
Dies ist keine zugängliche Methode zur Verwendung von Bildern. Es mag für dekorative Bilder gut funktionieren, aber jedes Bild, das informativ ist, benötigt Alternativtext.
user2532030
0

Die Breite und Höhe sind nur zum Beispiel:

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

Es muss für Sie funktionieren, wenn das linke und das obere Ende Ihres übergeordneten Divs nicht ganz oben und links vom Fenster Ihres Bildschirms sind. Für mich geht das.

Панайот Толев
quelle
Schien keinen Unterschied zu machen. Ich bin mir nicht sicher, ob es irgendetwas damit zu tun hat, dass die Breite fließend ist, während die Höhe auf dem übergeordneten Div festgelegt ist.
Tom
2
Diese Technik funktioniert, wenn das Bild kleiner als der Container ist.
otherDewi
0

Ich fand, dass dies eine elegantere Lösung ohne Flex ist:

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

Aufbauend auf der großartigen Antwort von @ yunzen:

Ich vermute, dass viele Leute, die nach diesem Thema suchen, versuchen, ein großes Bild als "Helden" -Hintergrundbild zu verwenden, zum Beispiel auf einer Homepage. In diesem Fall möchten sie häufig, dass Text über dem Bild angezeigt wird und auf Mobilgeräten gut verkleinert wird.

Hier ist das perfekte CSS für ein solches Hintergrundbild (verwenden Sie es auf dem <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
quelle
-1

Eine Option, die Sie verwenden können, ist, dass object-fit: coveres sich ein bisschen wie verhält background-size: cover. Mehr zur Objektanpassung .

Ignoriere alle JS unten, das ist nur für die Demo.

Der Schlüssel hier ist, dass Sie das Bild in einem Wrapper festlegen und ihm die folgenden Eigenschaften geben müssen.

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

Ich habe unten eine Demo erstellt, in der Sie die Höhe / Breite des Wrappers ändern und im Spiel sehen. Das Bild wird immer vertikal und horizontal zentriert. Es nimmt 100% seiner übergeordneten Breite und Höhe ein und wird nicht gedehnt / gequetscht. Dies bedeutet, dass das Seitenverhältnis des Bildes beibehalten wird. Die Änderungen werden stattdessen durch Vergrößern / Verkleinern übernommen.

Der einzige Nachteil object-fitist, dass es unter IE11 nicht funktioniert .

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