Mantieni le proporzioni di un div con CSS


1059

Voglio creare un divche può cambiare la sua larghezza / altezza man mano che cambia la larghezza della finestra.

Esistono regole CSS3 che consentirebbero di modificare l'altezza in base alla larghezza, pur mantenendo le proporzioni ?

So che posso farlo tramite JavaScript, ma preferirei usare solo CSS.

div mantenendo le proporzioni in base alla larghezza della finestra


3
Ho scritto su diversi approcci a questo nel mio articolo CSS-Tricks sul ridimensionamento delle animazioni reattive
Zach Saucier,

2
Sono arrivato a queste domande e risposte molto tardi, ma devo commentare. Sebbene sia molto disciplinato e all'interno delle regole SO di tutti coloro che rispondono per fare del loro meglio per soddisfare la domanda "solo CSS" della domanda, è abbastanza sorprendente che, ad eccezione della risposta dell'utente007 in basso nella pagina, no- uno ha menzionato l'ovvio: non esiste una soluzione affidabile solo per CSS, questo problema richiede Javascript. Un principiante che arriva su questa pagina potrebbe perdere tempo prezioso passando da una serie di pro / contro a un'altra prima che la lampadina si spenga: solo CSS non lo farà.
Theo d'Or,

1
Ho scritto un piccolo strumento che semplifica l'anteprima e il calcolo delle proporzioni, aspectrat.io . Genera anche il codice CSS / Sass / Less appropriato che puoi copiare e incollare nei tuoi progetti. Spero che le persone lo trovino utile.
Ryan Hefner

vedi questo esempio: w3schools.com/howto/howto_css_aspect_ratio.asp ..... che mi ha funzionato
Cristian Agudelo,

1
Questa domanda è per impostare l' altezza in base alla larghezza . Se hai bisogno del contrario, controlla Impostazione della larghezza dell'elemento in base all'altezza tramite CSS .
John Mellor,

Risposte:


1353

Basta creare un wrapper <div>con un valore percentuale per padding-bottom, in questo modo:

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>

Ne risulterà <div>un'altezza pari al 75% della larghezza del suo contenitore (un rapporto di aspetto 4: 3).

Ciò si basa sul fatto che per l'imbottitura:

La percentuale viene calcolata rispetto alla larghezza del blocco contenente la casella generata [...] (fonte: w3.org , enfasi mia)

Valori di riempimento inferiore per altri rapporti d'aspetto e larghezza del 100%:

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

Posizionamento del contenuto nel div:

Al fine di mantenere le proporzioni del div e impedire che il suo contenuto si estenda, è necessario aggiungere un bambino assolutamente posizionato e allungarlo ai bordi dell'involucro con:

div.stretchy-wrapper {
  position: relative;
}

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

Ecco una demo e un altro più in profondità demo


29
@schellmax, è perché il padding% viene calcolato in relazione alla larghezza dell'elemento corrente, dove come l'altezza% viene calcolata in relazione all'altezza dell'elemento padre. Inoltre, le posizioni assolute vengono calcolate in relazione al contenitore esterno di un elemento, che include l'area di imbottitura. Per ulteriori informazioni "CSS Box Model Model" di Google
Anson Kao,

11
Questo non sembra funzionare in modo nidificato. Funziona al primo livello, ma quando si tenta di fare la stessa cosa all'interno del div mantenendo le proporzioni, la percentuale di riempimento inferiore sembra essere applicata alla larghezza del genitore. ecco un esempio in cui .stretchy-wrap.onethird padding-bottom del 25% è in realtà il 25% della larghezza del genitore. Qualcuno può spiegare questo?
Misterparker,

4
Assolutamente fantastico. Mi sta uccidendo che questa tecnica non funzionerà quando vuoi fissare l'altezza al 100%. @Misterparker, la tecnica si basa sui calcoli di larghezza e imbottitura eseguiti sullo stesso riferimento; non puoi usare una larghezza inferiore al 100%, come nel tuo esempio.
Steveluscher,

2
@Misterparker Sì, la percentuale di riempimento viene calcolata in proporzione alla larghezza dell'elemento principale. Vedi l'esempio più approfondito che ho pubblicato in una modifica alla mia risposta. La mia demo aggiornata dimostra una "moda nidificata" di cui parlavi.
Web_Designer,

3
il fatto che abbia dimostrato che questo funziona è abbastanza per convincermi che questa è la migliore risposta che abbia mai visto su SO. urla al mio uomo @Web_Designer

410

vw unità:

Puoi usare le vwunità sia per la larghezza che per l'altezza dell'elemento. Ciò consente di preservare le proporzioni dell'elemento, in base alla larghezza della finestra.

vw: 1/100 della larghezza della finestra. [ MDN ]

In alternativa, è possibile utilizzare anche vhper l'altezza della finestra o anche vmin/ vmaxper utilizzare le dimensioni minore / maggiore della finestra (discussione qui ).

Esempio: proporzioni 1: 1

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

Per altri rapporti di formato, è possibile utilizzare la tabella seguente per calcolare il valore per l'altezza in base alla larghezza dell'elemento:

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

Esempio: griglia 4x4 di div quadrati

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>

Ecco un violino con questa demo ed ecco una soluzione per creare una griglia reattiva di quadrati con contenuto centrato verticalmente e orizzontalmente .


Il supporto del browser per le unità vh / vw è IE9 + vedi canIuse per maggiori informazioni


14
Questa dovrebbe essere la risposta accettata. Forse non ora, ma in futuro. le unità vw sono ora supportate nella maggior parte dei browser .
Agosto

3
@vivekmaharajh entrambe le tecniche sono buone, ognuna ha i suoi pro e contro. L'uso dell'uno o dell'altro dipende molto dalla situazione.
web-tiki,

11
@ web-tiki, hai ragione. Ho riscontrato un problema: si presume che la larghezza dell'elemento sia proporzionale alla larghezza del viewport, il che non avverrà se 1) hai cose come grondaie a larghezza fissa o 2) hai impostato la larghezza massima per alcuni dei tuoi elementi.
Vivek Maharajh,

1
Forse è solo Chrome v47beta, ma quando imposto il div su width:50%e height:50vwl'altezza è un po 'più alta della larghezza, quindi non esattamente una proporzione 1: 1. Qualche idea?
thdoan

2
@ 10basetom è un comportamento normale. le unità vw contengono la larghezza della barra di scorrimento mentre% width no. La differenza tra altezza e larghezza dipenderà dalla dimensione della barra di scorrimento che varia in base al browser.
web-tiki,

26

Ho trovato un modo per farlo usando i CSS, ma devi stare attento perché potrebbe cambiare a seconda del flusso del tuo sito web. L'ho fatto per incorporare video con proporzioni costanti all'interno di una porzione di larghezza fluida del mio sito web.

Supponi di avere un video incorporato come questo:

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

È quindi possibile inserire tutto questo all'interno di un div con una classe "video". Questa classe video sarà probabilmente l'elemento fluido nel tuo sito Web in modo tale che, di per sé, non abbia vincoli di altezza diretti, ma quando ridimensioni il browser cambierà in larghezza in base al flusso del sito web. Questo sarebbe l'elemento che probabilmente stai cercando di ottenere il tuo video incorporato mantenendo un certo rapporto di aspetto del video.

Per fare ciò, ho inserito un'immagine prima dell'oggetto incorporato all'interno della classe div "video".

!!! La parte importante è che l'immagine ha le proporzioni corrette che desideri mantenere. Inoltre, assicurati che la dimensione dell'immagine sia ALMENO grande quanto la più piccola che ti aspetti che il video (o qualunque cosa tu stia mantenendo l'AR) sia basata sul layout. Ciò eviterà qualsiasi potenziale problema nella risoluzione dell'immagine quando viene ridimensionata in percentuale. Ad esempio, se si desidera mantenere un rapporto di formato di 3: 2, non utilizzare solo un'immagine 3px per 2px. Potrebbe funzionare in alcune circostanze, ma non l'ho testato e probabilmente sarebbe una buona idea evitare.

Probabilmente dovresti già avere una larghezza minima come questa definita per gli elementi fluidi del tuo sito web. Altrimenti, è una buona idea farlo al fine di evitare di tagliare elementi o di sovrapporsi quando la finestra del browser diventa troppo piccola. È meglio avere una barra di scorrimento ad un certo punto. La larghezza minima che una pagina Web dovrebbe ottenere è di circa 600px (comprese eventuali colonne a larghezza fissa) perché le risoluzioni dello schermo non diminuiscono a meno che non si tratti di siti adatti al telefono. !!!

Uso un png completamente trasparente ma non credo davvero che finisca per importare se lo fai nel modo giusto. Come questo:

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

Ora dovresti essere in grado di aggiungere CSS simili ai seguenti:

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%; }

Assicurati anche di rimuovere qualsiasi dichiarazione esplicita di altezza o larghezza all'interno dell'oggetto e di incorporare i tag che di solito vengono forniti con il codice di incorporamento copia / incolla.

Il modo in cui funziona dipende dalle proprietà di posizione dell'elemento della classe video e l'elemento desiderato deve mantenere un determinato formato. Sfrutta il modo in cui un'immagine manterrà le proporzioni corrette quando viene ridimensionata in un elemento. Indica a tutti gli altri elementi della classe video di sfruttare appieno il patrimonio immobiliare fornito dall'immagine dinamica forzando la sua larghezza / altezza al 100% dell'elemento della classe video che viene regolato dall'immagine.

Abbastanza bello, eh?

Potrebbe essere necessario giocarci un po 'per farlo funzionare con il tuo design, ma in realtà funziona sorprendentemente bene per me. Il concetto generale è lì.


17

Elliot mi ha ispirato a questa soluzione - grazie:

aspectratio.png è un file PNG completamente trasparente con le dimensioni del tuo formato preferito, nel mio caso 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);
}

Nota: background-size è una funzione css3 che potrebbe non funzionare con i browser di destinazione. È possibile verificare l'interoperabilità (ad esempio su caniuse.com ).


14

Per aggiungere alla risposta di Web_Designer, l' <div>altezza (interamente costituita dall'imbottitura inferiore) sarà del 75% della larghezza del suo elemento contenente . Ecco un buon riassunto: http://mattsnider.com/css-using-percent-for-margin-and-padding/ . Non sono sicuro del motivo per cui dovrebbe essere così, ma è così.

Se vuoi che il tuo div sia una larghezza diversa dal 100%, hai bisogno di un altro div avvolgente su cui impostare la larghezza:

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

Di recente ho usato qualcosa di simile al trucco dell'immagine di Elliot per consentirmi di utilizzare query multimediali CSS per servire un file logo diverso a seconda della risoluzione del dispositivo, ma comunque ridimensionare proporzionalmente come <img>farebbe naturalmente (ho impostato il logo come immagine di sfondo su un .png trasparente con le proporzioni corrette). Ma la soluzione di Web_Designer mi farebbe risparmiare una richiesta http.


Ottima soluzione Nel mio caso, conosco la dimensione "naturale" dell'immagine quando la posiziono su DOM e ho bisogno di un segnaposto immagine con altezza adeguata per impedire un ulteriore scorrimento quando il browser carica le immagini. In .ar-outer ho la larghezza dell'immagine in pixel, in .ar ho il padding-bottom calcolato dalle proporzioni dell'immagine reale. Invece di ar-inner ho l'immagine stessa (<img>). Tuttavia, ho dovuto impostare la larghezza al 100% invece di impostare in alto, in basso, a sinistra e a destra. Quando imposto maxWidth su ar-outer, l'immagine si ridimensiona bene quando il genitore è piccolo, ma non si ridimensiona a una dimensione maggiore rispetto alla sua dimensione naturale.
Mi-La

13

Come indicato qui su w3schools.com e in qualche modo ripetuto in questa risposta accettata , inserendo i valori in percentuale (sottolineatura mia):

Specifica il riempimento in percentuale della larghezza dell'elemento contenitore

Ergo, un esempio corretto di un DIV reattivo che mantiene le proporzioni 16: 9 è il seguente:

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 su JSFiddle


13

Dato che @ web-tiki mostra già un modo di usare vh/ vw, ho anche bisogno di un modo per centrare lo schermo, ecco un codice snippet per il ritratto 9:16 .

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

translateYmanterrà questo centro sullo schermo. calc(100vw * 16 / 9)è prevista altezza per 9/16. (100vw * 16 / 9 - 100vh)è un'altezza di troppo pieno, quindi, tirare su overflow height/2lo manterrà al centro sullo schermo.

Per il paesaggio e mantieni 16: 9 , mostri l'uso

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

Il rapporto 9/16 è facile da modificare, non è necessario il valore predefinito 100:56.25o 100:75. Se si desidera garantire prima l'altezza, è necessario cambiare larghezza e altezza, ad esempio height:100vh;width: calc(100vh * 9 / 16)per il ritratto 9:16.

Se desideri adattarti a dimensioni dello schermo diverse, potresti anche interessarti

  • copertina di dimensioni dello sfondo / contenere
    • Lo stile sopra è simile a contenere, dipende dalla larghezza: rapporto altezza.
  • oggetto-fit
    • copertina / contiene per tag img / video
  • @media (orientation: portrait)/@media (orientation: landscape)
    • Media query per portrait/ landscapeper modificare il rapporto.

11

Questo è un miglioramento sulla risposta accettata:

  • Utilizza pseudo elementi invece di div wrapper
  • Le proporzioni si basano sulla larghezza della casella anziché sul suo genitore
  • La casella si allungherà verticalmente quando il contenuto diventa più alto

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


come disabilitare l'allungamento verticale della scatola? a rigor di termini un div stretching non mantiene le sue proporzioni
Florian,

Se il contenuto è più alto dell'altezza prevista, la casella si allungherà verticalmente. Questa idea viene utilizzata al meglio con contenuti che potrebbero estendersi per adattarsi alle dimensioni dei genitori, ad esempio video e immagini.
Salman A

10

Mi sono imbattuto in una soluzione intelligente usando <svg>e display:grid.

Grid element consente di occupare lo stesso spazio con due (o più) elementi, senza la necessità di specificare quale imposta l'altezza. Ciò significa che, fuori dalla scatola, quello più alto stabilisce il rapporto .

Ciò significa che puoi usarlo così com'è quando sai che il contenuto non sarà mai abbastanza alto da riempire l'intero "rapporto" e stai semplicemente cercando un modo per posizionare il contenuto in questo spazio (cioè centrarlo su entrambe le direzioni display:flex; align-items:center; justify-content:center).
E 'praticamente la stessa come con un trasparente <img>con display:blocke il rapporto predeterminato, ad eccezione del <svg>più leggero e molto più facile da modificare (per modificare il rapporto in risposta, nel caso fosse necessario).

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

Tutto quello che devi fare è cambiare il <svg>rapporto s:

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

Guardalo funzionare:


Se è necessaria una soluzione in cui l'elemento di contenuto non è autorizzato a impostare il rapporto quando è più alto (con overflow nascosto o automatico), è necessario impostare position:relativesulla griglia e position:absolute; height:100%; overflow-y: auto;sul contenuto. Esempio:


9

Sulla base delle tue soluzioni ho fatto qualche trucco:

Quando lo usi, il tuo HTML sarà solo

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

Per usarlo in questo modo crea: CSS:

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

e js (jQuery)

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

E avendo questo hai appena impostato attr data-keep-ratiosu altezza / larghezza e il gioco è fatto.


3
si dovrebbe usare data-keep-rationon keep-ratioe ottenere il suo valore con$(this).data('keep-ratio');
Robert

il tuo codice funziona ora e forse funzionerà per sempre ma non è standard e i browser potrebbero smettere di supportarlo in qualsiasi momento in futuro
Robert

1
L'uso di JS qui causerà cattive notizie!
Amir Hossein Ahmadi,

8

Puoi usare uno svg. Rendi relativa la posizione del contenitore / wrapper, metti prima lo svg come posizionato staticamente e poi inserisci il contenuto assolutamente posizionato (in alto: 0; a sinistra: 0; a destra: 0; in basso: 0;)

Esempio con proporzioni 16: 9:

image.svg: (può essere integrato in src)

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

Nota che svg inline non sembra funzionare, ma puoi urlencode lo svg e incorporarlo nell'attributo img src in questo modo:

<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 è la migliore soluzione nel mio caso; utilizzando un attributo di dati:

[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%;
}

Per esempio :

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

fonte


15
Cordiali saluti ... Puoi fare esattamente questa cosa (usando i selettori di attributo) esattamente nella stessa quantità di righe usando CSS semplice. Il [data-aspect-ratio]selettore di attributi è disponibile in CSS.
rnevius,

6

Sebbene la maggior parte delle risposte sia molto interessante, la maggior parte di esse richiede un'immagine già dimensionata correttamente ... Altre soluzioni funzionano solo per una larghezza e non si occupano dell'altezza disponibile, ma a volte si desidera adattare il contenuto anche a una certa altezza .

Ho provato ad accoppiarli insieme per portare una soluzione completamente portatile e ridimensionabile ... Il trucco è usare il ridimensionamento automatico di un'immagine ma usare un elemento svg in linea invece di usare un'immagine pre-renderizzata o qualsiasi forma di seconda richiesta HTTP ...

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>

Si noti che ho usato grandi valori negli attributi larghezza e altezza dell'SVG, poiché deve essere più grande della dimensione massima prevista in quanto può solo ridursi. L'esempio rende il rapporto del div 10: 5


4

Solo un'idea o un trucco.

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>


Questa non è una soluzione solo per CSS ... Ora, se avessi usato un'immagine codificata in base64 in uno pseudo elemento, sarebbe stata una soluzione interessante.
rnevius,

1
Non esiste davvero una soluzione solo CSS. HTML è il componente di base del web. Credo che lo scopo della domanda sia di astenersi dall'utilizzare JS forse per risparmiare risorse / elaborazione.
orlland,

Non sono sicuro che lo pseudo elemento funzionerà. Ho utilizzato la proprietà di img element per mantenere le proporzioni affinché questa soluzione funzionasse.
orlland,

Bello, ma calcola un'altezza solo quando la larghezza cambia. Dovrebbe funzionare in entrambi i modi, quindi quando riduco l'altezza, anche la larghezza viene ricalcolata. Altrimenti è inutile ..
Ωmega

4

supponiamo che tu abbia 2 div il div esterno è un contenitore e l'interno potrebbe essere qualsiasi elemento di cui hai bisogno per mantenere il suo rapporto (img o un iframe di YouTube o altro)

html è simile al seguente:

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

diciamo che è necessario mantenere il rapporto dell '"elemento"

rapporto => 4 a 1 o 2 a 1 ...

css si presenta così

.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 */
}

imbottitura se specificato in% viene calcolato in base alla larghezza e non all'altezza. .. quindi praticamente non importa quale sia la tua larghezza, l'altezza sarà sempre calcolata in base a quello. che manterrà il rapporto.


4

Ho riscontrato questo problema alcune volte, quindi ho creato una soluzione JS per questo. Questo regola sostanzialmente l'altezza di domElement in base alla larghezza dell'elemento in base al rapporto specificato. Puoi usarlo come segue:

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

Tieni presente che, poiché sta impostando l'altezza dell'elemento, l'elemento dovrebbe essere a display:blocko display:inline-block.

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


1
Anche se non ho visto o provato il tuo codice (ne ho già uno mio), ho annullato la tua risposta solo per il fatto che tu presenti l'unica soluzione affidabile, uno script JS.
Theo d'Or,

La domanda ha richiesto specificamente una soluzione che non necessitava di Javascript.
Flimm,

4

Se vuoi adattare un quadrato all'interno del viewport sia in verticale che in orizzontale (il più grande possibile, ma nulla si attacca all'esterno), passa dall'uso vw/ vhall'orientamento portrait/ landscape:

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

4

Vorrei condividere la mia soluzione, dove ho un imgtag che riempie un certo formato. Non ho potuto utilizzare backgrounda causa della mancanza di sostegno del CMS e io non preferisco usare un tag di stile in questo modo: <img style="background:url(...)" />. Inoltre, la larghezza è del 100%, quindi non è necessario impostare una dimensione fissa come in alcune soluzioni. Si ridimensionerà in modo reattivo!

.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

Puoi farlo usando SVG.

Dipende da un caso, ma in alcuni è davvero utile. Ad esempio, puoi impostare background-imagesenza impostare l'altezza fissa o utilizzarlo per incorporare YouTube <iframe>con rapporto 16:9eposition:absolute ecc.

Per 3:2set di rapportiviewBox="0 0 3 2" e così via.

Esempio:

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>


3

Un modo semplice per mantenere le proporzioni, usando l'elemento canvas.

Prova a ridimensionare il div in basso per vederlo in azione.

Per me, questo approccio ha funzionato meglio, quindi lo condivido con gli altri in modo che possano trarne vantaggio.

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

Funziona anche con altezza dinamica!

.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 mi ha aiutato, ora posso usarlo per impostare l'altezza div del genitore dell'immagine)
Alex

2

Dì che ti piace mantenere la Larghezza: 100 px e l'Altezza: 50 px (cioè 2: 1) Basta fare questo calcolo:

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



0

Ho usato una nuova soluzione.

.squares{
  width: 30vw
  height: 30vw

Alle proporzioni principali

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

Tuttavia, questo è relativo all'intero viewport. Quindi, se hai bisogno di un div pari al 30% della larghezza del viewport, puoi invece usare 30vw e, poiché conosci la larghezza, puoi riutilizzarli in altezza usando calc e vw unit.


7
Non è esattamente quello che la seconda risposta con il punteggio più alto ha già delineato?
rnevius,

-4

Se l'intera struttura del contenitore fosse basata su percentuale, questo sarebbe il comportamento predefinito, puoi fornire un esempio più specifico?

Di seguito è riportato un esempio di ciò che intendo, se la tua intera gerarchia genitore fosse basata su%, qualsiasi regolazione della finestra del browser funzionerebbe senza ulteriori js / css, non è questa una possibilità con il tuo layout?

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

1
Vedi la mia modifica alla domanda originale. Non vedo dove questa tecnica manterrebbe le proporzioni, l'altezza non cambierebbe.
Jackb
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.