Тренажёр размеров и позиционирования 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
HTML и CSS текущего блока
.box {
box-sizing: content-box;
width: 240px;
height: 120px;
padding: 20px;
border: 4px solid #487a9a;
margin: 16px;
}<div class="box">Содержимое</div>Уместить блок в 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
HTML и CSS текущего блока
.box {
box-sizing: content-box;
width: 260px;
height: 120px;
padding: 20px;
border: 2px solid #487a9a;
margin: 16px;
}<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.
Окно предпросмотра · прокручивайте внутри
HTML и 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; }
<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>
Сдвиг без перестройки потока
Сдвиньте элемент на 24 px вправо и 16 px вниз от его обычного места. Следующий блок должен остаться на прежнем месте. Используйте relative.
Подсказка
Положительные left и top смещают relative-элемент вправо и вниз, но место в потоке сохраняется.
Показать разбор
Position: relative; left: 24px; top: 16px. Следующий блок по-прежнему начинается через 100 px от верха карточки: 60 px перед элементом и 40 px самого элемента.
Просмотр разбора не засчитывает решение. Примените настройки и проверьте результат.
Окно предпросмотра · прокручивайте внутри
HTML и 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; }
<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 и 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; }
<main class="scene">
<section class="parent" aria-label="Родитель">
<span>Родитель</span>
<div class="modal">Окно</div>
</section>
<div class="overlay">Оверлей</div>
</main>Соседи в одном контексте
Поднимите окно над оверлеем, изменив z-index окна. Родитель не создаёт контекст наложения.
Подсказка
Окно и оверлей участвуют в одном корневом контексте. Сравните их z-index.
Показать разбор
Значение окна больше 2 — оно рисуется над оверлеем. При равных значениях оверлей выше, потому что расположен позже в HTML.
Просмотр разбора не засчитывает решение. Примените настройки и проверьте результат.
Дерево контекстов · выберите узел для пояснения и выделения в примере.
HTML и 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; }
<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.