1231 votes

Maintenir le rapport d'aspect d'un div avec CSS

Je veux créer un div qui peut changer sa largeur/hauteur lorsque la largeur de la fenêtre change.

Existe-t-il des règles CSS3 qui permettraient de modifier la hauteur en fonction de la largeur ? tout en conservant son rapport d'aspect ?

Je sais que je peux le faire via JavaScript, mais je préférerais utiliser uniquement CSS.

div keeping aspect ratio according to width of window

4 votes

J'ai abordé différentes approches à cet égard dans mon article CSS-Tricks sur le thème mise à l'échelle des animations réactives

5 votes

Je suis arrivé très tard à cette Q&R, mais je dois faire un commentaire. Bien qu'il soit très discipliné et conforme aux règles de l'OS que chaque personne qui répond fasse de son mieux pour satisfaire à l'exigence "uniquement CSS" de la question, il est assez surprenant qu'à l'exception de la réponse de user007 En bas de la page, personne n'a mentionné l'évidence : il n'existe pas de solution fiable uniquement en CSS, ce problème nécessite Javascript. Un néophyte arrivant sur cette page pourrait perdre un temps précieux à passer d'un ensemble d'avantages et d'inconvénients à un autre avant que l'ampoule ne se déclenche : Les CSS ne suffiront pas.

1 votes

J'ai écrit un petit outil qui permet de prévisualiser et de calculer facilement les rapports d'aspect, aspectrat.io . Il génère également le code CSS/Sass/Less approprié que vous pouvez copier et coller dans vos projets. J'espère que les gens le trouveront utile.

1490voto

Web_Designer Points 11083

Il suffit de créer un wrapper <div> avec une valeur en pourcentage pour padding-bottom comme ceci :

.demoWrapper {
  padding: 10px;
  background: white;
  box-sizing: border-box;
  resize: horizontal;
  border: 1px dashed;
  overflow: auto;
  max-width: 100%;
  height: calc(100vh - 16px);
}

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

<div class="demoWrapper">
  <div></div>
</div>

Il en résultera un <div> dont la hauteur est égale à 75 % de la largeur de son conteneur (un rapport d'aspect 4:3).

Cela repose sur le fait que pour le rembourrage :

Le pourcentage est calculé par rapport à la largeur du bloc contenant la boîte générée [...] (source : w3.org (c'est moi qui souligne)

Valeurs de padding-bottom pour les autres rapports d'aspect et la largeur de 100 % :

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

Placer du contenu dans le div :

Afin de conserver le rapport d'aspect de la division et d'empêcher son contenu de s'étirer, vous devez ajouter un enfant positionné de manière absolue et l'étirer jusqu'aux bords de l'enveloppe avec :

div.stretchy-wrapper {
  position: relative;
}

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

Voici un Démonstration et un autre plus approfondi Démonstration

33 votes

@schellmax, c'est parce que le % de padding est calculé par rapport à la largeur de l'élément actuel, alors que le % de height est calculé par rapport à la hauteur de l'élément parent. En outre, les positions absolues sont calculées par rapport au conteneur extérieur d'un élément, qui inclut la zone de remplissage. Pour plus d'informations, recherchez "CSS Box Model" sur Google.

15 votes

Cela ne semble pas fonctionner de manière imbriquée. Elle fonctionne au premier niveau, mais lorsqu'on essaie de faire la même chose à l'intérieur de la division en maintenant le rapport d'aspect, le pourcentage de padding-bottom semble être appliqué à la largeur du parent. voici un exemple où le padding-bottom .stretchy-wrap.onethird de 25 % correspond en fait à 25 % de la largeur du parent. Quelqu'un peut-il expliquer cela ?

5 votes

Totalement génial. Ce qui me tue, c'est que cette technique ne fonctionne pas quand on veut fixer la hauteur à 100%. @Misterparker, la technique repose sur le fait que les calculs de largeur et de remplissage sont effectués par rapport à la même référence ; vous ne pouvez pas utiliser une largeur inférieure à 100 %, comme vous l'avez fait dans votre exemple.

457voto

web-tiki Points 14660

vw unités :

Vous pouvez utiliser vw pour les deux largeur et hauteur de l'élément. Cela permet de préserver le rapport d'aspect de l'élément, en fonction de la largeur de la fenêtre d'affichage.

vw : 1/100ème de la largeur du viewport. [ _MDN_ ]

Alternativement, vous pouvez aussi utiliser vh pour la hauteur de la fenêtre, ou même vmin / vmax pour utiliser la plus petite/grande des dimensions de la fenêtre (discussion ici ).

Exemple : rapport d'aspect 1:1

div {
  width: 20vw;
  height: 20vw;
  background: gold;
}

<div></div>

Pour d'autres rapports d'aspect, vous pouvez utiliser le tableau suivant pour calculer la valeur de la hauteur en fonction de la largeur de l'élément :

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

Exemple : Grille 4x4 de divs carrés

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>

Voici un Jouez avec cette démo et voici une solution pour faire un grille réactive de carrés avec contenu centré verticalement et horizontalement .


Le support du navigateur pour les unités vh/vw est IE9+ voir canIuse pour plus d'informations

3 votes

@vivekmaharajh les deux techniques sont bonnes, chacune a ses avantages et ses inconvénients. L'utilisation de l'une ou l'autre dépend grandement de la situation.

13 votes

@web-tiki, vous avez raison. J'ai rencontré un problème - il suppose que la largeur de l'élément est proportionnelle à la largeur de la fenêtre d'affichage, ce qui ne sera pas le cas si 1) vous avez des choses comme des gouttières à largeur fixe, ou 2) vous avez une largeur maximale définie pour certains de vos éléments.

1 votes

Peut-être que c'est juste Chrome v47beta, mais quand je règle le div sur width:50% et height:50vw la hauteur est un peu plus grande que la largeur, donc pas exactement une proportion de 1:1. Avez-vous une idée ?

28voto

J'ai trouvé un moyen de le faire en utilisant les CSS, mais il faut faire attention car cela peut changer en fonction du flux de votre propre site web. Je l'ai fait pour intégrer une vidéo avec un rapport d'aspect constant dans une partie de mon site Web à largeur variable.

Disons que vous avez une vidéo intégrée comme celle-ci :

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

Vous pouvez ensuite placer le tout dans un div avec une classe "vidéo". Cette classe vidéo sera probablement l'élément fluide de votre site Web, c'est-à-dire qu'il n'a pas de contraintes de hauteur directes, mais que lorsque vous redimensionnez le navigateur, sa largeur change en fonction du flux du site Web. Il s'agit probablement de l'élément dans lequel vous essayez d'intégrer votre vidéo tout en maintenant un certain rapport d'aspect de la vidéo.

Pour ce faire, je place une image avant l'objet incorporé dans le div de la classe "vidéo".

! !! L'important est que l'image ait le bon rapport d'aspect que vous souhaitez conserver. En outre, assurez-vous que la taille de l'image est AU MOINS aussi grande que la plus petite que vous attendez de la vidéo (ou de ce que vous maintenez le rapport hauteur/largeur) en fonction de votre mise en page. Cela évitera tout problème potentiel de résolution de l'image lorsqu'elle est redimensionnée en pourcentage. Par exemple, si vous souhaitez conserver un rapport hauteur/largeur de 3:2, n'utilisez pas simplement une image de 3px par 2px. Cela peut fonctionner dans certaines circonstances, mais je ne l'ai pas testé, et ce serait probablement une bonne idée à éviter.

Vous devriez probablement avoir déjà défini une largeur minimale comme celle-ci pour les éléments fluides de votre site Web. Si ce n'est pas le cas, c'est une bonne idée de le faire afin d'éviter de couper des éléments ou d'avoir des chevauchements lorsque la fenêtre du navigateur devient trop petite. Il est préférable d'avoir une barre de défilement à un moment donné. La plus petite largeur d'une page Web devrait se situer autour de ~600px (y compris les colonnes à largeur fixe), car les résolutions d'écran ne sont pas plus petites, sauf s'il s'agit de sites adaptés aux téléphones. ! !!

J'utilise un png complètement transparent mais je ne pense pas que cela ait une importance si vous le faites correctement. Comme ceci :

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

Vous devriez maintenant être en mesure d'ajouter un CSS semblable à celui qui suit :

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

Veillez également à supprimer toute déclaration explicite de hauteur ou de largeur dans l'objet et les balises d'intégration qui accompagnent généralement le code d'intégration copié/collé.

La façon dont cela fonctionne dépend des propriétés de position de l'élément de classe vidéo et de l'élément que vous souhaitez voir conserver un certain rapport d'aspect. Il tire parti de la manière dont une image conserve son rapport d'aspect correct lorsqu'elle est redimensionnée dans un élément. Il indique à ce qui se trouve dans l'élément de classe vidéo de profiter pleinement de l'espace fourni par l'image dynamique en forçant sa largeur/hauteur à 100 % de l'élément de classe vidéo ajusté par l'image.

Plutôt cool, hein ?

Vous devrez peut-être jouer un peu avec pour que cela fonctionne avec votre propre design, mais cela fonctionne étonnamment bien pour moi. Le concept général est là.

20voto

florianb Points 718

Elliot m'a inspiré cette solution - merci :

aspectratio.png est un fichier PNG complètement transparent avec la taille de votre ratio d'aspect préféré, dans mon cas 30x10 pixels.

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

Veuillez noter : background-size est une fonctionnalité css3 qui peut ne pas fonctionner avec vos navigateurs cibles. Vous pouvez vérifier l'interopérabilité (par exemple sur caniuse.com ).

16voto

nabrown78 Points 76

Pour ajouter à la réponse de Web_Designer, l'option <div> aura une hauteur (entièrement constituée par le remplissage du bas) égale à 75 % de la largeur de son fichier élément contenant . Voici un bon résumé : http://mattsnider.com/css-using-percent-for-margin-and-padding/ . Je ne sais pas pourquoi il en est ainsi, mais c'est comme ça.

Si vous souhaitez que votre div ait une largeur différente de 100 %, vous devez définir la largeur d'une autre div enveloppante :

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

J'ai récemment utilisé quelque chose de similaire à l'astuce d'Elliot pour me permettre d'utiliser les requêtes média CSS afin de servir un fichier de logo différent en fonction de la résolution de l'appareil, tout en conservant une échelle proportionnelle en tant qu'image. <img> ferait naturellement l'affaire (j'ai défini le logo en tant qu'image d'arrière-plan sur un .png transparent avec le bon ratio d'aspect). Mais la solution de Web_Designer me permettrait d'éviter une requête http.

0 votes

Excellente solution. Dans mon cas, je connais la taille "naturelle" de l'image lorsque je la place dans le DOM et j'ai besoin d'un espace réservé à l'image avec une hauteur appropriée pour éviter tout défilement supplémentaire une fois que le navigateur a chargé les images. Dans .ar-outer, j'ai la largeur de l'image en pixels, dans .ar, j'ai le padding-bottom calculé à partir du rapport d'aspect réel de l'image. Au lieu de ar-inner, j'ai l'image elle-même (<img>). Cependant, j'ai dû définir la largeur à 100% au lieu de définir le haut, le bas, la gauche et la droite. Lorsque je fixe maxWidth à ar-outer, l'image s'adapte bien lorsque le parent est petit, mais ne s'adapte pas à une taille supérieure à sa taille naturelle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X