Я хочу создать div
который может изменить его ширину/высоту при изменении ширины окна.
Существуют ли какие-либо правила CSS3, позволяющие изменять высоту в соответствии с шириной, сохраняя при этом соотношение сторон?
Я знаю, что могу сделать это с помощью JavaScript, но я бы предпочел использовать только CSS.
Просто создайте обертку <div>
с процентным значением для padding-bottom
, например:
div {
width: 100%;
padding-bottom: 75%;
background: gold; /** <-- For the demo **/
}
<div></div>
Это приведет к <div>
с высотой, равной 75% от ширины ее контейнера (соотношение сторон 4: 3).
Это зависит от того, что для заполнения:
Процент вычисляется по ширине сгенерированного блока, содержащего блок [...] (источник: w3.org, акцент мой)
Предельные значения для других пропорций и 100% ширины:
aspect ratio | padding-bottom value
--------------|----------------------
16:9 | 56.25%
4:3 | 75%
3:2 | 66.66%
8:5 | 62.5%
Размещение содержимого в div:
Чтобы сохранить соотношение сторон div и предотвратить его растяжение, вам нужно добавить абсолютно позиционированного дочернего элемента и растянуть его до краев обертки с помощью:
div.stretchy-wrapper {
position: relative;
}
div.stretchy-wrapper > div {
position: absolute;
top: 0; bottom: 0; left: 0; right: 0;
}
Здесь демо и еще одна более подробная демоверсия
vw
единиц:Вы можете использовать единицы vw
для ширины и высоты элемента. Это позволяет сохранить соотношение сторон элемента в зависимости от ширины окна просмотра.
vw: 1/100th ширины окна просмотра. [MDN]
В качестве альтернативы вы также можете использовать vh
для высоты окна просмотра или даже vmin
/vmax
для использования меньшего/большего размера размеров окна просмотра (обсуждение здесь).
div {
width: 20vw;
height: 20vw;
background: gold;
}
<div></div>
Для других соотношений сторон вы можете использовать следующую таблицу для вычисления значения высоты в соответствии с шириной элемента:
aspect ratio | multiply width by
-----------------------------------
1:1 | 1
1:3 | 3
4:3 | 0.75
16:9 | 0.5625
body {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
div {
width: 23vw;
height: 23vw;
margin: 0.5vw auto;
background: gold;
}
<div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
Вот скрипт с этой демонстрацией и вот решение, чтобы сделать отзывчивую сетку квадраты с вертикальным и горизонтальным центрированным контентом.
Поддержка браузера для модулей vh/vw - это IE9 + см. canIuse для получения дополнительной информации
Я нашел способ сделать это с помощью CSS, но вы должны быть осторожны, поскольку это может измениться в зависимости от потока вашего собственного веб-сайта. Я сделал это, чтобы вставлять видео с постоянным соотношением сторон в пределах ширины жидкости моего веб-сайта.
Скажем, у вас есть встроенное видео:
<object>
<param ... /><param ... />...
<embed src="..." ...</embed>
</object>
Затем вы можете разместить все это внутри div с классом "видео". Этот видеокласс, вероятно, будет жидким элементом вашего сайта, который сам по себе не имеет прямых ограничений по высоте, но при изменении размера браузера он будет меняться по ширине в соответствии с потоком веб-сайта. Это будет тот элемент, который вы, вероятно, пытаетесь подключить встроенное видео, сохраняя при этом определенное соотношение сторон видео.
Чтобы сделать это, я поместил изображение перед внедренным объектом в класс div видео.
!!! Важная часть состоит в том, что изображение имеет правильное соотношение сторон, которое вы хотите сохранить. Кроме того, убедитесь, что размер изображения максимально высок, чем самый маленький, который вы ожидаете от видео (или того, что вы поддерживаете A.R.), чтобы получить на основе вашего макета. Это позволит избежать любых возможных проблем при разрешении изображения при его изменении в процентах. Например, если вы хотите сохранить соотношение сторон 3: 2, не просто используйте изображение 3px на 2px. Он может работать при некоторых обстоятельствах, но я не проверял его, и, вероятно, было бы неплохо избежать.
Вероятно, вы уже должны иметь минимальную ширину, как это определено для жидких элементов вашего веб-сайта. Если нет, рекомендуется сделать это, чтобы избежать измельчения элементов или перекрытия, когда окно браузера становится слишком маленьким. В какой-то момент лучше иметь полосу прокрутки. Наименьшая по ширине веб-страница должна быть где-то около ~ 600 пикселей (включая столбцы фиксированной ширины), поскольку разрешение экрана меньше, если только вы не имеете дело с телефонами.!!!
Я использую полностью прозрачный png, но я действительно не думаю, что это имеет значение, если вы сделаете это правильно. Вот так:
<div class="video">
<img class="maintainaspectratio" src="maintainaspectratio.png" />
<object>
<param ... /><param ... />...
<embed src="..." ...</embed>
</object>
</div>
Теперь вы можете добавить CSS, похожий на следующее:
div.video { ...; position: relative; }
div.video img.maintainaspectratio { width: 100%; }
div.video object { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; }
div.video embed {width: 100%; height: 100%; }
Удостоверьтесь, что вы также удалили любое явное объявление высоты или ширины внутри объекта и вставляете теги, которые обычно поставляются с копией/вставленным кодом вставки.
То, как оно работает, зависит от свойств позиции элемента видеокласса и элемента, который вы хотите поддерживать с определенным соотношением сторон. Он использует то, как изображение будет поддерживать правильное соотношение сторон при изменении размера элемента. Он сообщает, что все еще находится в элементе видео класса, чтобы получить полную выгоду от недвижимости, предоставляемой динамическим изображением, заставляя ее ширину/высоту до 100% элемента видеокласса корректироваться с помощью изображения.
Довольно круто, а??
Возможно, вам придется немного поиграть с ним, чтобы заставить его работать с вашим собственным дизайном, но на самом деле это работает на удивление хорошо для меня. Существует общая концепция.
Эллиот вдохновил меня на это решение - спасибо:
aspectratio.png
- это полностью прозрачный PNG файл с размером вашего предпочтительного соотношения сторон, в моем случае 30x10 пикселей.
<div class="eyecatcher">
<img src="/img/aspectratio.png"/>
</div>
.eyecatcher img {
width: 100%;
background-repeat: no-repeat;
background-size: 100% 100%;
background-image: url(../img/autoresized-picture.jpg);
}
Обратите внимание: background-size
- это функция css3, которая может не работать с вашими целевыми браузерами. Вы можете проверить совместимость (например, caniuse.com).
Чтобы добавить к ответу на Web_Designer, <div>
будет иметь высоту (полностью состоящую из нижней части), равную 75% от ширины , содержащего элемент. Вот хорошее резюме: http://mattsnider.com/css-using-percent-for-margin-and-padding/. Я не уверен, почему это так, но как это.
Если вы хотите, чтобы ваш div был шириной, отличной от 100%, вам понадобится другой обертывающий div, на котором можно установить ширину:
div.ar-outer{
width: 60%; /* container; whatever width you want */
margin: 0 auto; /* centered if you like */
}
div.ar {
width:100%; /* 100% of width of container */
padding-bottom: 75%; /* 75% of width of container */
position:relative;
}
div.ar-inner {
position: absolute;
top: 0; bottom: 0; left: 0; right: 0;
}
В последнее время я использовал что-то похожее на трюк с изображением Эллиота, чтобы позволить мне использовать мультимедийные запросы CSS для работы с другим файлом логотипа в зависимости от разрешения устройства, но по-прежнему масштабируется пропорционально, как обычно, <img>
(я устанавливаю логотип как фон изображение к прозрачному .png с правильным соотношением сторон). Но решение Web_Designer избавит меня от HTTP-запроса.
Как указано здесь на w3schools.com и несколько повторено в этом принятом ответе, значения заполнения в процентах (акцент мой):
Определяет заполнение в процентах от ширины содержащего элемента
Ergo, правильный пример чувствительного DIV, который поддерживает соотношение сторон 16: 9, выглядит следующим образом:
CSS
.parent {
position: relative;
width: 100%;
}
.child {
position: relative;
padding-bottom: calc(100% * 9 / 16);
}
.child > div {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
HTML
<div class="parent">
<div class="child">
<div>Aspect is kept when resizing</div>
</div>
</div>
Основываясь на ваших решениях, я сделал несколько трюков:
Когда вы используете его, ваш HTML будет только
<div data-keep-ratio="75%">
<div>Main content</div>
</div>
Чтобы использовать его таким образом, выполните: CSS:
*[data-keep-ratio] {
display: block;
width: 100%;
position: relative;
}
*[data-keep-ratio] > * {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
и js (jQuery)
$('*[data-keep-ratio]').each(function(){
var ratio = $(this).data('keep-ratio');
$(this).css('padding-bottom', ratio);
});
И имея это, вы просто устанавливаете attr data-keep-ratio
на высоту/ширину и что это.
data-keep-ratio
не keep-ratio
и получить его значение, используя $(this).data('keep-ratio');
Вы можете использовать svg. Сделайте положение контейнера/обертки относительным, сначала установите svg как статически, а затем разместите абсолютно позиционированное содержимое (вверху: 0; влево: 0; вправо: 0; внизу: 0;)
Пример с пропорциями 16: 9:
image.svg: (может быть встроено в src)
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 9" width="16" height="9"/>
CSS
.container {
position: relative;
}
.content {
position: absolute;
top:0; left:0; right:0; bottom:0;
}
HTML:
<div class="container">
<img style="width: 100%" src="image.svg" />
<div class="content"></div>
</div>
Обратите внимание, что inline svg не работает, но вы можете urlencode svg и вставить его в атрибут img src следующим образом:
<img src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2016%209%22%20width%3D%2216%22%20height%3D%229%22%2F%3E" style="width: 100%;" />
Поскольку @web-tiki уже показывает способ использования vh
/vw
, мне также нужен способ сосредоточиться на экране, вот код фрагмента для портрета 9:16.
.container {
width: 100vw;
height: calc(100vw * 16 / 9);
transform: translateY(calc((100vw * 16 / 9 - 100vh) / -2));
}
translateY
будет удерживать этот центр на экране. calc(100vw * 16/9)
ожидается высота для 9/16. (100vw * 16/9 - 100vh)
является высотой переполнения, поэтому вытащить overflow height/2
будет поддерживать ее на экране.
Для пейзажа и сохранения 16: 9 вы показываете использование
.container {
width: 100vw;
height: calc(100vw * 9 / 16);
transform: translateY(calc((100vw * 9 / 16 - 100vh) / -2));
}
Коэффициент 9/16 - легкость изменения, нет необходимости в предопределении 100:56.25
или 100:75
75.Если вы хотите сначала обеспечить высоту, вы должны переключить ширину и высоту, например, height:100vh;width: calc(100vh * 9/16)
для портрета 9:16.
Если вы хотите адаптироваться для разных размеров экрана, вы также можете заинтересовать
@media (orientation: portrait)
/@media (orientation: landscape)
portrait
/landscape
для изменения отношения.Это является улучшением принятого ответа:
.box {
margin-top: 1em;
margin-bottom: 1em;
background-color: #CCC;
}
.fixed-ar::before {
content: "";
float: left;
width: 1px;
margin-left: -1px;
}
.fixed-ar::after {
content: "";
display: table;
clear: both;
}
.fixed-ar-16-9::before {
padding-top: 56.25%;
}
.fixed-ar-3-2::before {
padding-top: 66.66%;
}
.fixed-ar-4-3::before {
padding-top: 75%;
}
.fixed-ar-1-1::before {
padding-top: 100%;
}
.width-50 {
display: inline-block;
width: 50%;
}
.width-20 {
display: inline-block;
width: 20%;
}
<div class="box fixed-ar fixed-ar-16-9">16:9 full width</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-50">16:9</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-20">16:9</div>
<div class="box fixed-ar fixed-ar-3-2 width-20">3:2</div>
<div class="box fixed-ar fixed-ar-4-3 width-20">4:3</div>
<div class="box fixed-ar fixed-ar-1-1 width-20">1:1</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-20">16:9</div>
<div class="box fixed-ar fixed-ar-16-9 width-50">16:9</div>
html выглядит следующим образом:
<div class='container'>
<div class='element'>
</div><!-- end of element -->
скажет, что вам нужно сохранить соотношение "элемент"
css выглядит следующим образом
.container{
position: relative;
height: 0
padding-bottom : 75% /* for 4 to 3 ratio */ 25% /* for 4 to 1 ratio ..*/
}
.element{
width : 100%;
height: 100%;
position: absolute;
top : 0 ;
bottom : 0 ;
background : red; /* just for illustration */
}
заполнение, если указано в%, оно рассчитывается на основе ширины не высоты. .. так что в основном вам не важно, на какой основе ваша высота будет всегда рассчитываться на основе этого. который будет поддерживать соотношение.
SCSS - лучшее решение в моем случае; используя атрибут data:
[data-aspect-ratio] {
display: block;
max-width: 100%;
position: relative;
&:before {
content: '';
display: block;
}
> * {
display: block;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
}
[data-aspect-ratio="3:1"]:before {
padding-top: 33.33%;
}
[data-aspect-ratio="2:1"]:before {
padding-top: 50%;
}
[data-aspect-ratio="16:9"]:before {
padding-top: 56.25%;
}
[data-aspect-ratio="3:2"]:before {
padding-top: 66.66%;
}
[data-aspect-ratio="4:3"]:before {
padding-top: 75%;
}
[data-aspect-ratio="1:1"]:before {
padding-top: 100%;
}
[data-aspect-ratio="3:4"]:before {
padding-top: 133.33%;
}
[data-aspect-ratio="2:3"]:before {
padding-top: 150%;
}
[data-aspect-ratio="9:16"]:before {
padding-top: 177.77%;
}
[data-aspect-ratio="1:2"]:before {
padding-top: 200%;
}
[data-aspect-ratio="1:3"]:before {
padding-top: 300%;
}
Например:
<div data-aspect-ratio="16:9"><iframe ...></iframe></div>
[data-aspect-ratio]
доступен для вас в CSS.
Просто идея или взлома.
div {
background-color: blue;
width: 10%;
transition: background-color 0.5s, width 0.5s;
font-size: 0;
}
div:hover {
width: 20%;
background-color: red;
}
img {
width: 100%;
height: auto;
visibility: hidden;
}
<div>
<!-- use an image with target aspect ratio. sample is a square -->
<img src="http://i.imgur.com/9OPnZNk.png" />
</div>
Если вы хотите поместить квадрат внутри окна просмотра на любом портретном или альбомном представлении (насколько это возможно, но ничего не торчит снаружи), переключайтесь между использованием vw
/vh
при ориентации portrait
/landscape
@media (orientation:portrait ) {
.square {
width :100vw;
height:100vw;
}
}
@media (orientation:landscape) {
.square {
width :100vh;
height:100vh;
}
}
Я столкнулся с этой проблемой довольно часто, поэтому я сделал для нее решение JS. Это в основном регулирует высоту domElement по ширине элемента по указанному вами соотношению. Вы можете использовать его следующим образом:
<div ratio="4x3"></div>
Помните, что поскольку он устанавливает высоту элемента, элемент должен быть либо display:block
, либо display:inline-block
.
В то время как большинство ответов очень классные, большинство из них требуют правильного размера изображения... Другие решения работают только по ширине и не заботятся о высоте, но иногда вы хотите поместить контент в определенная высота тоже.
Я попытался связать их вместе, чтобы принести полностью портативное и многозначное решение... Фокус в том, чтобы использовать для автоматического масштабирования изображения, но использовать встроенный элемент svg вместо использования предварительно визуализированного изображения или любой формы второго HTTP-запроса...
div.holder{
background-color:red;
display:inline-block;
height:100px;
width:400px;
}
svg, img{
background-color:blue;
display:block;
height:auto;
width:auto;
max-width:100%;
max-height:100%;
}
.content_sizer{
position:relative;
display:inline-block;
height:100%;
}
.content{
position:absolute;
top:0;
bottom:0;
left:0;
right:0;
background-color:rgba(155,255,0,0.5);
}
<div class="holder">
<div class="content_sizer">
<svg width=10000 height=5000 />
<div class="content">
</div>
</div>
</div>
Обратите внимание, что я использовал большие значения в атрибутах width и height SVG, так как он должен быть больше максимального ожидаемого размера, поскольку он может только уменьшаться. Пример делает соотношение div 10: 5
Я наткнулся на умное решение, используя <svg>
и display:grid
.
Элемент Grid позволяет вам занять одно и то же пространство с двумя (или более) элементами, не указывая, какой из них задает высоту. Это означает, что из коробки более высокий устанавливает отношение.
Это означает, что вы можете использовать его, как только вы знаете, что контент никогда не будет достаточно высоким, чтобы заполнить все "соотношение", и вы просто ищете способ разместить контент в этом пространстве (т.е. Центрировать его в обоих направлениях display:flex; align-items:center; justify-content:center
).
Это почти так же, как использование прозрачного <img>
с display:block
и предопределенное соотношение, за исключением того, что <svg>
легче и значительно легче модифицировать (чтобы изменить отношение, если вам нужно).
<div class="ratio">
<svg viewBox="0 0 1 1"></svg>
<div>
I'm square
</div>
</div>
.ratio {
display: grid;
}
.ratio > * {
grid-area: 1/1/1/1;
}
Все, что вам нужно сделать, это изменить соотношение <svg>
:
<svg viewBox="0 0 4 3"></svg>
<svg viewBox="0 0 16 9"></svg>
См. Работу:
.ratio {
display: grid;
}
.ratio > * {
grid-area: 1/1/1/1;
}
/* below code NOT needed for setting the ratio
* I just wanted to mark it visually
* and center contents
*/
.ratio div {
border: 1px solid red;
display: flex;
align-items: center;
justify-content: center;
}
<div class="ratio">
<svg viewBox="0 0 7 1"></svg>
<div>
Fixed ratio 7:1
</div>
</div>
Если вам нужно решение, в котором элементу контента не разрешено устанавливать коэффициент, когда он выше (с переполнением скрытым или автоматическим), вам необходимо установить position:relative
по сетке и position:absolute; height:100%; overflow-y: auto;
position:absolute; height:100%; overflow-y: auto;
по содержанию. Пример:
.ratio {
display: grid;
position: relative;
}
.ratio > * {
grid-area: 1/1/1/1;
}
.ratio > div {
height: 100%;
overflow-y: auto;
position: absolute;
/* the rest is not needed */
border: 1px solid red;
padding: 0 1rem;
}
<div class="ratio">
<svg viewBox="0 0 7 1"></svg>
<div>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. A scelerisque purus semper eget. Sem nulla pharetra diam sit amet nisl suscipit adipiscing bibendum. A cras semper auctor neque vitae tempus quam pellentesque nec. Morbi enim nunc faucibus a pellentesque sit amet porttitor. Arcu odio ut sem nulla. Sed viverra ipsum nunc aliquet bibendum enim facilisis gravida neque. Cras tincidunt lobortis feugiat vivamus at augue eget. Laoreet sit amet cursus sit amet. Amet nulla facilisi morbi tempus iaculis urna id volutpat. Leo in vitae turpis massa sed elementum tempus egestas sed. Egestas integer eget aliquet nibh. Dolor sit amet consectetur adipiscing elit.
<p>Ut aliquam purus sit amet. Eget magna fermentum iaculis eu non diam phasellus vestibulum. Diam in arcu cursus euismod quis viverra nibh. Nullam vehicula ipsum a arcu cursus vitae congue. Vel orci porta non pulvinar neque laoreet suspendisse. At tellus at urna condimentum mattis pellentesque. Tristique senectus et netus et malesuada. Vel pretium lectus quam id leo in. Interdum velit euismod in pellentesque. Velit euismod in pellentesque massa placerat duis. Vitae suscipit tellus mauris a diam maecenas sed enim.
<p>Mauris a diam maecenas sed enim ut sem. In hendrerit gravida rutrum quisque. Amet dictum sit amet justo donec enim diam. Diam vulputate ut pharetra sit amet aliquam id. Urna porttitor rhoncus dolor purus non enim praesent. Purus in massa tempor nec feugiat nisl pretium. Sagittis vitae et leo duis ut. Facilisi nullam vehicula ipsum a arcu cursus vitae congue mauris. Volutpat odio facilisis mauris sit amet massa vitae tortor condimentum. Aliquam purus sit amet luctus venenatis lectus magna. Sit amet purus gravida quis blandit turpis. Enim eu turpis egestas pretium aenean. Consequat mauris nunc congue nisi. Nunc sed id semper risus in hendrerit gravida rutrum. Ante metus dictum at tempor. Blandit massa enim nec dui nunc mattis enim ut.
</div>
</div>
Скажите, что вы поддерживаете Width: 100px и Height: 50px (т.е. 2: 1). Просто выполните эту математику:
.pb-2to1 {
padding-bottom: calc(50 / 100 * 100%); // i.e., 2:1
}
Вы можете использовать флеш-макет (FWD).
https://en.wikipedia.org/wiki/Adaptive_web_design
Он будет масштабировать и поддерживать макет, его бит сложный, но позволяет изменять размер страницы, не нажимая на такой контент (RWD).
Он выглядит отзывчивым, но он масштабируется. https://www.youtube.com/watch?v=xRcBMLI4jbg
Формулу масштабирования CSS можно найти здесь:
Я использовал новое решение.
.squares{
width: 30vw
height: 30vw
К основному соотношению сторон
.aspect-ratio
width: 10vw
height: 10vh
Однако это касается всего окна просмотра. Итак, если вам нужен div, который составляет 30% ширины видового экрана, вы можете использовать 30vw вместо этого, и, поскольку вы знаете ширину, вы повторно используете их по высоте, используя блок calc и vw.
Если бы вся структура контейнера была основана на процентах, это было бы поведением по умолчанию, можете ли вы предоставить более конкретный пример?
Ниже приведен пример того, что я имею в виду, если бы вся ваша родительская иерархия была% на основе, любая настройка окна браузера работала бы без каких-либо дополнительных js/css, разве это не возможно с вашим макетом?
<div style="width: 100%;">
<div style="width: 50%; margin: 0 auto;">Content</div>
</div>