Измените размер фонового изображения перед применением contain / cover

Общий вопрос:

Я хочу изменить размер фонового изображения CSS (без сохранения соотношения сторон), и потом применит background-size: contain к тому же изображению. В противном случае действие опции contain в некоторой степени нивелируется.

Можно ли это сделать с помощью HTML / CSS или нужно использовать Javascript? Предварительное редактирование изображений вручную в моем случае невозможно.

Мой вариант использования:

http://jsfiddle.net/h5a2nxfd/68/

У меня есть несколько изображений, которые я хотел бы отобразить с измененным соотношением сторон по бокам или сверху вниз, в зависимости от того, активен ли альбомный или портретный режим. В приведенном выше JSFiddle отсутствует изменение размера.

Я пробовал использовать transform для масштабирования, но в текущем решении ширина / высота div.item является переменной, поэтому это не очень выполнимо.

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

Обновлено: добавлены круги к образцам изображений SVG, используемых в JSFiddle.

Просто примечание: может быть более полезно использовать образцы фоновых изображений, которые похожи на круги или что-то в вашем фрагменте кода, поскольку с прямоугольниками сплошного цвета невозможно определить разницу, глядя на них, были ли они перекошены в другое соотношение сторон или просто обрезано.

kenS 10.08.2018 15:38

Как выбрать желаемое измененное соотношение сторон?

vals 10.08.2018 17:30

@kenS - хороший аргумент. Я обновил JSFiddle.

Magnus Teekivi 11.08.2018 10:19

@vals Требуемое соотношение сторон является постоянным и известно заранее, и в настоящее время оно будет одинаковым для всех рассматриваемых изображений. В настоящее время желаемое соотношение сторон составляет 4: 3.

Magnus Teekivi 11.08.2018 10:21
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Введение в 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. Это простой сайт, ничего вычурного. Основная цель -...
CSS: FlexBox
CSS: FlexBox
Ранее разработчики использовали макеты с помощью Position и Float. После появления flexbox сценарий полностью изменился.
1
4
57
2

Ответы 2

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

Magnus Teekivi 11.08.2018 10:35

Да, это будет означать, что вам следует использовать поля соотношения сторон, а не поля фиксированной ширины в моем текущем фрагменте. Не стесняйтесь попробовать, основываясь на ссылке css-tricks в моем сообщении. Я занят большую часть сегодняшнего дня, но обновлю свой ответ, включив демонстрацию окон с соотношением сторон, когда у меня будет возможность

kenS 12.08.2018 13:46

Я обновил свой ответ, чтобы использовать поля соотношения сторон, а также теги img, а не div с фоновыми изображениями. Фрагмент делает то, о чем, как я понимаю, вы просите, искажая изображения и не сохраняя их соотношение сторон, а не обрезая их, чтобы они соответствовали вашим желаемым контейнерам с соотношением сторон 4: 3.

kenS 13.08.2018 05:45

Я создал модификацию вашего решения здесь: jsfiddle.net/h5a2nxfd/74 К сожалению, решение не обрабатывает случаи, когда не хватает высоты экрана для размещения изображений. Если высоты экрана недостаточно, размер изображений следует изменить, чтобы они поместились в контейнере (например, они находятся в JSFiddle исходного сообщения).

Magnus Teekivi 14.08.2018 09:20

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