134 votes

Maintenir le rapport d'aspect de la division mais remplir la largeur et la hauteur de l'écran en CSS ?

J'ai un site à mettre en place qui a un rapport d'aspect fixe d'approximativement 16:9 paysage, comme une vidéo.

Je veux qu'il soit centré et qu'il s'étende pour remplir la largeur et la hauteur disponibles, mais qu'il ne s'agrandisse jamais d'un côté ou de l'autre.

Par exemple :

  1. Dans une page haute et mince, le contenu s'étendrait sur toute la largeur tout en conservant une hauteur proportionnelle.
  2. Dans une page courte et large, le contenu s'étend sur toute la hauteur, avec une largeur proportionnelle.

Il y a deux méthodes que j'ai étudiées :

  1. Utilisez une image avec le bon ratio d'aspect pour étendre un conteneur div mais je n'ai pas réussi à faire en sorte qu'il se comporte de la même manière avec les principaux navigateurs.
  2. J'ai défini un padding inférieur proportionnel, mais cela ne fonctionne que par rapport à la largeur et ignore la hauteur. Il ne fait que s'agrandir avec la largeur et affiche des barres de défilement verticales.

Je sais que vous pourriez faire cela avec JS assez facilement, mais j'aimerais une solution purement CSS.

Des idées ?

0 votes

sitepoint.com/ Définissez la div du conteneur sur position: relative (default) height: 0 padding-<top/bottom>: H/W*100%

0 votes

316voto

Danield Points 17720

Utilisez le nouveau Unités de visualisation CSS vw y vh (largeur de la fenêtre / hauteur de la fenêtre)

FIDDLE

Redimensionnez verticalement et horizontalement et vous verrez que l'élément remplira toujours la taille maximale de la fenêtre d'affichage sans casser le ratio et sans barres de défilement !

(PURE) CSS

div
{
    width: 100vw; 
    height: 56.25vw; /* height:width ratio = 9/16 = .5625  */
    background: pink;
    max-height: 100vh;
    max-width: 177.78vh; /* 16/9 = 1.778 */
    margin: auto;
    position: absolute;
    top:0;bottom:0; /* vertical center */
    left:0;right:0; /* horizontal center */
}

* {
  margin: 0;
  padding: 0;
}
div {
  width: 100vw;
  height: 56.25vw;
  /* 100/56.25 = 1.778 */
  background: pink;
  max-height: 100vh;
  max-width: 177.78vh;
  /* 16/9 = 1.778 */
  margin: auto;
  position: absolute;
  top: 0;
  bottom: 0;
  /* vertical center */
  left: 0;
  right: 0;
  /* horizontal center */
}

<div></div>

Si vous souhaitez utiliser un maximum de, disons, 90 % de la largeur et de la hauteur de la fenêtre d'affichage : FIDDLE

* {
  margin: 0;
  padding: 0;
}
div {
  width: 90vw;
  /* 90% of viewport vidth */
  height: 50.625vw;
  /* ratio = 9/16 * 90 = 50.625 */
  background: pink;
  max-height: 90vh;
  max-width: 160vh;
  /* 16/9 * 90 = 160 */
  margin: auto;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

<div></div>

La prise en charge des navigateurs est également très bonne : IE9+, FF, Chrome, Safari- caniuse

1 votes

C'est une solution propre et très agréable. L'idéal serait que le support du navigateur soit un peu plus ancien. Je suppose que sur un ancien navigateur, il suffirait d'avoir une largeur/hauteur minimale et de la fixer à cette valeur - s'il y a des barres de défilement, tant pis.

1 votes

Malheureusement, les versions récentes d'iOS ne soutiennent pas ou une implémentation défectueuse des unités de visualisation ( vh , vw , vmin , vmax ). Cependant, il existe un solution de contournement qui utilise des requêtes média pour cibler les appareils iOS.

0 votes

J'essaie de mettre en œuvre la solution à 90 % que vous proposez, mais mes images ne sont pas en 16:9 et elles sont compressées verticalement. Mes images sont de tailles différentes. Existe-t-il une solution à ce problème ?

20voto

Christophe Marois Points 705

Je ne fais que reformuler Danield dans un mixin LESS, pour une utilisation ultérieure :

// Mixin for ratio dimensions    
.viewportRatio(@x, @y) {
  width: 100vw;
  height: @y * 100vw / @x;
  max-width: @x / @y * 100vh;
  max-height: 100vh;
}

div {

  // Force a ratio of 5:1 for all <div>
  .viewportRatio(5, 1);

  background-color: blue;
  margin: 0;
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
}

12voto

Paul Points 198

Utilisez un Requête média CSS @media avec le Unités de visualisation CSS vw y vh pour s'adapter au rapport d'aspect de la fenêtre d'affichage. Cela présente l'avantage de mettre à jour d'autres propriétés, telles que font-size aussi.

Ce violon montre le rapport d'aspect fixe de la division, et le texte qui correspond exactement à son échelle.

La taille initiale est basée sur la pleine largeur :

div {
  width: 100vw; 
  height: calc(100vw * 9 / 16);

  font-size: 10vw;

  /* align center */
  margin: auto;
  position: absolute;
  top: 0px; right: 0px; bottom: 0px; left: 0px;

  /* visual indicators */
  background:
    url(data:image/gif;base64,R0lGODlhAgAUAIABAB1ziv///yH5BAEAAAEALAAAAAACABQAAAIHhI+pa+EPCwA7) repeat-y center top,
    url(data:image/gif;base64,R0lGODlhFAACAIABAIodZP///yH5BAEAAAEALAAAAAAUAAIAAAIIhI8Zu+nIVgEAOw==) repeat-x left center,
    silver;
}

Ensuite, lorsque la fenêtre d'affichage est plus large que le rapport d'aspect souhaité, la hauteur devient la mesure de base :

/* 100 * 16/9 = 177.778 */
@media (min-width: 177.778vh) {
  div {
    height: 100vh;
    width: calc(100vh * 16 / 9);

    font-size: calc(10vh * 16 / 9);
  }
}

Il s'agit d'une approche très similaire à celle de la max-width y max-height approche par @Danield, juste plus flexible.

8voto

Henry Gibson Points 466

La question que je me posais à l'origine était de savoir comment disposer d'un élément d'un aspect fixe, tout en l'insérant exactement dans un conteneur spécifié, ce qui rend les choses un peu compliquées. Si vous voulez simplement qu'un élément individuel conserve son rapport d'aspect, c'est beaucoup plus facile.

La meilleure méthode que j'ai trouvée consiste à donner une hauteur nulle à un élément, puis à utiliser le pourcentage padding-bottom pour lui donner de la hauteur. Le padding en pourcentage est toujours proportionnel à la largeur d'un élément, et non à sa hauteur, même s'il s'agit d'un padding supérieur ou inférieur.

Propriétés de remplissage du W3C

En utilisant cela, vous pouvez donner à un élément un pourcentage de largeur pour qu'il se situe dans un conteneur, puis un remplissage pour spécifier le rapport d'aspect, ou en d'autres termes, la relation entre sa largeur et sa hauteur.

.object {
    width: 80%; /* whatever width here, can be fixed no of pixels etc. */
    height: 0px;
    padding-bottom: 56.25%;
}
.object .content {
    position: absolute;
    top: 0px;
    left: 0px;
    height: 100%;
    width: 100%;
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    padding: 40px;
}

Ainsi, dans l'exemple ci-dessus, l'objet occupe 80 % de la largeur du conteneur, et sa hauteur représente 56,25 % de cette valeur. Si la largeur de l'objet était de 160px, le remplissage du fond, et donc la hauteur, serait de 90px - un aspect 16:9.

Le petit problème ici, qui n'est peut-être pas un problème pour vous, est qu'il n'y a pas d'espace naturel à l'intérieur de votre nouvel objet. Si vous devez insérer du texte, par exemple, et que ce texte doit prendre ses propres valeurs de remplissage, vous devez ajouter un conteneur à l'intérieur et y spécifier les propriétés.

En outre, les unités vw et vh ne sont pas prises en charge par certains navigateurs plus anciens, de sorte que la réponse acceptée à ma question pourrait ne pas être possible pour vous et vous pourriez avoir à utiliser quelque chose de plus lo-fi.

0 votes

Pour éviter d'utiliser des balises supplémentaires ici, vous pouvez ajouter un élément en utilisant ::before ou ::after et donner à cet élément une hauteur de 0 et un padding-bottom relatif à la largeur des objets et une largeur propre de 0. Cela aura le même effet, mais avec moins de balises, et permettra d'utiliser toute la zone de l'objet pour y placer du contenu sans avoir besoin d'un conteneur.

6voto

Henry Gibson Points 466

Il existe maintenant une nouvelle propriété CSS spécifiée pour résoudre ce problème : object-fit .

https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit

Cette fonctionnalité est désormais largement supportée ( http://caniuse.com/#feat=object-fit ).

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