Подскажите пожалуйста как спозиционировать эти блоки, как на изображении с макета

ссылка на макет: https://www.figma.com/file/0GtAVVt5vQEmKV0ynSLFIb/%D1%84%D0%BE%D1%82%D0%BE%D1%81%D1%82%D1%83%D0%B4%D0%B8%D1%8F

Буду очень благодарен за вашу помощь

Скриншот


Ответы (1 шт):

Автор решения: De.Minov

Если мы в выделим все блоки и сгруппируем их, то можно заметить, что блоки имеют некий родитель, с него и начнём.

введите сюда описание изображения

Создадим блок .map, дадим ему width: 100% и max-width: 1220px, чтобы ограничить в размерах как по макету.
Ставим ему position: relative;, т.к. внутри элементы будут position: absolute и позиция будет от его родителя.

Но из-за этого высота .map будет равна нулю.
Чтобы это исправить зададим ему ::before, который при помощи padding-top будет задавать блоку нужную высоту, отталкиваясь от соотношения height / width * 100% -

.map::before {
  content: '';
  display: block;
  width: 100%;
  height: 0;
  padding-top: calc(826 / 1220 * 100%);
}

Далее переходим к карточкам.

Как уже сказал, они будут position: absolute.
Берём их позицию относительно группы карточек.

введите сюда описание изображения

Для этого переходим на слой группы, зажимаем ctrl+alt и наводим на нужную карточку (допустим 4ую) и смотрим её координаты от левого и верхнего края группы - 162, 354.
Их мы запишем следующим образом

.map__item:nth-child(4) {
  left: calc(162 / 1220 * 100%);
  top: calc(354 / 826 * 100%);
}

Таким образом CSS будет считать позицию карточек в процентах, от размера родителя.

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


Мой пример с использованием препроцессоров и vw вместо %.

body {margin: 0;}

.wrapper {
  display: block;
  width: 100%;
  max-width: 1440px;
  margin: 0 auto;
}
@media screen and (max-width: 1440px) {
  .wrapper {
    overflow: hidden;
  }
}
h2 {
  text-align: center;
  margin-bottom: 97px;
}
.map {
  display: block;
  width: 100%;
  max-width: 1220px;
  background: url("//i.imgur.com/6Ahe9h5.png") no-repeat center center/100% auto;
  margin: 0 auto;
  position: relative;
  counter-reset: map-item;
}
.map::before {
  content: '';
  display: block;
  width: 100%;
  height: 0;
  padding-top: 67.70491803278689%;
}
.map__item {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  width: 24.166666666666668vw;
  height: 13.194444444444445vw;
  border-radius: 12px;
  border: 2px solid #e97522;
  background: #fff;
  padding: 1.388888888888889vw 2.777777777777778vw;
  box-sizing: border-box;
  position: absolute;
}
@media screen and (min-width: 1440px) {
  .map__item {
    width: 348px;
    height: 190px;
    padding: 20px 40px;
  }
}
.map__item::before {
  counter-increment: map-item;
  content: counter(map-item);
  display: flex;
  justify-content: center;
  align-items: center;
  width: 3.472222222222222vw;
  height: 3.472222222222222vw;
  border-radius: 50%;
  background: #f9f4ee;
  color: #e97522;
  font-size: 2.083333333333333vw;
  font-weight: bold;
  position: absolute;
  left: -1.111111111111111vw;
  bottom: -1.111111111111111vw;
}
@media screen and (min-width: 1440px) {
  .map__item::before {
    width: 50px;
    height: 50px;
    font-size: 30px;
    left: -16px;
    bottom: -16px;
  }
}
.map__item-title {
  font-size: 1.25vw;
  font-weight: bold;
  line-height: 120%;
  margin-bottom: 0.833333333333333vw;
}
@media screen and (min-width: 1440px) {
  .map__item-title {
    font-size: 18px;
    margin-bottom: 12px;
  }
}
.map__item-desc {
  font-size: 1.111111111111111vw;
  line-height: 140%;
}
@media screen and (min-width: 1440px) {
  .map__item-desc {
    font-size: 16px;
  }
}
.map__item:nth-child(1) {
  left: 0%;
  top: 0%;
}
.map__item:nth-child(2) {
  left: 50.90163934426229%;
  top: 6.900726392251816%;
}
.map__item:nth-child(3) {
  left: 71.47540983606558%;
  top: 43.46246973365617%;
}
.map__item:nth-child(4) {
  left: 13.278688524590162%;
  top: 42.857142857142854%;
}
.map__item:nth-child(5) {
  left: 26.721311475409838%;
  top: 76.99757869249395%;
}
<div class="wrapper">
  <h2>Этапы работ</h2>
  <div class="map">
    <div class="map__item">
      <div class="map__item-title">Заявка</div>
      <div class="map__item-desc">Съешь еще этих мягких французских булок, да выпей чаю. Съешь еще этих мягких.</div>
    </div>
    <div class="map__item">
      <div class="map__item-title">Бронь</div>
      <div class="map__item-desc">Съешь еще этих мягких французских булок, да выпей чаю. Съешь еще этих мягких.</div>
    </div>
    <div class="map__item">
      <div class="map__item-title">Съёмка</div>
      <div class="map__item-desc">Съешь еще этих мягких французских булок, да выпей чаю. Съешь еще этих мягких.</div>
    </div>
    <div class="map__item">
      <div class="map__item-title">Составление <br>Технического задания</div>
      <div class="map__item-desc">Съешь еще этих мягких французских булок, да выпей чаю. Съешь еще этих мягких.</div>
    </div>
    <div class="map__item">
      <div class="map__item-title">Готовые фото</div>
      <div class="map__item-desc">Съешь еще этих мягких французских булок, да выпей чаю. Съешь еще этих мягких.</div>
    </div>
  </div>
</div>

Codepen


P.s.

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

width (354 / $map-width * 100vw)

@media $min-wrap // @media screen and (min-width: 1440px)
  width 354px
→ Ссылка