web-dev-qa-db-ja.com

divのアスペクト比を維持しますが、CSSで画面の幅と高さを埋めますか?

ビデオのように、約16:9ランドスケープの固定アスペクト比を持つサイトをまとめています。

私はそれを中央に揃えて、利用可能な幅と利用可能な高さを埋めるように拡張したいが、どちらの側も大きくならないようにしたい。

例:

  1. 背が高くて薄いページでは、コンテンツが全幅に広がり、それに比例して高さが維持されます。
  2. 短い幅のページでは、コンテンツは幅に比例して完全な高さになります。

私が見てきた2つの方法があります:

  1. 適切なアスペクト比の画像を使用してコンテナdivを展開しますが、主要なブラウザ間で同じように動作させることはできませんでした。
  2. プロポーショナルボトムパディングを設定しますが、それは幅に対してのみ機能し、高さは無視します。幅とともに大きくなり続けるだけで、垂直スクロールバーが表示されます。

JSでこれを簡単に実行できることはわかっていますが、純粋なCSSソリューションが欲しいのです。

何か案は?

100
Henry Gibson

これに対処するために指定された新しいCSSプロパティがあります:object-fit

http://docs.webplatform.org/wiki/css/properties/object-fit

ブラウザのサポートはまだやや欠けています( http://caniuse.com/#feat=object-fit )-現在、Microsoftを除くほとんどのブラウザである程度動作します-しかし、時間を考えると、まさにそれが必要でしたこの質問に。

2
Henry Gibson

新しい CSSビューポート単位vwおよびvh(ビューポート幅/ビューポート高さ)を使用します

フィドル

垂直および水平にサイズを変更すると、要素が常に比率を壊さず、スクロールバーなしで最大ビューポートサイズを埋めることがわかります!

(純粋な)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>

たとえば、ビューポートの幅と高さの最大90%を使用する場合: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>

また、ブラウザのサポートもかなり良好です:IE9 +、FF、Chrome、Safari- caniuse

244
Danield

さらに使用するために、LESSミックスインでDanieldの回答を再構成するだけです。

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

CSSメディアクエリ@mediaCSSビューポートユニットvwおよびvhと一緒に使用して、ビューポートのアスペクト比に適合させます。これには、font-sizeなどの他のプロパティも更新できるという利点があります。

このfiddle は、divの固定アスペクト比と、縮尺と正確に一致するテキストを示しています。

初期サイズは全幅に基づいています:

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

次に、ビューポートが目的のアスペクト比よりも広い場合、基本メジャーとして高さに切り替えます。

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

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

これは、@ Danieldによるmax-widthおよびmax-heightapproach に非常によく似ており、より柔軟です。

7
Paul

これに対する私の最初の質問は、どちらも固定されたアスペクトの要素をどのように持つかですが、指定されたコンテナ内にそれを正確に収める方法でした。個々の要素のアスペクト比を維持するだけの場合は、はるかに簡単です。

私が遭遇した最良の方法は、要素にゼロの高さを与えてから、パーセンテージpadding-bottomを使用して要素に高さを与えることです。パーセントのパディングは、要素の幅に比例し、高さではなく、要素の幅に常に比例します(上または下のパディングであっても)。

W3Cパディングプロパティ

そのため、コンテナ内に収まるように要素に幅をパーセンテージで指定し、次にパディングしてアスペクト比または他の用語でその幅と高さの関係を指定できます。

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

したがって、上記の例では、オブジェクトはコンテナの幅の80%を占め、その高さはその値の56.25%になります。幅が160pxの場合、下部のパディング、つまり高さは90px-16:9のアスペクトになります。

ここでのわずかな問題は、あなたにとっては問題ではないかもしれませんが、新しいオブジェクトの中に自然な空間がないということです。たとえば、テキストを入力する必要があり、そのテキストが独自のパディング値を取る必要がある場合は、内部にコンテナを追加し、そこにプロパティを指定する必要があります。

また、一部の古いブラウザではvwユニットとvhユニットがサポートされていないため、私の質問に対する受け入れられた答えがあなたにとって不可能な場合があり、あなたはもっとlo-fiを使用する必要があるかもしれません。

7
Henry Gibson

CSSname__固有のソリューションが必要であることを尋ねたことを理解しています。アスペクト比を維持するには、高さを目的のアスペクト比で割る必要があります。 16:9 = 1.777777777778。

コンテナの正しい高さを取得するには、現在の幅を1.777777777778で割る必要があります。コンテナのwidthname__をCSSname__だけでチェックしたり、パーセンテージで除算することはCSSname__であるため、これはJavaScriptname__なしでは不可能です(私の知る限り)。

望ましいアスペクト比を維持する作業スクリプトを作成しました。

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

を使用して別の比率で何かを表示する場合は、functionname__を再度使用できます。

keepAspectRatio(id, width, height);
5
MCSharp

ダニエルの答え は良いですが、divがビューポート全体を埋める場合にのみ使用できます。または、calcを少し使用すると、他のコンテンツの幅と高さがビューポートで知られています。

ただし、margin-bottomトリックを前述の回答のメソッドと組み合わせることにより、問題を他のコンテンツの高さを知るだけに減らすことができます。これは、ヘッダーの高さが固定されているが、サイドバーの幅などがわからない場合に便利です。

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>

ここではscssを使用したjsfiddleにあります 。これにより、値の出所がより明確になります。

1
Cameron Martin

ダニエルの答え に基づいて、Bootstrapモーダルダイアログ内にあるyoutubeビデオのiframeの補間(#{})でこのSASSミックスインを作成しました。

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

使用法:

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

これは常にビデオを表示しますそれらの黒い部分なし幅または高さがビデオに比例しない場合、youtubeがiframeに追加します。ノート:

  • $sides-adjustmentは、側面に現れるこれらの黒い部分のごく一部を補正するためのわずかな調整です。
  • 非常に低い高さのデバイス(<480px)では、標準のモーダルは多くのスペースを占有するため、次のことに決めました。
    1. .modal-footerを非表示にします。
    2. .modal-dialogの位置を調整します;
    3. .modal-headerのサイズを小さくします。

多くのテストの後、これは今私にとって完璧に機能しています。

0
CPHPython