Поддерживайте соотношение сторон div, но заполняйте ширину и высоту экрана в CSS?


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

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

например:

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

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

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

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

какие идеи?

7 90

7 ответов:

использовать новый CSS viewport unitsvw и 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% ширины и высоты видового экрана:скрипка

* {
  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

просто переформулировать Danield ' s ответ в меньшем 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;
}

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

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

свойства заполнения 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.

использовать CSS media query@media вместе с CSS viewport unitsvw и 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подход by @Danield, просто более гибкий.

Я понимаю, что вы спросили, что вы хотели бы 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; }

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

можно использовать function опять же, если вы хотите отобразить что-то еще с другим соотношением, используя

keepAspectRatio(id, width, height);

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

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

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

ответ Данилда это хорошо, но он может быть использован только тогда, когда 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>

вот он в jsfiddle с помощью scss, что делает его более очевидным, откуда берутся значения.