Тренажёр размеров и позиционирования CSS

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

Как пользоваться

Выберите тему «Блочная модель», «Позиционирование» или «Контексты наложения». В режиме «Исследовать» для блочной модели меняйте размеры, отступы, рамку и box-sizing. Превью показывает содержимое, внутренний отступ, рамку и внешний отступ. Под ним — размеры и расчёт. Если блок не помещается, прокручивайте область превью: размеры не уменьшаются под экран.

В режиме «Практиковаться» прочитайте цель, измените доступные настройки и нажмите «Проверить». После ошибки можно попробовать снова. Подсказка и разбор не засчитывают задание сами по себе. Галочкой отмечаются решённые задания; прогресс хранится в этом браузере. Переключение режимов сохраняет их независимые настройки, а переход к другому заданию загружает его начальные значения.

В теме «Блочная модель» используются целые пиксели и одинаковые отступы и рамки со всех сторон. Блок стоит во flex-контейнере без сжатия, поэтому внешние отступы не схлопываются. «Сбросить настройки» возвращает исходный макет, «Сбросить прогресс» удаляет только отметки решённых заданий.

Как исследовать позиционирование

Выберите position элемента и карточки-контейнера, задайте отступы или включите auto. Изменения видны в отдельном окне предпросмотра. Прокручивайте его мышью, пальцем, клавишами после фокусировки окна или кнопками под ним. «За карточку» показывает, как sticky уходит вверх у нижней границы родителя.

relative сохраняет место в потоке, absolute и fixed освобождают его. В примере absolute отсчитывает отступы от карточки с position: relative; fixed — от окна предпросмотра. sticky сначала движется в потоке, затем прилипает к заданному краю и остаётся в пределах карточки. auto не равен нулевому отступу.

Размер элемента — 80 × 40 px, карточки — 640 px по высоте. Перед элементом находится блок высотой 60 px. Числовые отступы задаются целыми пикселями от −200 до 400. В практике проверяется положение элементов до и после прокрутки. Прогресс тем хранится отдельно; сброс отметок действует только на выбранную тему. HTML и CSS доступны с подсветкой и копированием, а кнопка скачивания сохраняет весь пример.

Как исследовать контексты наложения

Окно вложено в родителя, оверлей — его сосед. Меняйте z-index и дополнительное свойство родителя. Выберите узел дерева: соответствующий элемент выделится пунктиром, а пояснение покажет причину создания контекста. Дерево отражает вложенность контекстов, а не всех HTML-элементов и не порядок рисования.

Контекст рисуется как единое целое: окно с z-index: 999 внутри родителя с z-index: 1 остаётся под соседним оверлеем с z-index: 2. Поднимите контекст родителя или устраните причину его создания. У позиционированного родителя z-index: 0 создаёт контекст, а auto сам по себе — нет.

В примере можно исследовать также transform: translate(0), opacity: 0.9 и isolation: isolate. Все они создают контекст даже при z-index: auto. Это учебная сцена с заданной структурой, а не полный инспектор всех причин наложения. «Окно» — обычный блок: верхний слой браузера для модального dialog здесь не моделируется.

В практике изменяйте доступные настройки и нажмите «Проверить». Проверяется, какой блок браузер рисует сверху в пересечении, и выполнено ли условие задания. У равных уровней здесь выигрывает оверлей, расположенный позже в HTML. Прогресс темы независим от блочной модели и позиционирования. Код можно скопировать, а весь пример — скачать.

Правила в спецификациях: уровни и контексты наложения, влияние transform, изоляция группы.

Для вашего удобства рекомендую использовать полноэкранный режим.

Блочная модель

Меняйте параметры и сравнивайте заданный размер с размером рамки. Переключите box-sizing и посмотрите, как изменится место для содержимого.

Блок в натуральном размере

Содержимое
  • Содержимое
  • Padding
  • Border
  • Margin
Содержимое
240 × 120 px
С рамкой
288 × 168 px
С внешними отступами
320 × 200 px
Параметры блока
Справочник: box-sizing
Справочник: width
Справочник: height
Справочник: padding
Справочник: border-width
Справочник: margin

HTML и CSS текущего блока
CSS
.box {
  box-sizing: content-box;
  width: 240px;
  height: 120px;
  padding: 20px;
  border: 4px solid #487a9a;
  margin: 16px;
}
HTML
<div class="box">Содержимое</div>

1 из 8

Уместить блок в 300 px

Получите ширину до внешнего края рамки ровно 300 px. Меняйте только width; padding, border и content-box сохраняются. Margin в эти 300 px не входит.

Подсказка

В content-box к width прибавляются padding и border с обеих сторон.

Показать разбор

Подходит width: 256px. С рамкой: 256 + 20 × 2 + 2 × 2 = 300 px. Margin увеличивает внешнее место, но не размер рамки.

Просмотр разбора не засчитывает решение. Примените настройки и проверьте результат.

Блок в натуральном размере

Содержимое
  • Содержимое
  • Padding
  • Border
  • Margin
Содержимое
260 × 120 px
С рамкой
304 × 164 px
С внешними отступами
336 × 196 px
Параметры блока
Справочник: box-sizing
Справочник: width
Справочник: height
Справочник: padding
Справочник: border-width
Справочник: margin

    HTML и CSS текущего блока
    CSS
    .box {
      box-sizing: content-box;
      width: 260px;
      height: 120px;
      padding: 20px;
      border: 2px solid #487a9a;
      margin: 16px;
    }
    HTML
    <div class="box">Содержимое</div>

    Для интерактивной части включите JavaScript. Пример: при content-box, width: 240px, padding: 20px и border: 4px ширина с рамкой равна 240 + 20 × 2 + 4 × 2 = 288 px. При border-box она равна 240 px, а содержимому остаётся 192 px.

    Позиционирование

    Меняйте position и отступы, переключайте позиционирование карточки. Прокрутите окно, чтобы сравнить fixed и sticky.

    Окно предпросмотра · прокручивайте внутри

    Позиция элемента
    Справочник: position
    Справочник: right
    Справочник: bottom
    Справочник: left

    HTML и CSS текущего примера
    CSS
    .card {
      position: relative;
    }
    .target {
      position: static;
      top: 0px;
      right: auto;
      bottom: auto;
      left: 0px;
    }
    
    /* Оформление сцены */
    * { box-sizing: border-box; }
    html { color-scheme: light dark; }
    body { margin: 0; font: 14px/1.4 system-ui, sans-serif; background: light-dark(#f8fafc, #182026); color: light-dark(#243640, #e5edf2); }
    .intro { height: 100px; padding: 16px; }
    .card { height: 640px; margin-inline: 24px; outline: 2px dashed light-dark(#607d8b, #a8c8d6); background: light-dark(#e5eef3, #253540); }
    .before { height: 60px; padding: 12px; }
    .target { width: 80px; height: 40px; display: grid; place-items: center; background: light-dark(#256147, #a3e2bf); color: light-dark(#fff, #122e20); outline: 2px solid light-dark(#173c2c, #cff5df); }
    .after { height: 64px; padding: 12px; background: light-dark(#f4dcb0, #574527); }
    .caption { padding: 16px; }
    .outro { height: 700px; padding: 24px; }
    
    HTML
    <div class="intro">Прокручивайте окно вниз ↓</div>
    <section class="card" aria-label="Карточка-контейнер">
      <div class="before">До элемента · 60 px</div>
      <div class="target">Элемент</div>
      <div class="after">Следующий блок</div>
      <div class="caption">Карточка высотой 640 px</div>
    </section>
    <div class="outro">Карточка закончилась. Sticky уходит вместе с ней.</div>
    

    1 из 7

    Сдвиг без перестройки потока

    Сдвиньте элемент на 24 px вправо и 16 px вниз от его обычного места. Следующий блок должен остаться на прежнем месте. Используйте relative.

    Подсказка

    Положительные left и top смещают relative-элемент вправо и вниз, но место в потоке сохраняется.

    Показать разбор

    Position: relative; left: 24px; top: 16px. Следующий блок по-прежнему начинается через 100 px от верха карточки: 60 px перед элементом и 40 px самого элемента.

    Просмотр разбора не засчитывает решение. Примените настройки и проверьте результат.

    Окно предпросмотра · прокручивайте внутри

    Позиция элемента
    Справочник: position
    Справочник: right
    Справочник: bottom
    Справочник: left

      HTML и CSS текущего примера
      CSS
      .card {
        position: relative;
      }
      .target {
        position: static;
        top: 0px;
        right: auto;
        bottom: auto;
        left: 0px;
      }
      
      /* Оформление сцены */
      * { box-sizing: border-box; }
      html { color-scheme: light dark; }
      body { margin: 0; font: 14px/1.4 system-ui, sans-serif; background: light-dark(#f8fafc, #182026); color: light-dark(#243640, #e5edf2); }
      .intro { height: 100px; padding: 16px; }
      .card { height: 640px; margin-inline: 24px; outline: 2px dashed light-dark(#607d8b, #a8c8d6); background: light-dark(#e5eef3, #253540); }
      .before { height: 60px; padding: 12px; }
      .target { width: 80px; height: 40px; display: grid; place-items: center; background: light-dark(#256147, #a3e2bf); color: light-dark(#fff, #122e20); outline: 2px solid light-dark(#173c2c, #cff5df); }
      .after { height: 64px; padding: 12px; background: light-dark(#f4dcb0, #574527); }
      .caption { padding: 16px; }
      .outro { height: 700px; padding: 24px; }
      
      HTML
      <div class="intro">Прокручивайте окно вниз ↓</div>
      <section class="card" aria-label="Карточка-контейнер">
        <div class="before">До элемента · 60 px</div>
        <div class="target">Элемент</div>
        <div class="after">Следующий блок</div>
        <div class="caption">Карточка высотой 640 px</div>
      </section>
      <div class="outro">Карточка закончилась. Sticky уходит вместе с ней.</div>
      

      Для интерактивной части включите JavaScript. Relative сохраняет место элемента в потоке; absolute исключает его из потока и ищет позиционированного предка. Fixed в этом примере закреплён относительно окна, sticky прилипает при прокрутке и ограничен своей карточкой.

      Контексты наложения

      Меняйте z-index и свойства родителя. Выбирайте узлы дерева, чтобы увидеть причины создания контекстов и сравнить их порядок.

      Дерево контекстов · выберите узел для пояснения и выделения в примере.

      Порядок наложения

      Окно вложено в родителя. Оверлей идёт после родителя в HTML. Заблокированные настройки заданы условием задания.

      HTML и CSS текущего примера
      CSS
      .parent {
        position: relative;
        z-index: 1;
        transform: none;
        opacity: 1;
        isolation: auto;
      }
      .modal {
        position: absolute;
        z-index: 999;
      }
      .overlay {
        position: absolute;
        z-index: 2;
      }
      
      /* Оформление сцены */
      * { box-sizing: border-box; }
      html { color-scheme: light dark; }
      body { margin: 0; font: 16px/1.5 system-ui, sans-serif; background: light-dark(#f8fafc, #182026); color: light-dark(#243640, #e5edf2); }
      .scene { position: relative; height: 300px; margin: 12px; }
      .parent { height: 260px; padding: 8px; border: 2px dashed light-dark(#607d8b, #a8c8d6); }
      .modal, .overlay { display: grid; place-items: center; border: 2px solid currentColor; }
      .modal { top: 60px; left: 8%; width: 65%; height: 150px; background: light-dark(#c0e9cf, #24533c); }
      .overlay { top: 110px; left: 40%; width: 55%; height: 150px; background: light-dark(#f4dcb0, #574527); }
      [data-selected] { outline: 3px dotted light-dark(#243640, #fff); outline-offset: -6px; }
      
      HTML
      <main class="scene">
        <section class="parent" aria-label="Родитель">
          <span>Родитель</span>
          <div class="modal">Окно</div>
        </section>
        <div class="overlay">Оверлей</div>
      </main>

      1 из 6

      Соседи в одном контексте

      Поднимите окно над оверлеем, изменив z-index окна. Родитель не создаёт контекст наложения.

      Подсказка

      Окно и оверлей участвуют в одном корневом контексте. Сравните их z-index.

      Показать разбор

      Значение окна больше 2 — оно рисуется над оверлеем. При равных значениях оверлей выше, потому что расположен позже в HTML.

      Просмотр разбора не засчитывает решение. Примените настройки и проверьте результат.

      Дерево контекстов · выберите узел для пояснения и выделения в примере.

      Порядок наложения

      Окно вложено в родителя. Оверлей идёт после родителя в HTML. Заблокированные настройки заданы условием задания.

        HTML и CSS текущего примера
        CSS
        .parent {
          position: relative;
          z-index: auto;
          transform: none;
          opacity: 1;
          isolation: auto;
        }
        .modal {
          position: absolute;
          z-index: 1;
        }
        .overlay {
          position: absolute;
          z-index: 2;
        }
        
        /* Оформление сцены */
        * { box-sizing: border-box; }
        html { color-scheme: light dark; }
        body { margin: 0; font: 16px/1.5 system-ui, sans-serif; background: light-dark(#f8fafc, #182026); color: light-dark(#243640, #e5edf2); }
        .scene { position: relative; height: 300px; margin: 12px; }
        .parent { height: 260px; padding: 8px; border: 2px dashed light-dark(#607d8b, #a8c8d6); }
        .modal, .overlay { display: grid; place-items: center; border: 2px solid currentColor; }
        .modal { top: 60px; left: 8%; width: 65%; height: 150px; background: light-dark(#c0e9cf, #24533c); }
        .overlay { top: 110px; left: 40%; width: 55%; height: 150px; background: light-dark(#f4dcb0, #574527); }
        [data-selected] { outline: 3px dotted light-dark(#243640, #fff); outline-offset: -6px; }
        
        HTML
        <main class="scene">
          <section class="parent" aria-label="Родитель">
            <span>Родитель</span>
            <div class="modal">Окно</div>
          </section>
          <div class="overlay">Оверлей</div>
        </main>

        Для интерактивной части включите JavaScript. Контекст наложения рисуется как единое целое. Окно с z-index: 999 внутри родителя с z-index: 1 остаётся под соседним оверлеем с z-index: 2. Поднимите контекст родителя выше 2 или устраните причину его создания.

        Как связаны размеры

        • content-box: width и height задают размер содержимого. Внутренние отступы и рамки прибавляются с обеих сторон.
        • border-box: отступы и рамки входят в заданные размеры. Содержимое уменьшается, но не может стать отрицательным. Если отступы с рамками больше заданной ширины, фактическая ширина блока будет больше width.
        • margin всегда находится снаружи рамки и не входит в width, независимо от box-sizing.

        Свойства в справочнике: box-sizing, width, height, padding, margin, border, border-width. Общее объяснение — в статье «Размеры блочных элементов».

        Для построения готовых макетов используйте конструкторы Flexbox и Grid.

        Свойства позиционирования в справочнике: position, top, right, bottom, left.