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

6voto

MCSharp Points 390

J'ai cru comprendre que vous avez demandé à ce qu'il y ait une CSS solution spécifique. Pour conserver le rapport hauteur/largeur, vous devez diviser la hauteur par le rapport hauteur/largeur souhaité. 16:9 = 1.777777777778.

Pour obtenir la hauteur correcte du conteneur, vous devez diviser la largeur actuelle par 1,777777777778. Puisque vous ne pouvez pas vérifier la width du conteneur avec seulement CSS ou diviser par un pourcentage est CSS ce qui n'est pas possible sans JavaScript (à ma connaissance).

J'ai écrit un script fonctionnel qui conservera le rapport d'aspect souhaité.

HTML

<div id="aspectRatio"></div>

CSS

body { width: 100%; height: 100%; padding: 0; margin: 0; }
#aspectRatio { background: #ff6a00; }

JavaScript

window.onload = function () {
    //Let's create a function that will scale an element with the desired ratio
    //Specify the element id, desired width, and height
    function keepAspectRatio(id, width, height) {
        var aspectRatioDiv = document.getElementById(id);
        aspectRatioDiv.style.width = window.innerWidth;
        aspectRatioDiv.style.height = (window.innerWidth / (width / height)) + "px";
    }

    //run the function when the window loads
    keepAspectRatio("aspectRatio", 16, 9);

    //run the function every time the window is resized
    window.onresize = function (event) {
        keepAspectRatio("aspectRatio", 16, 9);
    }
}

Vous pouvez utiliser le function à nouveau si vous souhaitez afficher quelque chose d'autre avec un ratio différent en utilisant

keepAspectRatio(id, width, height);

0 votes

Merci pour votre réponse. Faire cela dans script est relativement simple, mais je voulais vraiment une solution basée sur CSS. Je veux une solution réactive fiable vraiment rapide, et je trouve parfois que les événements de redimensionnement dans différents navigateurs sont un peu décalés. Vous finissez par effectuer votre transformation un peu après que le redimensionnement du navigateur ait eu lieu, ce qui ne donne pas la meilleure expérience utilisateur. Je veux quelque chose qui rende au moment où le navigateur change de taille, donc du pur CSS.

1 votes

@Henry Gibson Le script a été testé dans Chrome, FF, IE, Opera et Safari. Tous fonctionnent rapidement et sont fiables même dans les anciennes versions des navigateurs. Chaque navigateur déclenche ses propres événements. window.onresize est déclenché au moment où le navigateur change de taille.

0 votes

Rappelez-vous que les utilisateurs finaux ne redimensionnent pas les navigateurs autant que les développeurs.

1voto

ddlshack Points 1501

La réponse de Danield est une bonne chose, mais elle ne peut être utilisée que lorsque le div remplit entièrement la fenêtre d'affichage, ou en utilisant un peu de calc peut être utilisé si la largeur et la hauteur de l'autre contenu dans la fenêtre d'affichage sont connues.

Cependant, en combinant les margin-bottom Avec la méthode décrite dans la réponse susmentionnée, le problème peut être réduit à la seule connaissance de la hauteur de l'autre contenu. Ceci est utile si vous avez un en-tête de hauteur fixe, mais que la largeur de la barre latérale, par exemple, n'est pas connue.

body {
  margin: 0;
  margin-top: 100px; /* simulating a header */
}

main {
  margin: 0 auto;
  max-width: calc(200vh - 200px);
}

section {
  padding-bottom: 50%;
  position: relative;
}

div {
  position:absolute;
  background-color: red;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
}

<main>
  <section>
    <div></div>
  </section>
</main>

Le voici dans un jsfiddle utilisant scss ce qui rend plus évidente l'origine des valeurs.

0voto

CPHPython Points 2219

Sur la base de La réponse de Daniel j'ai écrit ce mixin SASS avec interpolation ( #{} ) pour l'iframe d'une vidéo youtube qui se trouve dans une boîte de dialogue modale Bootstrap :

@mixin responsive-modal-wiframe($height: 9, $width: 16.5,
                                $max-w-allowed: 90, $max-h-allowed: 60) {
  $sides-adjustment: 1.7;

  iframe {
    width: #{$width / $height * ($max-h-allowed - $sides-adjustment)}vh;
    height: #{$height / $width * $max-w-allowed}vw;
    max-width: #{$max-w-allowed - $sides-adjustment}vw;
    max-height: #{$max-h-allowed}vh;
  }

  @media only screen and (max-height: 480px) {
    margin-top: 5px;
    .modal-header {
      padding: 5px;
      .modal-title {font-size: 16px}
    }
    .modal-footer {display: none}
  }
}

Utilisation :

.modal-dialog {
  width: 95vw; // the modal should occupy most of the screen's available space
  text-align: center; // this will center the titles and the iframe

  @include responsive-modal-wiframe();
}

HTML :

<div class="modal">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
        <h4 class="modal-title">Video</h4>
      </div>
      <div class="modal-body">
        <iframe src="https://www.youtube-nocookie.com/embed/<?= $video_id ?>?rel=0" frameborder="0"
          allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
          allowfullscreen></iframe>
      </div>
      <div class="modal-footer">
        <button class="btn btn-danger waves-effect waves-light"
          data-dismiss="modal" type="button">Close</button>
      </div>
    </div>
  </div>
</div>

Cela affichera toujours la vidéo sans ces parties noires que youtube ajoute à l'iframe lorsque la largeur ou la hauteur n'est pas proportionnelle à la vidéo. Notes :

  • $sides-adjustment est un léger ajustement pour compenser une infime partie de ces parties noires apparaissant sur les côtés ;
  • dans les appareils de très faible hauteur (< 480px), la modale standard prend beaucoup de place, j'ai donc décidé de.. :
    1. cacher le .modal-footer ;
    2. ajuster le positionnement de la .modal-dialog ;
    3. réduire les tailles des .modal-header .

Après de nombreux tests, cela fonctionne parfaitement pour moi maintenant.

-1voto

Voici une solution basée sur la solution de @Danield, qui fonctionne même dans un div.

Dans cet exemple, j'utilise Angular mais on peut rapidement passer à vanilla JS ou à un autre framework.

L'idée principale est simplement de déplacer la solution @Danield dans une iframe vide et de copier les dimensions après que la taille de la fenêtre de l'iframe ait changé.

Cet iframe doit avoir les mêmes dimensions que son élément père.

https://stackblitz.com/edit/angular-aspect-ratio-by-iframe?file=src%2Findex.html

Voici quelques captures d'écran :

enter image description here

enter image description here

enter image description here

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