Jump to content
  • 0

Вписать изображение в контейнер с подгонкой размеров


ows.nightwolf
 Share

Question

Доброго времени суток, прошу помощи в решении задачи.

Пример (как должно быть):

image.png

На данном рисунке:

  1. Есть общий контейнер (зеленый прямоугольник), чьи размеры (и ширина и высота) заданы фиксированно (но эти величины заранее не известны + при изменении размеров окна браузера могут меняться)
  2. Внутри общего контейнера лежит контейнер изображения (красный прямоугольник).
  3. Ну и есть само изображение, о котором не известно вообще ничего.

Суть задачи: изображение должно масштабироваться сохраняя свои пропорции так, чтобы занимать всю высоту или ширину зеленого контейнера (быть вписанным в зеленый контейнер), при этом красный контейнер должен иметь размеры в точности такие как само изображение (облегать его). Задача должна быть решена на чистом CSS + HTML.

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

Скрытый текст

 

Это модуль из реального проекта, который представляет информацию о свободных местах за столами (затяно/свободно). Сервер присылает нам url плана (это наше изображение в центре), его размеры (для чего нужны см. ниже) + список объектов с информаций о рассадке. Каждый объект - это прямоугольник с координатами top/left/width/height и цветом (обычно зеленый - свободный стул, красный - занятый стул).

Примерный JSON с сервера:


{
    "map": "plan.png",
    "width": 100,
    "height": 200,
    "seats": [
        {
            "top": 10,
            "left": 20,
            "width": 10,
            "height": 10,
            "color": "red" 
        },
        {
            "top": 20,
            "left": 40,
            "width": 10,
            "height": 10,
            "color": "green" 
        }
    ]
}

Карта должна быть резиновой, по этому для того чтоб отрендерить это мне нужен контейнер (красный прямоугольник)  у которого задана position: relative, который содержит внутри карту и отрендеренный массив seats (абсолютно позиционированные div'ы) у которых пиксельные значения top и left пересчитаны в проценты от ширины/высоты карты (для этого с сервера и передается информация о ширине и высоте карты). И для того чтоб это сработало мне нужно чтоб этот красный контейнер в точности повторял размеры карты. В результате схематично html будет примерно такой:


<div class="map-container" style="position: relative;">
  <img src="map.png"> <!-- карта резиновая, но всегда сохраняет свои пропорции -->
  <div class="seat" style="position: absolute; top: 10%; left: 10%; width: 10%; height: 5%;"></div>
  <div class="seat" style="position: absolute; top: 20%; left: 20%; width: 10%; height: 5%;"></div>
</div>

 

 

Мои наработки:

Пока что наиболее близкого поведения я смог добиться только таким способом:

https://codepen.io/ows_nightwolf/pen/yxoYBa

Но тут изображение не может вырасти больше своего реального размера, и красный контейнер не повторяет размеров изображения

Edited by ows.nightwolf
Link to comment
Share on other sites

7 answers to this question

Recommended Posts

  • 0
1 час назад, ows.nightwolf сказал:

 заданы фиксированно (но эти величины заранее не известны + при изменении размеров окна браузера могут меняться)

Так фиксированно или может меняться?

1 час назад, ows.nightwolf сказал:

Задача должна быть решена на чистом CSS + HTML.

IMHO, при заданных условиях это невозможно. 

Link to comment
Share on other sites

  • 0

Спасибо всем за ответы,

@Switch74: object-fit действительно вписывает картинку в контейнер, но сам контейнер не принимает ее размеров, так что это только частично решает задачу.

@AlexZaw: Фиксирвано том смысле что размеры не равны auto или еще чему-то абстрактному (что может "сломать" свойства типа min-width или min-height, если они заданы в %), там четко заданы размеры в % или px. А меняться могут под действием различных media query.

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

Тем не менее для задачи на реальном проекте (описана в разделе "доп информация" этого поста) я нашел решение проблемы - использовать SVG в качестве контейнера картинки, а саму картинку внутри этого svg вставлять через тег image. Вот так: https://codepen.io/ows_nightwolf/pen/Mqvoab .

Эффект от этого подхода очень схож с эффектом от использования object-fit, который был предложен Switch74, в том плане что изображение будет вписано в контейнер, но сам контейнер (SVG элемент) не будет иметь те же размеры что и изображение. Но тем не менее есть два отличия:

  1. Он лучше поддерживается браузерами (IE9+, в то время как object-fit поддерживается только IE Edge)
  2. Есть возможность вставлять различные элементы "в пределах" размеров исходного изображения (вставлять их внутрь SVG, в моем примере я вставил красный прозрачный прямоугольник для иллюстрации), при этом они будут отображаться правильно вне зависимости от масштаба изображения.

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

UPD.:
Согласно предложенному Switch74 решению можно узначать исходные размеры изображения после его загрузки, и согласно им обновить значения width и height у image, а так же width, height и viewBox у svg. Получится что-то типа такого: https://codepen.io/ows_nightwolf/pen/KxXzyL

Edited by ows.nightwolf
Добавлено решение проблемы неизвестных размеров изображения
Link to comment
Share on other sites

  • 0
47 минут назад, ows.nightwolf сказал:

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

Если нельзя использовать js (кстати почему?) то может можно пхп? А в нем уже получать размеры изображения и формировать svg контейнер ?

Link to comment
Share on other sites

  • 0
2 минуты назад, AlexZaw сказал:

Если нельзя использовать js (кстати почему?) то может можно пхп? А в нем уже получать размеры изображения и формировать svg контейнер ?

Я написал что нельзя использовать js т.к. насколько я понимаю все решения сводились бы к чтению размеров изображения, сравнения их с размерами контейнера, высчитыванием правильных размеров с учетом масштабирования и назначения этих размеров (в пикселях я полагаю) контейнеру. Такие решения будут работать "в моменте" но рано или поздно потребуют костылей для того чтоб работать например при изменении размеров окна (типа надо вешаться на window.onresize и пересчитывать все при ресайзе), и их производительность хуже чем решения на чистом CSS.
Ну а PHP не подходит потому что сервер вообще на classic ASP (не спрашивайте, заказчик упрям как обычно), а у нас что-то типа single-page application и разметку мы гереним на клиенте.

Но в моем решении я конечно исользую js чтоб сформировать svg контейнер как вы сказали, но это делается только один раз в начале и работает в любых условиях в дальнейшем, так что такое решение в теории не приведет к доп. работам в будущем.

Link to comment
Share on other sites

  • 0
5 часов назад, Switch74 сказал:

получить размер картинки можно при ее загрузке, сделайте прелоадер для нее и показывайте после полной загрузки

Согласен, это решает проблему неизвестных исходных размеров изображения.

К сожалению у объекта image (который находится внутри SVG) нет возможности получить оригинальный размер при загрузке, так что надо будет "костыльнуть" и на событии onLoad создавать нативный HTMLImage, сетить в него src такой же как у image внутри svg, и уже на нем по onload смотреть оригинальные размеры. Получится что-то типа такого: https://codepen.io/ows_nightwolf/pen/KxXzyL

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

  • Similar Content

    • By Balalayka
      Не могу расположить второй ряд картинок все div идут в одну строчку. Пробовал и команду clear (both, left) всем блокам прописан float:left.(Всё в конце кода). Заранее спасибо за помощь.На всякий случай прикреплю ещё картинки.
      index.html
      style.css









    • By Lex_85
      Здравствуйте! Есть небольшая проблема: имеется блок, в который вставляем строчные гиперссылки с изображениями внутри. Обнаружил, что в данном блоке появляется странный отступ снизу (зеленного цвета), от которого я не могу избавиться. Так как я новичок, то прошу помощи. Визуально проблему можно посмотреть здесь: https://jsfiddle.net. Проблема плевая, но я застрял . Заранее благодарю!
    • By gadjet
      Такая конструкция работает нормально
      <img src="/img/logo.png" alt="Logo" />
       
      Перестает работать внутри контейнера <a>. И локально и на хостинге, картинка не отображается
      <a href="/index.html>
      <img src="/img/logo.png" alt="Logo" />
      </a>
    • By Elizabeth2018
      Помогите пожалуйста, мне надо, чтобы текст отображался внизу картинки БЕЗ ОТСТУПОВ, сразу после картинки.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy