Сочетание соответствия объекта: содержит и жестко запрограммированное соотношение сторон в img

Я пытаюсь совместить 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 /> находится внутри динамического контейнера, например. из панелей с изменяемым размером.

Редактировать:

Текущее поведение (изображение обычной сетки с квадратным соотношением сторон):

  • Адаптивный размер
  • Не учитываю мое соотношение сторон

и

Желаемое поведение

  • Адаптивный размер
  • Принудительно установить соотношение сторон 3:2, игнорируя исходный размер изображения.

и

Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
0
0
67
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Не совсем понятно, чего вы пытаетесь достичь. Но вы можете поместить 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>

Извините, что не ясно. В вашем примере я хочу, чтобы изображение вело себя точно так же, как ваш left-panel-img div, при этом изображение было растянуто до соотношения сторон 3:2.

MHebes 30.05.2024 23:31

Тогда просто ставь object-fit: cover

imhvost 31.05.2024 11:17

Чтобы изображение соответствовало определенному соотношению сторон, у вас есть три варианта:

  1. Почтовый ящик – с object-fit: contain
  2. Клип – с object-fit: cover
  3. Искажение – опустите object-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

MHebes 31.05.2024 02:13

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

MHebes 31.05.2024 02:23

Я скорректировал фрагмент, чтобы сделать контейнер width: 100% вместо max-width: 100%. Это растягивает контейнер, который затем растягивает изображение, если оно маленькое. И я добавил второй фрагмент, который растягивает (искажает) изображение, а не обрезает его, если вам действительно нужен именно этот эффект. Обратите внимание, что важно четко и точно описать ваши требования. В любом случае, если вы хотите, чтобы изображение соответствовало определенному соотношению сторон, вы можете выбрать: (а) почтовый ящик (с object-fit: contain), (б) клип (с object-fit: cover) или (в) искажать (без object-fit).

Brett Donald 31.05.2024 02:32

Честно говоря, я думал, что ясно описал свои требования, но, видимо, нет. Извинения. Я добавил несколько изображений в свой пост, чтобы объяснить дальше. «Желаемый» набор изображений был создан путем ручного выбора width: 100% или height: 100% в зависимости от размера панели.

MHebes 31.05.2024 02:38

Хорошо, вы хотите исказить изображение, это теперь ясно. Одна картинка стоит тысячи слов. Я обновил свой ответ.

Brett Donald 31.05.2024 02:40

1) Это хорошо работает (по крайней мере, в Firefox), когда панель узкая, но не когда она широкая. 2) Кажется, это не меняет соотношение сторон изображения в Chrome :(

MHebes 31.05.2024 02:51

Фрагмент обновлен, чтобы устранить проблему, видимую в Chrome. Вам просто нужно добавить overflow: hidden в контейнер соотношения сторон.

Brett Donald 31.05.2024 05:40

Я очень ценю время, которое вы потратили на это. Однако это работает только для одной оси: если панель становится широкой, изображение начинает растягиваться, чтобы заполнить всю панель, а не иметь полосы слева и справа. Я выяснил, как правильно задать размер изображения по обеим осям, здесь: jsfiddle.net/jwtsm3g1/277. Теперь проблема в том, как это центрировать (мне пришлось удалить флексбокс, чтобы этот размер заработал). Может быть отвлекающий маневр.

MHebes 31.05.2024 05:55

Думаю, что понял, напишу ответ. Еще раз спасибо.

MHebes 31.05.2024 06:02
Ответ принят как подходящий

Спасибо другим ответившим за потраченное время.

Я нашел свой ответ здесь: 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>

Другие вопросы по теме