Поддерживайте соотношение сторон div, но заполняйте ширину и высоту экрана в CSS?
у меня есть сайт, чтобы собрать, что имеет фиксированное соотношение сторон примерно 16:9
пейзаж, как видео.
Я хочу, чтобы он центрировался и расширялся, чтобы заполнить доступную ширину и доступную высоту, но никогда не увеличивался с обеих сторон.
например:
- высокая и тонкая страница будет иметь содержимое, растягивающееся на всю ширину при сохранении пропорциональной высоты.
- короткая широкая страница будет иметь содержание, растягивающееся на всю высоту, с пропорциональной шириной.
есть два метода, которые я рассматривал:
- используйте изображение с правильным соотношением сторон, чтобы развернуть контейнер
div
, но я не мог заставить его вести себя одинаково во всех основных браузерах. - установка пропорционального Нижнего заполнения, но это работает только относительно ширины и игнорирует высоту. Он просто продолжает становиться больше с шириной и отображает вертикальные полосы прокрутки.
Я знаю, что вы могли бы сделать это с JS довольно легко, но я хотел бы чистое решение CSS.
какие идеи?
7 ответов:
использовать новый CSS viewport units
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% ширины и высоты видового экрана:скрипка
* { 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; }
мой первоначальный вопрос для этого состоял в том, как иметь элемент фиксированного аспекта, но точно вписать его в указанный контейнер, что делает его немного неудобным. Если вы просто хотите, чтобы отдельный элемент поддерживал свое соотношение сторон, это намного проще.
лучший метод, с которым я столкнулся,-это дать элементу нулевую высоту, а затем использовать процентное заполнение-дно, чтобы дать ему высоту. Процент заполнения всегда пропорционален ширине элемента, а не его высота, даже если ее верхняя или нижняя обивка.
таким образом, используя, что вы можете дать элементу процентную ширину, чтобы сидеть в контейнере, а затем заполнить, чтобы указать соотношение сторон или, другими словами, отношение между его шириной и высотой.
.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, что делает его более очевидным, откуда берутся значения.