delphinpro
@delphinpro
frontend developer

Головоломка с раскладкой страницы. Решим?

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

  • Фон зеленой секции тянется на всю ширину вьюпорта;
  • UPD. Фон однородный, не картинка, не градиент;
  • Контент зеленой секции вписывается в заданную сетку (во всех брикпойнтах);
  • Зеленых секций может быть несколько (для упрощения можно считать, что все секции ведут себя как зеленые, только с разным фоном);
  • Левая колонка перекрывает такие секции;
  • В мобильной раскладке сайдбар оказывается внизу (и в разметке желательно, чтобы он был последним);
  • Высота сайдбара может превышать высоту основного контента (что исключает его абсолютное позиционирование);


У меня есть пара вариантов, но они мне не нравятся. Предлагаю вам, коллеги, высказать свои предложения (необязательно код, можно и просто текстового объяснения принципов)

5c9a0d55bd318839856031.png
  • Вопрос задан
  • 380 просмотров
Решения вопроса 2
victory_vas
@victory_vas
Ну с сайдбаром вроде всё стандартно - почему бы не сделать колонки на флексах или гридах?
По поводу фона на всю ширину - приходит в голову решение с псевдоэлементом для зелёного блока, у этого псевдоэлемента ширина 100vw и высота 100% и он сдвинут влево на ширину сайдбара и левого отступа, с абсолютным позиционированием... Как мне кажется, это самый безболезненный вариант, потому что ломать сетку ради фона смысла не вижу.
Ответ написан
delphinpro
@delphinpro Автор вопроса, куратор тега CSS
frontend developer
Решение.

Так как контент секций всегда остается в пределах сетки, а заполнителем выступает лишь фон, и с оглядкой на будущее (вдруг фоном будет выступать картинка, а не сплошной цвет) искал решение на основе варианта, предложенного #FFFFFF .

Общая разметка колонок страницы

<div class="page">
  <div class="page__main"> ... </div>
  <div class="page__side"> ... </div>
</div>


Секция размещается внутри основной колонки

<div class="page__main">
    <div class="section">
      <div class="section__body">
        ...
      </div>
    </div>
  </div>


Стили колонок представляют собой обычную бутстраповскую сетку (часть медиа-запросов убрана для краткости)

/*==
 *== Page layout
 *== ======================================= ==*/

.page {
  @include make-row();

  &__main,
  &__side {
    @include make-col-ready();
  }

  &__side {
    z-index: 1;
  }
  
  // <…cut>

  @include media-breakpoint-up(lg) {
    &__main {
      @include make-col(9);
    }
    &__side {
      @include make-col(3);
      order: -1;
    }
  }
}


И стили самой секции (собственно решение проблемы)

$default-scrollbar-width: 16px;

.section {
  @include make-row();
  position: relative;

  &__body { @include make-col-ready(); }

  &::before {
    z-index: -1;
    position: absolute;
    top: 0;
    right: percentage(6/9);
    width: 100vw;
    height: 100%;
    transform: translateX(50%);
    margin-right: ($default-scrollbar-width / 2);
  }
}


Значение для переменной $default-scrollbar-width измерено в браузере линейкой.
Конечно, это не годится для использования, поэтому ширина скроллбара измеряется джавасриптом и в страницу вставляется корректирующий стиль
App.compensateWidthScrollbar = function () {
    let width  = this.getScrollbarWidth();
    let css    = '.section::before{margin-right:'+ (width / 2) + 'px';
    let style  = document.createElement('style');
    style.type = 'text/css';
    style.appendChild(document.createTextNode(css));
    (document.head || document.getElementsByTagName('head')[0]).appendChild(style);
};

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

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы