Pflegen Sie das Seitenverhältnis eines Div mit CSS


1058

Ich möchte eine erstellen div, die ihre Breite / Höhe ändern kann, wenn sich die Breite des Fensters ändert.

Gibt es CSS3-Regeln, nach denen sich die Höhe entsprechend der Breite ändern kann, während das Seitenverhältnis beibehalten wird ?

Ich weiß, dass ich dies über JavaScript tun kann, aber ich würde es vorziehen, nur CSS zu verwenden.

div Seitenverhältnis entsprechend der Fensterbreite beibehalten


2
Ich habe in meinem CSS-Tricks-Artikel über die Skalierung reaktionsfähiger Animationen
Zach Saucier

2
Ich bin sehr spät zu diesem Q & A gekommen, aber ich muss einen Kommentar abgeben. Obwohl es sehr diszipliniert ist und innerhalb der SO-Regeln von allen antwortenden Personen versucht, ihr Bestes zu geben, um die "einzige CSS" -Anforderung der Frage zu erfüllen, ist es ziemlich überraschend, dass mit Ausnahme der Antwort von user007 unten auf der Seite nein- man hat das Offensichtliche erwähnt: Es gibt keine zuverlässige Nur-CSS-Lösung, dieses Problem erfordert Javascript. Ein Neuling, der auf diese Seite kommt, könnte wertvolle Zeit damit verschwenden, von einem Satz Vor- / Nachteile zu einem anderen zu wechseln, bevor die Glühbirne ausgeht: Nur CSS reicht nicht aus.
Theo d'Or

1
Ich habe ein kleines Tool geschrieben, mit dem sich die Seitenverhältnisse leicht anzeigen und berechnen lassen: aspektrat.io . Außerdem wird der entsprechende CSS / Sass / Less-Code generiert, den Sie kopieren und in Ihre Projekte einfügen können. Hoffe, die Leute finden es nützlich.
Ryan Hefner


1
Diese Frage dient zum Einstellen der Höhe basierend auf der Breite . Wenn Sie das Gegenteil benötigen, lesen Sie Einstellen der Elementbreite basierend auf der Höhe über CSS .
John Mellor

Antworten:


1353

Erstellen Sie einfach einen Wrapper <div>mit einem Prozentwert für padding-bottom:

div {
  width: 100%;
  padding-bottom: 75%;
  background: gold; /** <-- For the demo **/
}

/* demonstration purposed only : non-essential */
.demoWrapper {
  padding: 10px;
  background: white;
  box-sizing: border-box;
  resize: horizontal;
  border: 1px dashed;
  overflow: auto;
  max-width: 100%;
  height: calc(100vh - 16px);
}
<div class="demoWrapper">
  <div></div>
</div>

Dies führt zu einer <div>Höhe von 75% der Breite des Behälters (ein Seitenverhältnis von 4: 3).

Dies beruht auf der Tatsache, dass für die Polsterung:

Der Prozentsatz wird in Bezug auf die Breite des generierten Blocks berechnet, der den Block [...] enthält (Quelle: w3.org , Schwerpunkt Mine).

Padding-Bottom-Werte für andere Seitenverhältnisse und 100% Breite:

aspect ratio  | padding-bottom value
--------------|----------------------
    16:9      |       56.25%
    4:3       |       75%
    3:2       |       66.66%
    8:5       |       62.5%

Platzieren von Inhalten in der div:

Um das Seitenverhältnis des Div beizubehalten und zu verhindern, dass sein Inhalt es dehnt, müssen Sie ein absolut positioniertes Kind hinzufügen und es an den Rändern des Wrappers strecken mit:

div.stretchy-wrapper {
  position: relative;
}

div.stretchy-wrapper > div {
  position: absolute;
  top: 0; bottom: 0; left: 0; right: 0;
}

Hier ist eine Demo und eine weitere ausführlichere Demo


29
@schellmax, weil das Auffüllen% relativ zur Breite des aktuellen Elements berechnet wird, wobei als Höhe% relativ zur Höhe des übergeordneten Elements berechnet wird. Darüber hinaus werden absolute Positionen relativ zum Außencontainer eines Elements berechnet, der den Auffüllbereich enthält. Für weitere Informationen Google "CSS Box Model"
Anson Kao

11
Dies scheint nicht verschachtelt zu funktionieren. Es funktioniert auf der ersten Ebene, aber wenn versucht wird, dasselbe innerhalb des Seitenverhältnisses von div zu tun, scheint der Prozentsatz des Auffüllbodens auf die Breite des übergeordneten Elements angewendet zu werden. Hier ist ein Beispiel, in dem der dritte Stretch-Boden von .stretchy-wrap.onethird von 25% tatsächlich 25% der übergeordneten Breite beträgt. Kann jemand das erklären?
Misterparker

4
Total genial. Es bringt mich um, dass diese Technik nicht funktioniert, wenn Sie die Höhe auf 100% festlegen möchten. @Misterparker, die Technik basiert auf den Breiten- und Polsterungsberechnungen, die für dieselbe Referenz durchgeführt werden. Sie können keine Breite verwenden, die kleiner als 100% ist, wie in Ihrem Beispiel.
steveluscher

2
@Misterparker Ja, der prozentuale Abstand wird proportional zur Breite des übergeordneten Elements berechnet. Sehen Sie sich das ausführlichere Beispiel an, das ich in einer Bearbeitung zu meiner Antwort gepostet habe. Meine aktualisierte Demo zeigt eine "verschachtelte Mode", von der Sie gesprochen haben.
Web_Designer

3
Die Tatsache, dass er gezeigt hat, dass dies funktioniert, reicht aus, um mich davon zu überzeugen, dass dies die beste Antwort ist, die ich bisher auf SO gesehen habe. schreien Sie zu meinem Mann @Web_Designer

411

vw Einheiten:

Sie können vwEinheiten sowohl für die Breite als auch für die Höhe des Elements verwenden. Dadurch kann das Seitenverhältnis des Elements basierend auf der Breite des Ansichtsfensters beibehalten werden.

vw: 1/100 der Breite des Ansichtsfensters. [ MDN ]

Alternativ können Sie auch vhfür Darstellungshöhe oder sogar vmin/ vmaxdie weniger / mehr im Darstellungs Dimensionen zu verwenden (Diskussion hier ).

Beispiel: Seitenverhältnis 1: 1

div {
  width: 20vw;
  height: 20vw;
  background: gold;
}
<div></div>

Für andere Seitenverhältnisse können Sie die folgende Tabelle verwenden, um den Wert für die Höhe entsprechend der Breite des Elements zu berechnen:

aspect ratio  |  multiply width by
-----------------------------------
     1:1      |         1
     1:3      |         3
     4:3      |        0.75
    16:9      |       0.5625

Beispiel: 4x4-Raster aus quadratischen Divs

body {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
div {
  width: 23vw;
  height: 23vw;
  margin: 0.5vw auto;
  background: gold;
}
<div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>

Hier ist eine Geige mit dieser Demo und hier ist eine Lösung, um ein ansprechendes Quadratraster mit vertikal und horizontal zentriertem Inhalt zu erstellen .


Browser-Unterstützung für vh / vw-Einheiten ist IE9 + siehe canIuse für weitere Informationen


14
Dies sollte die akzeptierte Antwort sein. Vielleicht nicht jetzt, aber in der Zukunft. vw-Einheiten werden derzeit in den meisten Browsern unterstützt .
August

3
@vivekmaharajh beide Techniken sind gut, jede hat ihre eigenen Vor- und Nachteile. Die Verwendung des einen oder anderen hängt stark von der Situation ab.
Web-Tiki

11
@ Web-Tiki, du hast recht. Ich bin auf ein Problem gestoßen: Es wird davon ausgegangen, dass die Breite des Elements proportional zur Breite des Ansichtsfensters ist. Dies ist nicht der Fall, wenn 1) Sie Rinnen mit fester Breite haben oder 2) Sie die maximale Breite festgelegt haben für einige Ihrer Elemente.
Vivek Maharajh

1
Vielleicht ist es nur Chrome v47beta, aber wenn ich das div auf setze width:50%und height:50vwdie Höhe etwas größer als die Breite ist, also nicht gerade ein 1: 1-Verhältnis. Irgendwelche Ideen?
Dooan

2
@ 10basetom ist es ein normales Verhalten. vw-Einheiten enthalten die Breite der Bildlaufleiste,% width nicht. Der Unterschied zwischen Höhe und Breite hängt von der Größe der Bildlaufleiste ab, die je nach Browser unterschiedlich ist.
Web-Tiki

26

Ich habe einen Weg gefunden, dies mit CSS zu tun, aber Sie müssen vorsichtig sein, da es sich je nach Ablauf Ihrer eigenen Website ändern kann. Ich habe es getan, um Videos mit einem konstanten Seitenverhältnis in einen Bereich mit flüssiger Breite meiner Website einzubetten.

Angenommen, Sie haben ein eingebettetes Video wie dieses:

<object>
     <param ... /><param ... />...
     <embed src="..." ...</embed>
</object>

Sie könnten dies alles in einem Div mit einer "Video" -Klasse platzieren. Diese Videoklasse wird wahrscheinlich das fließende Element auf Ihrer Website sein, sodass es für sich genommen keine direkten Höhenbeschränkungen gibt. Wenn Sie jedoch die Größe des Browsers ändern, ändert sich die Breite entsprechend dem Fluss der Website. Dies ist das Element, in das Sie wahrscheinlich versuchen, Ihr eingebettetes Video zu integrieren, während Sie ein bestimmtes Seitenverhältnis des Videos beibehalten.

Zu diesem Zweck habe ich ein Bild vor das eingebettete Objekt innerhalb der Klasse "Video" div gesetzt.

!!! Der wichtige Teil ist, dass das Bild das richtige Seitenverhältnis hat, das Sie beibehalten möchten. Stellen Sie außerdem sicher, dass die Größe des Bildes MINDESTENS so groß ist wie die kleinste, von der Sie erwarten, dass das Video (oder was auch immer Sie den AR beibehalten) basierend auf Ihrem Layout erhalten wird. Dadurch werden potenzielle Probleme bei der Auflösung des Bilds vermieden, wenn die Größe in Prozent geändert wird. Wenn Sie beispielsweise ein Seitenverhältnis von 3: 2 beibehalten möchten, verwenden Sie nicht nur ein 3 x 2 Pixel großes Bild. Es kann unter bestimmten Umständen funktionieren, aber ich habe es nicht getestet, und es wäre wahrscheinlich eine gute Idee, dies zu vermeiden.

Sie sollten wahrscheinlich bereits eine Mindestbreite wie diese für flüssige Elemente Ihrer Website definiert haben. Wenn nicht, ist es eine gute Idee, dies zu tun, um zu vermeiden, dass Elemente abgeschnitten werden oder sich überlappen, wenn das Browserfenster zu klein wird. Es ist besser, irgendwann eine Bildlaufleiste zu haben. Die kleinste Breite, die eine Webseite erhalten sollte, liegt bei etwa 600 Pixel (einschließlich Spalten mit fester Breite), da die Bildschirmauflösungen nur dann kleiner werden, wenn Sie mit telefonfreundlichen Websites arbeiten. !!!

Ich verwende ein vollständig transparentes PNG, aber ich denke nicht, dass es wichtig ist, wenn Sie es richtig machen. So was:

<div class="video">
     <img class="maintainaspectratio" src="maintainaspectratio.png" />
     <object>
          <param ... /><param ... />...
          <embed src="..." ...</embed>
     </object>
</div>

Jetzt sollten Sie in der Lage sein, CSS ähnlich dem folgenden hinzuzufügen:

div.video { ...; position: relative; }
div.video img.maintainaspectratio { width: 100%; }
div.video object { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; }
div.video embed {width: 100%; height: 100%; }

Stellen Sie sicher, dass Sie auch alle expliziten Höhen- oder Breitendeklarationen innerhalb des Objekts entfernen und Tags einbetten, die normalerweise mit kopiertem / eingefügtem Einbettungscode geliefert werden.

Die Funktionsweise hängt von den Positionseigenschaften des Videoklassenelements ab, und das gewünschte Element hat ein bestimmtes Seitenverhältnis. Es nutzt die Art und Weise, wie ein Bild sein korrektes Seitenverhältnis beibehält, wenn die Größe in einem Element geändert wird. Es weist an, was sich sonst noch im Videoklassenelement befindet, um die durch das dynamische Bild bereitgestellte Fläche voll auszunutzen, indem seine Breite / Höhe auf 100% des vom Bild angepassten Videoklassenelements erzwungen wird.

Ziemlich cool, oder?

Möglicherweise müssen Sie ein wenig damit herumspielen, damit es mit Ihrem eigenen Design funktioniert, aber das funktioniert für mich überraschend gut. Das allgemeine Konzept ist da.


17

Elliot hat mich zu dieser Lösung inspiriert - danke:

aspectratio.png ist eine vollständig transparente PNG-Datei mit der Größe Ihres bevorzugten Seitenverhältnisses, in meinem Fall 30x10 Pixel.

HTML

<div class="eyecatcher">
  <img src="/img/aspectratio.png"/>
</div>

CSS3

.eyecatcher img {
  width: 100%;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-image: url(../img/autoresized-picture.jpg);
}

Bitte beachten Sie: background-size ist eine CSS3-Funktion, die möglicherweise nicht mit Ihren Zielbrowsern funktioniert. Sie können die Interoperabilität überprüfen ( z . B. auf caniuse.com ).


14

Um die Antwort von Web_Designer zu ergänzen, hat der <div>eine Höhe (die vollständig aus der unteren Polsterung besteht) von 75% der Breite des enthaltenen Elements . Hier ist eine gute Zusammenfassung: http://mattsnider.com/css-using-percent-for-margin-and-padding/ . Ich bin mir nicht sicher, warum das so sein sollte, aber so ist es.

Wenn Sie möchten, dass Ihr Div eine andere Breite als 100% hat, benötigen Sie ein anderes Wrapping-Div, auf dem Sie die Breite festlegen können:

div.ar-outer{
    width: 60%; /* container; whatever width you want */
    margin: 0 auto; /* centered if you like */
}
div.ar {
    width:100%; /* 100% of width of container */
    padding-bottom: 75%; /* 75% of width of container */
    position:relative;
}
div.ar-inner {
    position: absolute;
    top: 0; bottom: 0; left: 0; right: 0;
}

Ich habe kürzlich etwas Ähnliches wie Elliots Bildtrick verwendet, um CSS-Medienabfragen zu verwenden, um je nach Geräteauflösung eine andere Logodatei bereitzustellen, aber trotzdem proportional zu skalieren, wie <img>es natürlich der Fall wäre (ich habe das Logo als Hintergrundbild auf eine transparente PNG- Datei gesetzt mit dem richtigen Seitenverhältnis). Die Lösung von Web_Designer würde mir jedoch eine http-Anfrage ersparen.


Tolle Lösung. In meinem Fall kenne ich die "natürliche" Bildgröße, wenn ich sie in DOM platziere, und ich benötige einen Platzhalter für Bilder mit der richtigen Höhe, um ein weiteres Scrollen zu verhindern, sobald der Browser die Bilder lädt. In .ar-Outer habe ich die Bildbreite in Pixel, in .ar habe ich Padding-Bottom, berechnet aus dem realen Bildseitenverhältnis. Anstelle von ar-inner habe ich das Bild selbst (<img>). Ich musste jedoch die Breite auf 100% einstellen, anstatt oben, unten, links und rechts. Wenn ich maxWidth auf ar-äußere setze, wird das Bild gut skaliert, wenn das übergeordnete Element klein ist, aber nicht größer als seine natürliche Größe.
Mi-La

13

Wie hier auf w3schools.com angegeben und in dieser akzeptierten Antwort etwas wiederholt , werden die Werte als Prozentsätze aufgefüllt (Hervorhebung von mir):

Gibt den Abstand in Prozent der Breite des enthaltenen Elements an

Ergo ist ein korrektes Beispiel für ein responsives DIV, das ein Seitenverhältnis von 16: 9 beibehält, wie folgt:

CSS

.parent {
    position: relative;
    width: 100%;
}
.child {
    position: relative;
    padding-bottom: calc(100% * 9 / 16);
}
.child > div {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}

HTML

<div class="parent">
    <div class="child">
        <div>Aspect is kept when resizing</div>
    </div>
</div>

Demo auf JSFiddle


13

Da @ web-tiki bereits eine Möglichkeit zur Verwendung von vh/ zeigt vw, brauche ich auch eine Möglichkeit, den Bildschirm zu zentrieren . Hier ist ein Snippet-Code für das 9: 16- Porträt.

.container {
  width: 100vw;
  height: calc(100vw * 16 / 9);
  transform: translateY(calc((100vw * 16 / 9 - 100vh) / -2));
}

translateYbehält diese Mitte auf dem Bildschirm. calc(100vw * 16 / 9)wird Höhe für 9/16 erwartet. (100vw * 16 / 9 - 100vh)Wenn die Überlaufhöhe beträgt, overflow height/2bleibt sie beim Hochziehen mittig auf dem Bildschirm.

Für Landschaft und 16: 9 zeigen Sie Verwendung

.container {
  width: 100vw;
  height: calc(100vw * 9 / 16);
  transform: translateY(calc((100vw * 9 / 16 - 100vh) / -2));
}

Das Verhältnis 9/16 ist leicht zu ändern, muss nicht vordefiniert werden 100:56.25oder. 100:75Wenn Sie zuerst die Höhe sicherstellen möchten, sollten Sie Breite und Höhe wechseln, z height:100vh;width: calc(100vh * 9 / 16). B. für 9:16 Porträt.

Wenn Sie für unterschiedliche Bildschirmgrößen angepasst werden möchten, könnten Sie auch interessiert sein

  • Hintergrundgröße Abdeckung / enthalten
    • Der obige Stil ist ähnlich zu enthalten, hängt vom Verhältnis von Breite zu Höhe ab.
  • Objektanpassung
    • cover / enthalten für img / video tag
  • @media (orientation: portrait)/.@media (orientation: landscape)
    • Medienabfrage für portrait/ landscapezum Ändern des Verhältnisses.

11

Dies ist eine Verbesserung gegenüber der akzeptierten Antwort:

  • Verwendet Pseudoelemente anstelle von Wrapper-Divs
  • Das Seitenverhältnis basiert auf der Breite des Felds anstelle des übergeordneten Felds
  • Das Feld wird vertikal gedehnt, wenn der Inhalt größer wird

.box {
  margin-top: 1em;
  margin-bottom: 1em;
  background-color: #CCC;
}

.fixed-ar::before {
  content: "";
  float: left;
  width: 1px;
  margin-left: -1px;
}
.fixed-ar::after {
  content: "";
  display: table;
  clear: both;
}

.fixed-ar-16-9::before {
  padding-top: 56.25%;
}
.fixed-ar-3-2::before {
  padding-top: 66.66%;
}
.fixed-ar-4-3::before {
  padding-top: 75%;
}
.fixed-ar-1-1::before {
  padding-top: 100%;
}

.width-50 {
  display: inline-block;
  width: 50%;
}
.width-20 {
  display: inline-block;
  width: 20%;
}
<div class="box fixed-ar fixed-ar-16-9">16:9 full width</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-50">16:9</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-20">16:9</div>
<div class="box fixed-ar fixed-ar-3-2 width-20">3:2</div>
<div class="box fixed-ar fixed-ar-4-3 width-20">4:3</div>
<div class="box fixed-ar fixed-ar-1-1 width-20">1:1</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-20">16:9</div>
<div class="box fixed-ar fixed-ar-16-9 width-50">16:9</div>


Wie deaktiviere ich die vertikale Dehnung der Box? Genau genommen behält ein Stretching Div sein Seitenverhältnis nicht bei
Florian

Wenn der Inhalt größer als die erwartete Höhe ist, wird die Box vertikal gedehnt. Diese Idee eignet sich am besten für Inhalte, die sich an die Dimensionen der Eltern anpassen lassen, z. B. Videos und Bilder.
Salman A

10

Ich bin auf eine intelligente Lösung mit <svg>und gestoßen display:grid.

Mit dem Rasterelement können Sie denselben Raum mit zwei (oder mehr) Elementen belegen, ohne angeben zu müssen, welches die Höhe festlegt. Was bedeutet, dass sofort das größere Verhältnis festgelegt wird .

Dies bedeutet, dass Sie es so verwenden können, wie es ist, wenn Sie wissen, dass der Inhalt niemals groß genug sein wird, um das gesamte "Verhältnis" auszufüllen, und Sie einfach nach einer Möglichkeit suchen, den Inhalt in diesem Bereich zu positionieren (dh ihn in beide Richtungen zu zentrieren) display:flex; align-items:center; justify-content:center ).
Es ist so ziemlich das Gleiche wie die Verwendung eines transparenten Verhältnisses <img>mit display:blockund eines vorgegebenen Verhältnisses, außer dass das Verhältnis <svg>leichter und wesentlich einfacher zu ändern ist (um das Verhältnis bei Bedarf entsprechend zu ändern).

<div class="ratio">
  <svg viewBox="0 0 1 1"></svg>
  <div>
    I'm square
  </div>
</div>
.ratio {
  display: grid;
}
.ratio > * {
  grid-area: 1/1/1/1;
}

Alles was Sie tun müssen, ist das zu ändern <svg> s-Verhältnis :

  • <svg viewBox="0 0 4 3"></svg>
  • <svg viewBox="0 0 16 9"></svg>

Sehen Sie, wie es funktioniert:


Wenn Sie eine Lösung benötigen, bei der das Inhaltselement das Verhältnis nicht festlegen darf, wenn es größer ist (mit ausgeblendetem oder automatischem Überlauf), müssen Sie festlegen position:relative im Raster und position:absolute; height:100%; overflow-y: auto;im Inhalt . Beispiel:


9

Basierend auf Ihren Lösungen habe ich einen Trick gemacht:

Wenn Sie es verwenden, wird nur Ihr HTML sein

<div data-keep-ratio="75%">
    <div>Main content</div>
</div>

Um es auf diese Weise zu verwenden, machen Sie: CSS:

*[data-keep-ratio] {
    display: block;
    width: 100%;
    position: relative;
}
*[data-keep-ratio] > * {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
}

und js (jQuery)

$('*[data-keep-ratio]').each(function(){ 
    var ratio = $(this).data('keep-ratio');
    $(this).css('padding-bottom', ratio);
});

Und wenn Sie dies haben, setzen Sie attr einfach data-keep-ratioauf Höhe / Breite und das wars .


3
Sie sollten data-keep-rationicht verwenden keep-ratiound seinen Wert erhalten mit$(this).data('keep-ratio');
Robert

Ihr Code funktioniert jetzt und wird vielleicht für immer funktionieren, aber er ist nicht Standard und Browser unterstützen ihn möglicherweise in Zukunft nicht mehr
Robert

1
Die Verwendung von JS hier wird schlechte Nachrichten verursachen!
Amir Hossein Ahmadi

8

Sie können ein SVG verwenden. Machen Sie die Position des Containers / Wrappers relativ, setzen Sie das SVG zuerst als statisch positioniert und dann als absolut positionierten Inhalt (oben: 0; links: 0; rechts: 0; unten: 0;)

Beispiel mit 16: 9 Proportionen:

image.svg: (kann in src eingefügt werden)

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 9" width="16" height="9"/>

CSS:

.container {
  position: relative;
}
.content {
  position: absolute;
  top:0; left:0; right:0; bottom:0;
}

HTML:

<div class="container">
  <img style="width: 100%" src="image.svg" />
  <div class="content"></div>
</div>

Beachten Sie, dass Inline-SVG anscheinend nicht funktioniert. Sie können das SVG jedoch urlencodieren und wie folgt in das Attribut img src einbetten:

<img src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2016%209%22%20width%3D%2216%22%20height%3D%229%22%2F%3E" style="width: 100%;" />

7

SCSS ist in meinem Fall die beste Lösung. Verwenden eines Datenattributs:

[data-aspect-ratio] {
    display: block;
    max-width: 100%;
    position: relative;

    &:before {
        content: '';
        display: block;
    }

    > * {
        display: block;
        height: 100%;
        left: 0;
        position: absolute;
        top: 0;
        width: 100%;
    }
}
[data-aspect-ratio="3:1"]:before {
    padding-top: 33.33%;
}
[data-aspect-ratio="2:1"]:before {
    padding-top: 50%;
}
[data-aspect-ratio="16:9"]:before {
    padding-top: 56.25%;
}
[data-aspect-ratio="3:2"]:before {
    padding-top: 66.66%;
}
[data-aspect-ratio="4:3"]:before {
    padding-top: 75%;
}
[data-aspect-ratio="1:1"]:before {
    padding-top: 100%;
}
[data-aspect-ratio="3:4"]:before {
    padding-top: 133.33%;
}
[data-aspect-ratio="2:3"]:before {
    padding-top: 150%;
}
[data-aspect-ratio="9:16"]:before {
    padding-top: 177.77%;
}
[data-aspect-ratio="1:2"]:before {
    padding-top: 200%;
}
[data-aspect-ratio="1:3"]:before {
    padding-top: 300%;
}

Beispielsweise :

<div data-aspect-ratio="16:9"><iframe ...></iframe></div>

Quelle


15
Nur zu Ihrer Information ... Sie können genau das (mit Attributselektoren) in genau der gleichen Anzahl von Zeilen mit einfachem CSS tun. Die [data-aspect-ratio]Attributauswahl steht Ihnen in CSS zur Verfügung.
Rnevius

6

Während die meisten Antworten sehr cool sind, müssen die meisten ein Bild haben, das bereits die richtige Größe hat ... Andere Lösungen funktionieren nur für eine Breite und kümmern sich nicht um die verfügbare Höhe, aber manchmal möchten Sie den Inhalt auch in eine bestimmte Höhe einpassen .

Ich habe versucht, sie miteinander zu koppeln, um eine vollständig portable und anpassbare Lösung zu erhalten ... Der Trick besteht darin, ein Bild automatisch zu skalieren, aber ein Inline-SVG-Element zu verwenden, anstatt ein vorgerendertes Bild oder eine andere Form von zu verwenden zweite HTTP-Anfrage ...

div.holder{
  background-color:red;
  display:inline-block;
  height:100px;
  width:400px;
}
svg, img{
  background-color:blue;
  display:block;
  height:auto;
  width:auto;
  max-width:100%;
  max-height:100%;
}
.content_sizer{
  position:relative;
  display:inline-block;
  height:100%;
}
.content{
  position:absolute;
  top:0;
  bottom:0;
  left:0;
  right:0;
  background-color:rgba(155,255,0,0.5);
}
<div class="holder">
  <div class="content_sizer">
    <svg width=10000 height=5000 />
    <div class="content">
    </div>
  </div>
</div>

Beachten Sie, dass ich große Werte in den Attributen width und height des SVG verwendet habe, da es größer sein muss als die maximal erwartete Größe, da es nur schrumpfen kann. Das Beispiel macht das Div-Verhältnis 10: 5


4

Nur eine Idee oder ein Hack.

div {
  background-color: blue;
  width: 10%;
  transition: background-color 0.5s, width 0.5s;
  font-size: 0;
}

div:hover {
  width: 20%;
  background-color: red;
}
  
img {
  width: 100%;
  height: auto;
  visibility: hidden;
}
<div>
  <!-- use an image with target aspect ratio. sample is a square -->
  <img src="http://i.imgur.com/9OPnZNk.png" />
</div>


Dies ist keine reine CSS-Lösung ... Wenn Sie ein Base64-codiertes Bild in einem Pseudoelement verwendet hätten, wäre dies eine coole Lösung gewesen.
Rnevius

1
Es gibt wirklich keine reine CSS-Lösung. HTML ist die Grundkomponente des Web. Ich glaube, der Zweck der Frage ist es, JS nicht zu verwenden, um möglicherweise Ressourcen / Verarbeitung zu sparen.
Orlland

Ich bin nicht sicher, ob Pseudoelement funktionieren wird. Ich habe die Eigenschaft von img element genutzt, um das Seitenverhältnis beizubehalten, damit diese Lösung funktioniert.
Orlland

Schön, aber es berechnet eine Höhe nur, wenn sich die Breite ändert. Es sollte in beide Richtungen gehen. Wenn ich also die Höhe reduziere, wird auch die Breite neu berechnet. Sonst ist es nutzlos ..
Ωmega

4

Nehmen wir an, Sie haben 2 Divs. Das äußere Div ist ein Container und das innere könnte ein beliebiges Element sein, das Sie benötigen, um sein Verhältnis beizubehalten (img oder ein Youtube-Iframe oder was auch immer).

HTML sieht so aus:

<div class='container'>
  <div class='element'>
  </div><!-- end of element -->

Angenommen, Sie müssen das Verhältnis des "Elements" beibehalten.

Verhältnis => 4 zu 1 oder 2 zu 1 ...

CSS sieht so aus

.container{
  position: relative;
  height: 0
  padding-bottom : 75% /* for 4 to 3 ratio */ 25% /* for 4 to 1 ratio ..*/

}

.element{
  width : 100%;
  height: 100%;
  position: absolute; 
  top : 0 ;
  bottom : 0 ;
  background : red; /* just for illustration */
}

Auffüllen, wenn in% angegeben, wird es basierend auf der Breite und nicht auf der Höhe berechnet. .. also im Grunde ist es dir egal, wie breit deine Höhe ist, es wird immer basierend darauf berechnet. das wird das Verhältnis halten.


4

Wenn Sie ein Quadrat in das Ansichtsfenster im Hoch- oder Querformat einfügen möchten (so groß wie möglich, aber nichts bleibt außen), wechseln Sie zwischen vw/ vhon Ausrichtung portrait/ landscape:

@media (orientation:portrait ) {
  .square {
    width :100vw;
    height:100vw;
  }
} 
@media (orientation:landscape) {
  .square {
    width :100vh;
    height:100vh;
  }
} 

4

Ich möchte meine Lösung teilen, bei der ein imgTag ein bestimmtes Seitenverhältnis ausfüllt. Ich konnte es backgroundwegen mangelnder Unterstützung des CMS nicht verwenden und würde es nicht vorziehen, ein Style-Tag wie das folgende zu verwenden : <img style="background:url(...)" />. Außerdem beträgt die Breite 100%, sodass sie nicht wie bei einigen Lösungen auf eine feste Größe eingestellt werden muss. Es wird reaktionsschnell skaliert!

.wrapper {
  width: 50%;
}

.image-container {
  position: relative;
  width: 100%;
}

.image-container::before {
  content: "";
  display: block;
}

.image-container img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.ratio-4-3::before {
  padding-top: 75%;
}

.ratio-3-1::before {
  padding-top: calc(100% / 3);
}

.ratio-2-1::before {
  padding-top: 50%;
}
<div class="wrapper"> <!-- Just to make things a bit smaller -->
  <p>
  Example of an 4:3 aspect ratio, filled by an image with an 1:1 ratio.
  </p>
  <div class="image-container ratio-4-3"> <!-- Lets go for a 4:3 aspect ratio -->
    <img src="https://placekitten.com/1000/1000/" alt="Kittens!" />
  </div>
  <p>
  Just place other block elements around it; it will work just fine.
  </p>
</div>


3

Ich bin schon einige Male auf dieses Problem gestoßen, deshalb habe ich eine JS-Lösung dafür entwickelt. Dadurch wird die Höhe des domElement grundsätzlich entsprechend der Breite des Elements um das von Ihnen angegebene Verhältnis angepasst. Sie können es wie folgt verwenden:

<div ratio="4x3"></div>

Bitte beachten Sie, dass das Element entweder ein display:blockoder sein sollte, da es die Höhe des Elements festlegt display:inline-block.

https://github.com/JeffreyArts/html-ratio-component


1
Obwohl ich Ihren Code nicht gesehen oder ausprobiert habe (ich habe bereits meinen eigenen), habe ich Ihre Antwort nur deshalb positiv bewertet, weil Sie die einzige zuverlässige Lösung präsentieren, ein JS-Skript.
Theo d'Or

In der Frage wurde speziell nach einer Lösung gefragt, für die kein Javascript erforderlich war.
Flimm

2

Sie können dies mit SVG erreichen.

Es hängt von einem Fall ab, aber in einigen ist es wirklich nützlich. Als Beispiel - Sie können festlegen, background-imageohne eine feste Höhe festzulegen, oder es verwenden, um YouTube <iframe>mit Verhältnis 16:9und einzubettenposition:absolute usw.

Für 3:2Verhältnis eingestelltviewBox="0 0 3 2" und so weiter.

Beispiel:

div{
    background-color:red
}
svg{
    width:100%;
    display:block;
    visibility:hidden
}

.demo-1{width:35%}
.demo-2{width:20%}
<div class="demo-1">
  <svg viewBox="0 0 3 2"></svg>
</div>

<hr>

<div class="demo-2">
  <svg viewBox="0 0 3 2"></svg>
</div>


2

Angenommen, Sie möchten die Breite: 100px und die Höhe: 50px (dh 2: 1) beibehalten. Führen Sie einfach folgende Berechnungen durch:

.pb-2to1 {
  padding-bottom: calc(50 / 100 * 100%); // i.e., 2:1
}


1

Eine einfache Möglichkeit, das Seitenverhältnis mithilfe des Canvas-Elements beizubehalten.

Versuchen Sie, die Größe des Div unten zu ändern, um es in Aktion zu sehen.

Für mich hat dieser Ansatz am besten funktioniert, daher teile ich ihn mit anderen, damit auch sie davon profitieren können.

.cont {
  border: 5px solid blue;
  position: relative;
  width: 300px;
  padding: 0;
  margin: 5px;
  resize: horizontal;
  overflow: hidden;
}

.ratio {
  width: 100%;
  margin: 0;
  display: block;
}

.content {
  background-color: rgba(255, 0, 0, 0.5);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  margin: 0;
}
<div class="cont">
  <canvas class="ratio" width="16" height="9"></canvas>
  <div class="content">I am 16:9</div>
</div>

Funktioniert auch mit dynamischer Höhe!

.cont {
  border: 5px solid blue;
  position: relative;
  height: 170px;
  padding: 0;
  margin: 5px;
  resize: vertical;
  overflow: hidden;
  display: inline-block; /* so the div doesn't automatically expand to max width */
}

.ratio {
  height: 100%;
  margin: 0;
  display: block;
}

.content {
  background-color: rgba(255, 0, 0, 0.5);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  margin: 0;
}
<div class="cont">
  <canvas class="ratio" width="16" height="9"></canvas>
  <div class="content">I am 16:9</div>
</div>


yup hat mir geholfen, ich kann es jetzt verwenden, um die Höhe der übergeordneten Bild-Divs einzurichten
Alex

0

Ich habe eine neue Lösung verwendet.

.squares{
  width: 30vw
  height: 30vw

Zum Hauptseitenverhältnis

.aspect-ratio
  width: 10vw
  height: 10vh

Dies bezieht sich jedoch auf das gesamte Ansichtsfenster. Wenn Sie also ein Div benötigen, das 30% der Breite des Ansichtsfensters beträgt, können Sie stattdessen 30vw verwenden. Da Sie die Breite kennen, können Sie sie in der Höhe mit calc und vw wiederverwenden.


7
Ist das nicht genau das, was die zweithöchste Antwort bereits umrissen hat?
Rnevius


-4

Wenn die gesamte Container-Struktur prozentual wäre, wäre dies das Standardverhalten. Können Sie ein spezifischeres Beispiel angeben?

Im Folgenden finden Sie ein Beispiel dafür, was ich meine: Wenn Ihre gesamte übergeordnete Hierarchie auf% basiert, würde jede Anpassung des Browserfensters ohne zusätzliche JS / CSS funktionieren. Ist dies bei Ihrem Layout nicht möglich?

<div style="width: 100%;">
   <div style="width: 50%; margin: 0 auto;">Content</div>
</div>

1
Siehe meine Bearbeitung der ursprünglichen Frage. Ich sehe nicht, wo diese Technik das Seitenverhältnis halten würde, die Höhe würde sich nicht ändern.
Jackb
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.