Поддерживать соотношение сторон div, но ширину и высоту экрана в CSS?

У меня есть сайт для сборки, который имеет фиксированное соотношение сторон приблизительно 16:9 ландшафта, например видео.

Я хочу, чтобы он был центрирован и расширялся, чтобы заполнить доступную ширину и доступную высоту, но никогда не увеличиваться с обеих сторон.

Например:

  • Высокая и тонкая страница будет иметь контент, растягивающий всю ширину, сохраняя пропорциональную высоту.
  • У короткой широкой страницы будет содержание, растянутое на всю высоту с пропорциональной шириной.

Есть два метода, на которые я смотрел:

  • Используйте изображение с правильным соотношением сторон, чтобы развернуть контейнер div, но я не мог заставить его вести себя одинаково в основных браузерах.
  • Установка пропорционального нижнего заполнения, но это работает только относительно ширины и игнорирует высоту. Он просто увеличивается с шириной и отображает вертикальные полосы прокрутки.

Я знаю, что вы можете сделать это с JS довольно легко, но я бы хотел получить чистое решение CSS.

Любые идеи?

Ответ 1

Теперь для этого используется новый CSS-свойство: object-fit.

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

Поддержка браузеров по-прежнему несколько отсутствует (http://caniuse.com/#feat=object-fit) - в настоящее время работает в некоторой степени в большинстве браузеров, кроме Microsoft, но с учетом времени именно то, что требовалось для этого вопроса.

Ответ 2

Используйте новые узлы просмотра CSS vw и vh (ширина видового экрана/высота видового экрана)

FIDDLE

Измените размер по вертикали и по горизонтали, и вы увидите, что элемент всегда будет заполнять максимальный размер видового экрана без нарушения отношения и без полос прокрутки!

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

Ответ 3

Просто переформулировав Danield ответ в LESS mixin, для дальнейшего использования:

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

Ответ 4

Мой оригинальный вопрос для этого состоял в том, как обе имеют элемент фиксированного аспекта, но точно соответствуют этому в определенном контейнере, что делает его немного затруднительным. Если вы просто хотите, чтобы отдельный элемент поддерживал соотношение сторон, это намного проще.

Лучший метод, с которым я столкнулся, - это указать нулевую высоту элемента, а затем использовать процентное заполнение-снизу, чтобы дать ему высоту. Процент заполнения всегда пропорционален ширине элемента, а не его высоте, даже если его верхняя или нижняя прокладка.

Свойства W3C Padding

Таким образом, используя это, вы можете дать элементу процентную ширину для размещения внутри контейнера, а затем отложить, чтобы указать соотношение сторон или, другими словами, соотношение между его шириной и высотой.

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

Ответ 5

Используйте мультимедийный запрос CSS @media вместе с CSS видовых экранов vw и vh для адаптации к пропорциям видового экрана. Это полезно для обновления других свойств, таких как font-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);
  }
}

Это очень похоже в вене с max-width и max-height подход от @Danield, более гибкий.

Ответ 6

Я понимаю, что вы спросили, что вам нужно специальное решение CSS. Чтобы сохранить соотношение сторон, вам необходимо разделить высоту на желаемое соотношение сторон. 16: 9 = 1,777777777778.

Чтобы получить правильную высоту для контейнера, вам нужно будет разделить текущую ширину на 1.777777777778. Поскольку вы не можете проверить width контейнера только с CSS или делить на процент CSS, это невозможно без JavaScript (насколько мне известно).

Я написал рабочий script, который сохранит желаемое соотношение сторон.

HTML

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

CSS

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

JavaScript

window.onload = function () {
    //Let 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);

Ответ 7

ответ 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>