Overflow

overflow управляет отображением контента, выходящего за границы элемента: показать, скрыть, обрезать, добавить скроллбар. Тесно связан с text-overflow для обрезки текста и стилизацией скроллбаров.

Зачем нужно

Контент не всегда помещается в элемент. Длинный текст, большие изображения, динамический контент — всё это может «вылезать» за границы. overflow решает, что делать с переполнением: показать, скрыть или дать пользователю прокрутку.

Где используется

  • Скроллируемые контейнеры (чаты, списки, сайдбары)
  • Обрезка контента (карточки, превью)
  • Текст с многоточием
  • Создание BFC (Block Formatting Context)
  • Кастомные скроллбары

Предпосылки

  • Display — блочная модель
  • Position — позиционирование и overflow

Значения overflow

/* Контент виден за пределами (по умолчанию) */
.visible { overflow: visible; }

/* Обрезать без скролла */
.hidden { overflow: hidden; }

/* Всегда показывать скроллбар */
.scroll { overflow: scroll; }

/* Скроллбар только при необходимости */
.auto { overflow: auto; }

/* Обрезать без возможности скролла (даже JS) */
.clip { overflow: clip; }
Значение Видимость Скроллбар JS-скролл
visible Виден за пределами Нет
hidden Обрезан Нет Да (через JS)
scroll Обрезан Всегда Да
auto Обрезан (если нужно) При переполнении Да
clip Обрезан Нет Нет

overflow-x и overflow-y

Контроль по отдельным осям:

/* Горизонтальный скролл, вертикальный — скрыть */
.horizontal-scroll {
  overflow-x: auto;
  overflow-y: hidden;
  white-space: nowrap;
}

/* Вертикальный скролл */
.vertical-scroll {
  overflow-y: auto;
  max-height: 400px;
}

/* Shorthand */
.box { overflow: hidden auto; } /* overflow-x overflow-y */

Если одна ось visible, а другая — нет, то visible автоматически становится auto.


text-overflow: ellipsis

Обрезка текста с многоточием:

/* Однострочный текст */
.truncate {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Многострочный текст (webkit) */
.line-clamp {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
Значение Результат
clip Просто обрезает (по умолчанию)
ellipsis Добавляет ...
"→" Кастомная строка (limited support)

Стилизация скроллбаров

Webkit (Chrome, Safari, Edge)

.scrollable {
  overflow-y: auto;
  max-height: 300px;
}

/* Ширина скроллбара */
.scrollable::-webkit-scrollbar {
  width: 8px;
}

/* Дорожка */
.scrollable::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 4px;
}

/* Ползунок */
.scrollable::-webkit-scrollbar-thumb {
  background: #888;
  border-radius: 4px;
}

.scrollable::-webkit-scrollbar-thumb:hover {
  background: #555;
}

Firefox

.scrollable {
  scrollbar-width: thin;              /* auto | thin | none */
  scrollbar-color: #888 #f1f1f1;     /* thumb track */
}

Скрыть скроллбар, но оставить прокрутку

.no-scrollbar {
  overflow-y: auto;
  scrollbar-width: none;              /* Firefox */
}
.no-scrollbar::-webkit-scrollbar {
  display: none;                      /* Chrome/Safari */
}

overflow и Block Formatting Context

overflow != visible создаёт новый BFC:

/* Содержать float-потомков */
.container {
  overflow: hidden; /* Создаёт BFC */
}

/* Лучше: display: flow-root (без побочных эффектов) */
.container {
  display: flow-root;
}

overflow и position: sticky

/* ПРОБЛЕМА: sticky не работает */
.parent {
  overflow: hidden; /* Блокирует sticky! */
}
.child {
  position: sticky;
  top: 0;
}

/* РЕШЕНИЕ: убрать overflow или реструктурировать DOM */

overflow: clip vs overflow: hidden

/* hidden — скроллится через JS */
.hidden-box {
  overflow: hidden;
  /* element.scrollTop = 100; работает */
}

/* clip — не скроллится вообще, даже через JS */
.clip-box {
  overflow: clip;
  /* element.scrollTop = 100; НЕ работает */
}

/* clip можно применять к одной оси без влияния на другую */
.one-axis {
  overflow-x: clip;
  overflow-y: visible; /* Реально остаётся visible! */
}

Практические примеры

Чат-окно с автоскроллом

.chat {
  max-height: 500px;
  overflow-y: auto;
  overscroll-behavior-y: contain; /* Не скроллить страницу */
  scroll-behavior: smooth;
}

Горизонтальная карусель

.carousel {
  display: flex;
  gap: 16px;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 8px; /* Место для скроллбара */
}
.carousel .card {
  flex: 0 0 280px;
  scroll-snap-align: start;
}

Карточка с обрезанным контентом

.card {
  max-height: 200px;
  overflow: hidden;
  position: relative;
}
.card::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 60px;
  background: linear-gradient(to bottom, transparent, white);
}

Частые ошибки

  1. text-overflow: ellipsis без overflow: hidden и white-space: nowrap — все три обязательны для однострочного truncate

  2. overflow: hidden ломает position: sticky — sticky работает только если прокрутка происходит в этом же контейнере

  3. overflow-x: hidden автоматически делает overflow-y: auto — если одна ось не visible, другая тоже становится не visible

  4. Двойной скроллбарoverflow: scroll всегда показывает скроллбар, даже если контент помещается. Используйте auto

  5. overflow: hidden на body — блокирует скролл всей страницы (используется при открытии модалок):

    body.modal-open {
      overflow: hidden;
    }
    

Практика

  • Создать скроллируемый контейнер с max-height и overflow-y: auto
  • Стилизовать скроллбар через -webkit-scrollbar и scrollbar-color
  • Реализовать однострочный и многострочный truncate
  • Создать горизонтальную карусель с overflow-x: auto
  • Скрыть скроллбар, сохранив прокрутку

Связанные темы

Ресурсы