Отрицательные поля в CSS

Отрицательные поля в CSS

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

Последняя спецификация говорит только: «Отрицательные значения для свойств margin допускаются, но могут быть ограничения в конкретных реализациях». И на этом все. Не очень полезно. MDN также в основном молчит.

Это странно, особенно если учесть, что отрицательные поля — это очень старый функционал, который я, возможно, даже использовал в своем самом первом тесте CSS где-то в далеком 1998 году. (Если это был не position: relative, я уже не помню).

Но, во всяком случае, здесь, по-видимому, впервые в мире систематически рассматриваются отрицательные поля в простых ситуациях.

Отрицательные поля в CSS

Можно задать для поля отрицательное значение. Это позволяет вам отобразить элемент ближе к его верхнему или левому соседу или вывести его правого и нижнего соседа ближе к нему. Кроме того, есть исключение, к которому мы придем через минуту.

Вот наш тестовый элемент: простой контейнер с тремя абзацами. Обратите внимание, что абзацы имеют ширину 250 пикселей. Это очень важно.

Отрицательные поля в CSS

Отрицательные margin-top и -bottom

Для начала давайте зададим для первого абзаца margin-bottom в -15px. По сути, когда браузер вычисляет точку, где должен начинаться второй абзац, он перемещает эту точку на 15 пикселей вверх. С этого момента браузер укладывает все абзацы как обычно.

Отрицательные поля в CSS

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

Этот трюк полезен для тонких настроек, когда содержимое одного элемента должно слегка перекрывать содержимое другого над ним.

Теперь давайте зададим для второго абзаца margin-top в -15px. Как видите, это дает точно такой же эффект. Снова, второй абзац перемещается вверх на 15px, а последующие абзацы следуют нормально.

Отрицательные поля в CSS

Сворачивание полей

Также обратите внимание, что при использовании отрицательных полей происходит сворачивание полей. Это, по крайней мере, указано в CSS 2.1:

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

В последнем примере первый абзац по-прежнему имеет поле по умолчанию 1em (Chrome; не могу найти значение Firefox).

Обычно браузер берет margin-bottom первого абзаца и margin-top второго, определяет, какое из них больше, и применяет это поле между этими двумя абзацами, что дает max(-15px,1em) = 1em. Хотя это не так.

В случае отрицательных полей мы берем абсолютные значения двух смежных полей (15 пикселей для второго абзаца; 1em для первого) и вычитаем меньшее (15 пикселей) из большего (1em). Это дает около 1px (в зависимости от размера шрифта, конечно).

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

Теперь мы полностью рассмотрели отрицательные значения margin-top и -bottom. Это иногда полезный эффект.

Отрицательные margin-left и -right

Отрицательные margin-left и -right работают аналогично, при условии, что элемент имеет ширину. Здесь мы применяем margin-left: -10px и margin-right: 10px.

Отрицательные поля в CSS

Как видите, первый абзац теперь смещен на 10 пикселей влево, сохраняя при этом свою ширину. Таким образом, его правый край также перемещается на 10 пикселей влево.

Второй абзац с отрицательным краем справа остался без изменений. Отрицательное margin-right будет влиять на любой элемент справа от второго абзаца, но их нет.

Чтобы проиллюстрировать, как работает margin-right, давайте сместим абзацы, чтобы у них был сосед справа.

Отрицательные поля в CSS

Теперь мы собираемся задать в абзацах некоторые отрицательные поля.

Отрицательные поля в CSS

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

Также обратите внимание, что второй абзац имеет отрицательное значение margin-right, что означает, что он смещен на 10 пикселей вверх. Третий абзац имеет отрицательное значение margin-bottom, которое не дает никакого эффекта, поскольку у него нет нижнего соседа.

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

Если мы зададим для второго абзаца margin-left: -10px, произойдет то же самое. Так же, как с горизонтальными полями, левое и правое поля могут задавать пересечение элементов.

Отрицательные поля в CSS

Пока что отрицательные поля слева и справа ведут себя точно так же, как поля сверху и снизу.

width: auto и отрицательное margin-right

Теперь давайте изменим поведение отрицательного margin-right, задав для абзацев width: auto. У них больше нет фиксированной ширины; вместо этого они полностью заполняют родительский элемент в соответствии с его отступами. Так работает width: auto.

Абзац с margin-left: -10px по-прежнему смещен на 10px влево, но его ширина увеличивается. Таким образом, его правый край не смещен, а остается там, где и был.

Отрицательные поля в CSS

Отрицательное значение сейчас делает то же самое. Оно смещает правое поле абзаца на 10 пикселей вправо, а его левый край остается на своем месте, в результате чего ширина абзаца увеличивается. Это происходит только тогда, когда для элемента задано width: auto. Как мы видели ранее, элементы с фиксированной шириной ведут себя совершенно иначе.

Наконец, для третьего абзаца заданы оба горизонтальных поля. Его левое и правое поля смещены на 10px, по существу сводя на нет отступы контейнера в 10px.

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

Отрицательные поля в CSS

Это стили заголовка; контейнер имеет отступы: 10px

h5 { margin-left: -10px; margin-right: -10px; padding-left: 10px; margin-top: 0; margin-bottom: 0; background-color: grey; color: white; /* no width, so defaults to width: auto */ }

Опять же, это возможно, только если заголовок имеет width: auto. К счастью, это так в 99% реальных случаев использования.

Так ведут себя отрицательные поля в простых ситуациях. Теперь, когда я описал базовое поведение, я могу рассмотреть, как они ведут себя во flexbox и grid.

Источник: https://www.quirksmode.org

Редакция: Команда webformyself.