Иногда, когда вы пишете компонент, то вдруг замечаете странную полосу горизонтальной прокрутки. Снова и снова вы пытаетесь исправить положение, только чтобы позже понять, что причина в чём-то другом. Сколько раз так было? В этой статье я растолкую хитрую проблему, которая может стоить часов проб и ошибок; связана эта проблема с макетом сетки CSS, и я подумал, что о ней стоит написать. Прежде чем начать, я хочу дать некоторый контекст. Вот несколько вещей, которые следует принять во внимание. Представьте, что вы:

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

Учитывая всё это, давайте погрузимся в проблему.




Что должно получиться


Я дам немного контекста. Вот макет, который должен получиться. Обратите внимание, что в конце раздела main есть контейнер с прокруткой.


Определим проблему


Работая над разделом контейнера с прокруткой, я заметил горизонтальную прокрутку по всей странице, увидеть которую не ожидал.


У раздела было свойство display: flex без обёртки, поэтому контент мог оставаться в той же строке. Кроме того, чтобы разрешить прокрутку по оси x, я воспользовался overflow-x: auto.

    .section {
        display: flex;
        overflow-x: auto;
      }

Однако эффекта не последовало. Это сбивало с толку: я был уверен, что так я делаю контейнер с прокруткой. Я открыл браузер DevTools, чтобы проверить раздел main, и заметил, что раздел очень широкий. Расширился он за счёт прокручиваемого контейнера.


Странно, правда? Когда я впервые увидел эту проблему, то задался следующими вопросами:

  • Может, я забыл добавить overflow-x: hidden?
  • Что-то не так с flexbox?

Я дважды перепроверил flexbox и overflow-x. Всё должно было работать так, как я ожидал. Тогда я заподозрил, что причиной проблемы может оказаться CSS-сетка (grid) для родительского элемента. Проверил подозрение, и оно подтвердилось. Макет сломался из-за grid.

Первопричиной проблемы могла быть особенность CSS (т. е. из-за какого-то контекста ожидается именно такое поведение) либо то, что свойство неверно реализовали в браузере.

Почему же появилась прокрутка?


Возможно, вы задумались, почему grid прикрепляет прокрутку к контейнеру? Смотрите: вот сетка, на которой расположены разделы main и aside.

    <div class="wrapper">
        <main>
          <section class="section"></section>
        </main>
        <aside></aside>
      </div>

@media (min-width: 1020px) {
    .wrapper {
      display: grid;
      grid-template-columns: 1fr 248px;
      grid-gap: 40px;
    }
  }

В свойствах main есть значение 1fr. Это означает, что main займет доступное пространство, кроме aside и отступа. Это не подлежит сомнению. Однако минимальный размер содержимого элемента сетки — auto. Это означает, что элемент сетки может расширяться из-за длинного содержимого (в нашем случае из-за контейнера с прокруткой).

Как убрать лишнюю прокрутку?


Решается проблема так: нужно сообщить браузеру, что нам необходим конкретный и фиксированный минимальный размер, но не auto. Сделать это можно при помощи функции minmax().

.wrapper {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 248px;
    grid-gap: 40px;
  }

Проблему мы решили. Но мы также можем решить эту проблему на уровне элемента сетки. Вот два решения, которые применимы к элементу .main:

  1. Установить свойство min-width: 0.
  2. Или overflow: hidden.

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


На рисунке выше у нас два элемента, которые расположены вне main (кнопка шаринга слева и декоративная фигурка внизу справа). Учитывая это, вы должны выбрать решение, которое лучше всего подходит именно в вашем случае.

Статьи по теме





image