div의 종횡비를 유지하지만 CSS에서 화면 너비와 높이를 채우시겠습니까?


122

16:9동영상처럼 가로 세로 비율이 고정 된 사이트를 모아 놓았습니다 .

나는 그것을 중앙에 놓고 사용 가능한 너비와 사용 가능한 높이를 채우기 위해 확장하고 싶지만 양쪽에서 더 커지지 않도록합니다.

예를 들면 :

  1. 길고 얇은 페이지에는 비례 높이를 유지하면서 전체 너비로 콘텐츠가 늘어납니다.
  2. 짧은 폭의 페이지에는 비례하는 너비로 전체 높이로 콘텐츠가 늘어납니다.

내가 살펴본 두 가지 방법이 있습니다.

  1. 적절한 가로 세로 비율의 이미지를 사용하여 컨테이너를 확장 div했지만 주요 브라우저에서 동일한 방식으로 작동하도록 만들 수 없습니다.
  2. 비례 하단 패딩을 설정하지만 너비에 대해서만 상대적으로 작동하고 높이를 무시합니다. 너비에 따라 계속 커지고 세로 스크롤 막대가 표시됩니다.

JS로 쉽게 할 수 있다는 것을 알고 있지만 순수한 CSS 솔루션을 원합니다.

어떤 아이디어?


sitepoint.com/... 설정 컨테이너 사업부에position: relative (default) height: 0 padding-<top/bottom>: H/W*100%
Ujjwal 싱

답변:


280

새로운 CSS 뷰포트 단위 vwvh(뷰포트 너비 / 뷰포트 높이) 사용

깡깡이

수직 및 수평으로 크기를 조정하면 요소가 비율을 깨지 않고 스크롤바없이 항상 최대 뷰포트 크기를 채운다는 것을 알 수 있습니다!

(순수) 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 */
}

뷰포트의 너비와 높이의 최대 90 %를 사용하려는 경우 : FIDDLE

또한 브라우저 지원도 꽤 좋습니다 : IE9 +, FF, Chrome, Safari- caniuse


1
이것은 정말 좋은 깨끗한 솔루션입니다. 그래도 브라우저 지원으로 이상적으로 할 수 있습니다. 나는 당신이 단지 최소 너비 / 높이가 그로 설정 것 이전 브라우저에 생각 -이 스크롤 바는 그렇게 할 수 있던 경우에
헨리 깁슨을

8
음 .. 2 일의 작업과 무한한 사용자 불만을 줄여 주셔서 감사합니다. 내가 할 수 있다면 1000+.
Schoening

2
당신은 저에게 많은 시간을 절약했습니다. 대단히 감사합니다.
Dylan Gattey

1
불행하게도, 최근 아이폰 OS 버전을 지원하지 않는 , 또는 뷰포트 단위의 깨진 구현이 ( vh, vw, vmin, vmax). 그러나 미디어 쿼리를 사용하여 iOS 기기를 타겟팅 하는 해결 방법이 있습니다.
Tim

1
사랑해. 훌륭한 솔루션!
Guttemberg 2014

20

Danield추가 사용을 위해 LESS 믹스 인에서의 답변을 재구성 합니다.

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

11

CSS 뷰포트 단위 와 함께 CSS 미디어 쿼리를 사용하고 뷰포트 의 종횡비에 맞게 조정합니다. 이렇게하면과 같은 다른 속성도 업데이트 할 수 있습니다.@media vwvhfont-size

이 바이올린 은 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-widthand max-height 접근 방식 과 매우 유사하며 더 유연합니다.


7

이것에 대한 나의 원래 질문은 두 가지 모두 고정 된 측면의 요소를 갖는 방법이지만 지정된 컨테이너 내에 정확히 맞추는 방법이었습니다. 개별 요소가 종횡비를 유지하기 만하면 훨씬 쉽습니다.

내가 만난 가장 좋은 방법은 요소에 높이를 0으로 지정한 다음 백분율 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를 사용해야 할 수도 있습니다.


여기에서 추가 마크 업을 사용하지 않으려면 :: before 또는 :: after를 사용하여 요소를 추가하고 해당 요소에 높이 0을 지정하고 개체 너비와 0 너비에 상대적인 padding-bottom을 지정할 수 있습니다. 이는 동일한 효과를 가지지 만 마크 업이 적고 컨테이너 없이도 전체 개체 영역을 사용하여 콘텐츠를 넣을 수 있습니다.
Henry Gibson

6

CSS특정 솔루션 을 원한다고 요청하셨습니다 . 종횡비를 유지하려면 높이를 원하는 종횡비로 나누어야합니다. 16 : 9 = 1.777777777778.

컨테이너의 올바른 높이를 얻으려면 현재 너비를 1.777777777778로 나누어야합니다. 당신은 width단지 CSS또는 백분율로 나눈 컨테이너의 확인을 할 수 없기 때문에 (내가 아는 한) CSS이것은 불가능합니다 JavaScript.

원하는 종횡비를 유지하는 작업 스크립트를 작성했습니다.

HTML

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

CSS

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

자바 스크립트

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

다음을 사용하여 function다른 비율로 다른 것을 표시 하려면 다시 사용할 수 있습니다.

keepAspectRatio(id, width, height);

답변 해 주셔서 감사합니다. 스크립트에서이 작업을 수행하는 것은 비교적 간단하지만 CSS 기반 솔루션을 원했습니다. 정말 빠르고 안정적인 반응 형 솔루션을 원하고 때로는 다른 브라우저의 크기 조정 이벤트가 약간 느립니다. 브라우저 크기 조정이 발생한 후 약간의 변환을 수행하므로 최상의 사용자 경험을 제공하지 못합니다. 브라우저가 크기를 변경하는 순간 렌더링하는 것을 원하므로 순수한 CSS를 원합니다.
Henry Gibson

1
@Henry Gibson 스크립트는 Chrome, FF, IE, Opera 및 Safari에서 테스트되었습니다. 모든 것이 신속하게 작동하며 이전 버전의 브라우저에서도 안정적입니다. 모든 브라우저는 자체 이벤트를 발생시킵니다. window.onresize브라우저가 크기를 변경하는 순간 시작됩니다.
MCSharp

최종 사용자가 거의 많은 개발자들처럼 브라우저의 크기를 조정하지 않는 기억
Simon_Weaver


1

Danield의 대답 은 좋지만 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 에 있으므로 값의 출처가 더 명확 해집니다.


0

Daniel의 답변을 기반으로 #{}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입니다.

많은 테스트를 거친 후, 이것은 이제 나에게 완벽하게 작동합니다.


-1

여기에는 div 내에서도 작동하는 @Danield 솔루션을 기반으로 한 솔루션이 있습니다.

이 예에서는 Angular를 사용하고 있지만 바닐라 JS 또는 다른 프레임 워크로 빠르게 이동할 수 있습니다.

주요 아이디어는 빈 iframe 내에서 @Danield 솔루션을 이동하고 iframe 창 크기가 변경된 후 크기를 복사하는 것입니다.

해당 iframe은 아버지 요소와 크기가 맞아야합니다.

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

다음은 몇 가지 스크린 샷입니다.

여기에 이미지 설명 입력

여기에 이미지 설명 입력

여기에 이미지 설명 입력

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.