Я хочу изменить размер фонового изображения CSS (без сохранения соотношения сторон), и потом применит background-size: contain
к тому же изображению. В противном случае действие опции contain
в некоторой степени нивелируется.
Можно ли это сделать с помощью HTML / CSS или нужно использовать Javascript? Предварительное редактирование изображений вручную в моем случае невозможно.
http://jsfiddle.net/h5a2nxfd/68/
У меня есть несколько изображений, которые я хотел бы отобразить с измененным соотношением сторон по бокам или сверху вниз, в зависимости от того, активен ли альбомный или портретный режим. В приведенном выше JSFiddle отсутствует изменение размера.
Я пробовал использовать transform
для масштабирования, но в текущем решении ширина / высота div.item
является переменной, поэтому это не очень выполнимо.
Я открыт для ваших предложений. Возможно, я пытаюсь подойти к этой проблеме с неправильной точки зрения. Но я бы предпочел не использовать Javascript.
Обновлено: добавлены круги к образцам изображений SVG, используемых в JSFiddle.
Как выбрать желаемое измененное соотношение сторон?
@kenS - хороший аргумент. Я обновил JSFiddle.
@vals Требуемое соотношение сторон является постоянным и известно заранее, и в настоящее время оно будет одинаковым для всех рассматриваемых изображений. В настоящее время желаемое соотношение сторон составляет 4: 3.
Я не знаю, чего именно вы пытаетесь достичь, попробуйте установить размер фона на 100%, а не содержать
Если вы можете использовать решение HTML и CSS, а не просто решение на чистом CSS, следующее работает путем вложения изображений внутри div
, что позволяет более эффективно разделять стили изменения размеров гибких элементов и стили изображений. Вы можете установить стили для гибкого элемента, чтобы определить размер блока, в котором будет находиться .image
, и / или установить ширину и высоту на самом .image
, чтобы изменить соотношение сторон изображения. Обратите внимание: чтобы сделать это более оперативно, вместо того, чтобы устанавливать фиксированные значения ширины и высоты для контейнера, я создал контейнеры фиксированное соотношение сторон для .image
. Вы можете изменить соотношение сторон в зависимости от ваших потребностей. Я также использовал img
вместо div
с фоновыми изображениями, что дает вам немного больше контроля над соотношением сторон прямо из коробки (т.е. в отличие от div
явная ширина и height: auto;
на img
приведет к сохранению соотношения сторон, а также width: auto;
и явная высота, которая может быть полезна, когда ваш макет переключается с строкового макета flexbox на столбцовый).
Еще одно потенциальное преимущество, которое может дать использование тегов img
, а не div
с фоновыми изображениями, - это использование свойства object-fit: contain;
(или object-fit: scale-down;
, если вы хотите, чтобы изображение только уменьшалось, а не увеличивалось), вместо того, чтобы устанавливать ширину и высоту изображения на 100%. контейнер ограничен соответствующим соотношением сторон или использует background-size: contain;
на div
с фоновым изображением. См. MDN для справки по object-fit
, включая информацию о поддержке браузера.
Вот фрагмент рабочего кода с тегами img
, помещенными в поля соотношения сторон, причем их соотношения сторон не сохраняются в запросах вопроса:
document.body.addEventListener("click", function() {
document.body.classList.toggle("portrait");
});
html,
body {
height: 100%;
}
.container {
height: auto;/*you had this as 100%. If you are going to constrain the height of your container, then you need to constrain the height of the items too to make sure they still fit inside, ie put max-height: 50%; on the items inside the container.*/
width: 100%;
display: flex;
flex-flow: row wrap;
/*align-items: stretch;*//*align-items: stretch; will cause potential problems with your layout if you intend for there to be more than 1 item per row/column*/
}
/*body.portrait .container {
flex-direction: column;
}*/
.item {
/*flex-grow: 1;*//*flex-grow: 1; will likewise cause potential problems with your layout if you intend for there to be more than 1 item per row/column*/
width: 50%;/*can use width auto with images that have an intrinsic width to let image size determine width, or can set an explicit width as I have done here (for 1 image per row 100%, for 2 images per row 50%, etc)*/
}
.aspect-ratio-box-outer {
position: relative;
width: 100%;
height: 0;
padding: 0 0 75%;
margin: 0;
}
.aspect-ratio-box-inner {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.item .image {
background-repeat: no-repeat;
background-position: center;
background-size: 100% 100%;
width: 100%;
height: 100%;
}
body.portrait .aspect-ratio-box-outer {
padding: 0 0 133.33333%;
}
/* The images are inline SVG for demonstration purposes only */
/*.item.first {
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='500' height='400'><rect width='100%' height='100%' style='fill: red' /><circle cx='50%' cy='50%' r='150' style='fill: black' /></svg>");
}*/
/*.item.second {
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='500' height='400'><rect width='100%' height='100%' style='fill: blue' /><circle cx='50%' cy='50%' r='150' style='fill: black' /></svg>");
}*/
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8">
<title>Stackoverflow question</title>
</head>
<body>
<p>
Click to toggle between landscape and portrait mode.
</p>
<div class = "container">
<div class = "item first">
<div class = "aspect-ratio-box-outer">
<div class = "aspect-ratio-box-inner">
<!--<div class = "image"></div>-->
<img class = "image" src = "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='500' height='400'><rect width='100%' height='100%' style='fill: red' /><circle cx='50%' cy='50%' r='150' style='fill: black' /></svg>" alt = "" />
</div>
</div>
</div>
<div class = "item second">
<div class = "aspect-ratio-box-outer">
<div class = "aspect-ratio-box-inner">
<!--<div class = "image"></div>-->
<img class = "image" src = "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='500' height='400'><rect width='100%' height='100%' style='fill: blue' /><circle cx='50%' cy='50%' r='150' style='fill: black' /></svg>" alt = "" />
</div>
</div>
</div>
</div>
</body>
</html>
Спасибо за ваш ответ. Однако я вижу пару проблем с решением, для которого вы предоставили код. Мне нужно, чтобы изображения занимали как можно больше места в контейнере, оставаясь при этом «содержащимся», но ваше решение не реагирует на изменение размера окна (посмотрите, как мой JSFiddle реагирует на изменение размера). Легче исправить то, что в портретном режиме соотношение сторон должно быть 4: 3, но не 3: 4. Но еще раз спасибо за ваши мысли. Мне также было бы интересно увидеть блоки с фиксированным соотношением сторон и решения для тегов img.
Да, это будет означать, что вам следует использовать поля соотношения сторон, а не поля фиксированной ширины в моем текущем фрагменте. Не стесняйтесь попробовать, основываясь на ссылке css-tricks в моем сообщении. Я занят большую часть сегодняшнего дня, но обновлю свой ответ, включив демонстрацию окон с соотношением сторон, когда у меня будет возможность
Я обновил свой ответ, чтобы использовать поля соотношения сторон, а также теги img
, а не div
с фоновыми изображениями. Фрагмент делает то, о чем, как я понимаю, вы просите, искажая изображения и не сохраняя их соотношение сторон, а не обрезая их, чтобы они соответствовали вашим желаемым контейнерам с соотношением сторон 4: 3.
Я создал модификацию вашего решения здесь: jsfiddle.net/h5a2nxfd/74 К сожалению, решение не обрабатывает случаи, когда не хватает высоты экрана для размещения изображений. Если высоты экрана недостаточно, размер изображений следует изменить, чтобы они поместились в контейнере (например, они находятся в JSFiddle исходного сообщения).
Просто примечание: может быть более полезно использовать образцы фоновых изображений, которые похожи на круги или что-то в вашем фрагменте кода, поскольку с прямоугольниками сплошного цвета невозможно определить разницу, глядя на них, были ли они перекошены в другое соотношение сторон или просто обрезано.