Я пытаюсь совместить object-fit: contains с aspect-ratio: 1.5 /* hardcoded number */ на img.
Однако изображение остается квадратным:
// Javascript for example resizing panels only.
const leftPanel = document.querySelector('.left-panel');
const rightPanel = document.querySelector('.right-panel');
const panelHandle = document.querySelector('.panel-handle');
let isDragging = false;
panelHandle.addEventListener('mousedown', (e) => {
isDragging = true;
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
});
function onMouseMove(e) {
if (!isDragging) return;
const containerWidth = document.body.clientWidth;
const newLeftWidth = e.clientX;
if (newLeftWidth < 0 || newLeftWidth > containerWidth - panelHandle.offsetWidth) return;
const newRightWidth = containerWidth - newLeftWidth - panelHandle.offsetWidth;
leftPanel.style.width = `${newLeftWidth}px`;
rightPanel.style.width = `${newRightWidth}px`;
}
function onMouseUp() {
isDragging = false;
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
}/* img scaling */
img {
width: 100%;
height: 100%;
object-fit: contain;
/* has no effect */
aspect-ratio: 1.5;
}
/* panel resizing */
body {
display: flex;
height: 100vh;
margin: 0;
overflow: hidden;
user-select: none;
}
.left-panel,
.right-panel {
height: 100%;
}
.left-panel {
background-color: lightblue;
width: 50%;
}
.right-panel {
background-color: lightcoral;
flex-grow: 1;
text-align: center;
}
.panel-handle {
width: 10px;
background-color: gray;
cursor: ew-resize;
}<div class = "left-panel">
<img src = "https://picsum.photos/400" draggable = "false" />
</div>
<div class = "panel-handle">
</div>
<div class = "right-panel">
<div>
Drag the center bar to resize these panels.
</div>
<div>
The image should be a 3:2 aspect ratio but is it's instrinsic square.
</div>
</div>Я хочу перевести изображение в aspect-ratio: 1.5, а затем использовать автоматический почтовый ящик.
Концептуально я хочу установить aspect-ratio: 1.5, а затем css выбрать либо width: 100%, либо height: 100% в зависимости от соотношения сторон контейнера.
Возможно ли это в чистом CSS? Многие связанные с этим вопросы касаются сохранения существующего соотношения сторон изображения, а это не то, чего я хочу.
X вместо моего Y : у меня есть изображение с сервера с неправильным соотношением сторон. Сервер — это какое-то прошивочное устройство, которое выводит изображение с соотношением сторон, в два раза превышающим должное (по техническим причинам). Я знаю правильное соотношение сторон дисплея и могу установить его напрямую. <img /> находится внутри динамического контейнера, например. из панелей с изменяемым размером.
Редактировать:
Текущее поведение (изображение обычной сетки с квадратным соотношением сторон):
Желаемое поведение






Не совсем понятно, чего вы пытаетесь достичь. Но вы можете поместить img с object-fit: contain в div, в котором будет aspect-ratio: 1.5:
// Javascript for example resizing panels only.
const leftPanel = document.querySelector('.left-panel');
const rightPanel = document.querySelector('.right-panel');
const panelHandle = document.querySelector('.panel-handle');
let isDragging = false;
panelHandle.addEventListener('mousedown', (e) => {
isDragging = true;
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
});
function onMouseMove(e) {
if (!isDragging) return;
const containerWidth = document.body.clientWidth;
const newLeftWidth = e.clientX;
if (newLeftWidth < 0 || newLeftWidth > containerWidth - panelHandle.offsetWidth) return;
const newRightWidth = containerWidth - newLeftWidth - panelHandle.offsetWidth;
leftPanel.style.width = `${newLeftWidth}px`;
rightPanel.style.width = `${newRightWidth}px`;
}
function onMouseUp() {
isDragging = false;
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
}/* img scaling */
.left-panel-img{
aspect-ratio: 1.5;
max-height:100%;
max-width:100%;
margin:auto;
outline:solid 1px yellow;
}
img {
width:100%;
height:100%;
object-fit: contain;
}
/* panel resizing */
body {
display: flex;
height: 100vh;
margin: 0;
overflow: hidden;
user-select: none;
}
.left-panel,
.right-panel {
height: 100%;
}
.left-panel {
background-color: lightblue;
width: 50%;
display:flex;
flex-direction:column;
}
.right-panel {
background-color: lightcoral;
flex-grow: 1;
text-align: center;
}
.panel-handle {
width: 10px;
background-color: gray;
cursor: ew-resize;
}<div class = "left-panel">
<div class = "left-panel-img">
<img src = "https://picsum.photos/400" draggable = "false" />
</div>
</div>
<div class = "panel-handle">
</div>
<div class = "right-panel">
<div>
Drag the center bar to resize these panels.
</div>
<div>
The image should be a 3:2 aspect ratio but is it's instrinsic square.
</div>
</div>Тогда просто ставь object-fit: cover
Чтобы изображение соответствовало определенному соотношению сторон, у вас есть три варианта:
object-fit: containobject-fit: coverobject-fit или используйте object-fit: fill (значение по умолчанию)Кажется, вы хотите исказить изображение, поэтому просто удалите свой object-fitстиль.
// Javascript for example resizing panels only.
const leftPanel = document.querySelector('.left-panel');
const rightPanel = document.querySelector('.right-panel');
const panelHandle = document.querySelector('.panel-handle');
let isDragging = false;
panelHandle.addEventListener('mousedown', (e) => {
isDragging = true;
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
});
function onMouseMove(e) {
if (!isDragging) return;
const containerWidth = document.body.clientWidth;
const newLeftWidth = e.clientX;
if (newLeftWidth < 0 || newLeftWidth > containerWidth - panelHandle.offsetWidth) return;
const newRightWidth = containerWidth - newLeftWidth - panelHandle.offsetWidth;
leftPanel.style.width = `${newLeftWidth}px`;
rightPanel.style.width = `${newRightWidth}px`;
}
function onMouseUp() {
isDragging = false;
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
}.left-panel-img {
aspect-ratio: 1.5;
max-height: 100%;
width: 100%;
margin: auto;
border: 3px solid yellow;
box-sizing: border-box;
overflow: hidden;
}
img {
width: 100%;
height: 100%;
}
body {
display: flex;
height: 100vh;
margin: 0;
overflow: hidden;
user-select: none;
}
.left-panel,
.right-panel {
height: 100%;
}
.left-panel {
background-color: lightblue;
width: 50%;
display:flex;
flex-direction:column;
}
.right-panel {
background-color: lightcoral;
flex-grow: 1;
text-align: center;
}
.panel-handle {
width: 10px;
background-color: gray;
cursor: ew-resize;
}<div class = "left-panel">
<div class = "left-panel-img">
<img src = "https://picsum.photos/400" draggable = "false" />
</div>
</div>
<div class = "panel-handle">
</div>
<div class = "right-panel">
<div>
Drag the center bar to resize these panels.
</div>
<div>
The image should be a 3:2 aspect ratio but is it's instrinsic square.
</div>
</div>Спасибо! Это очень близко. Единственная небольшая проблема заключается в том, что если изображение недостаточно велико, оно не будет расширяться, чтобы заполнить рамку (например, измените src на /100 или откройте пример на полной странице и разверните левую панель). Например: jsfiddle.net/4odw68uq/14
Ах, подождите, извините, это обрезает изображение, а это не то, что мне нужно. Ясно, что мой вопрос не имеет смысла, я отредактирую некоторые скриншоты и фотошопы.
Я скорректировал фрагмент, чтобы сделать контейнер width: 100% вместо max-width: 100%. Это растягивает контейнер, который затем растягивает изображение, если оно маленькое. И я добавил второй фрагмент, который растягивает (искажает) изображение, а не обрезает его, если вам действительно нужен именно этот эффект. Обратите внимание, что важно четко и точно описать ваши требования. В любом случае, если вы хотите, чтобы изображение соответствовало определенному соотношению сторон, вы можете выбрать: (а) почтовый ящик (с object-fit: contain), (б) клип (с object-fit: cover) или (в) искажать (без object-fit).
Честно говоря, я думал, что ясно описал свои требования, но, видимо, нет. Извинения. Я добавил несколько изображений в свой пост, чтобы объяснить дальше. «Желаемый» набор изображений был создан путем ручного выбора width: 100% или height: 100% в зависимости от размера панели.
Хорошо, вы хотите исказить изображение, это теперь ясно. Одна картинка стоит тысячи слов. Я обновил свой ответ.
1) Это хорошо работает (по крайней мере, в Firefox), когда панель узкая, но не когда она широкая. 2) Кажется, это не меняет соотношение сторон изображения в Chrome :(
Фрагмент обновлен, чтобы устранить проблему, видимую в Chrome. Вам просто нужно добавить overflow: hidden в контейнер соотношения сторон.
Я очень ценю время, которое вы потратили на это. Однако это работает только для одной оси: если панель становится широкой, изображение начинает растягиваться, чтобы заполнить всю панель, а не иметь полосы слева и справа. Я выяснил, как правильно задать размер изображения по обеим осям, здесь: jsfiddle.net/jwtsm3g1/277. Теперь проблема в том, как это центрировать (мне пришлось удалить флексбокс, чтобы этот размер заработал). Может быть отвлекающий маневр.
Думаю, что понял, напишу ответ. Еще раз спасибо.
Спасибо другим ответившим за потраченное время.
Я нашел свой ответ здесь: https://stackoverflow.com/a/66721382/3554391
Не могу объяснить, почему это работает, но вот и все.
// Javascript for example resizing panels only.
const leftPanel = document.querySelector('.left-panel');
const rightPanel = document.querySelector('.right-panel');
const panelHandle = document.querySelector('.panel-handle');
let isDragging = false;
panelHandle.addEventListener('mousedown', (e) => {
isDragging = true;
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
});
function onMouseMove(e) {
if (!isDragging) return;
const containerWidth = document.body.clientWidth;
const newLeftWidth = e.clientX;
if (newLeftWidth < 0 || newLeftWidth > containerWidth - panelHandle.offsetWidth) return;
const newRightWidth = containerWidth - newLeftWidth - panelHandle.offsetWidth;
leftPanel.style.width = `${newLeftWidth}px`;
rightPanel.style.width = `${newRightWidth}px`;
}
function onMouseUp() {
isDragging = false;
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
}/* img scaling */
.left-panel {
position: relative;
}
.left-panel-img-wrapper {
position: absolute;
margin: auto;
left: 0;
right: 0;
top: 0;
bottom: 0;
max-width: 100%;
max-height: 100%;
aspect-ratio: 1.5;
}
img {
width: 100%;
height: 100%;
display: block;
}
/* panel resizing */
body {
display: flex;
height: 100vh;
margin: 0;
overflow: hidden;
user-select: none;
}
.left-panel,
.right-panel {
height: 100%;
}
.left-panel {
background-color: lightblue;
width: 50%;
}
.right-panel {
background-color: lightcoral;
flex-grow: 1;
text-align: center;
}
.panel-handle {
width: 10px;
background-color: gray;
cursor: ew-resize;
}<div class = "left-panel">
<div class = "left-panel-img-wrapper">
<img class = "left-panel-img" src = "data:image/bmp;base64,Qk2mAAAAAAAAAD4AAAAoAAAADQAAAA0AAAABAAQAAAAAAAAAAADEDgAAxA4AAAIAAAACAAAAAAAA//////8AAAAAAAAAAAERAREBEQAAAREBEQERAAABEQERAREAAAAAAAAAAAAAAREBEQERAAABEQERAREAAAERAREBEQAAAAAAAAAAAAABEQERAREAAAERAREBEQAAAREBEQERAAAAAAAAAAAAAA= = " draggable = "false" />
</div>
</div>
<div class = "panel-handle">
</div>
<div class = "right-panel">
<div>
Drag the center bar to resize these panels.
</div>
<div>The image to the left should be 3:2 and centered in its panel vertically and horizontally.</div>
</div>
Извините, что не ясно. В вашем примере я хочу, чтобы изображение вело себя точно так же, как ваш
left-panel-imgdiv, при этом изображение было растянуто до соотношения сторон 3:2.