В самом начале бывает трудно выбирать между margin и padding: и то и другое отступы, так что же использовать

Попробуем разобраться. Готового алгоритма нет, да и придумать его очень сложно. Поэтому сперва мы немного потеоретизируем, а затем перейдем к чуть более практичной части и разберем несколько примеров. Ну что, Погнали? (признавайтесь, у кого сейчас мурашки по спине побежали 😁 )

Теоретизируем

Ключевая разница

Давайте начнем с… перевода. Мы привыкли их воспринимать как “внутренний отступ” и “внешний отступ”. Однако, прямой перевод с английского даст очень разные понятия:
marginполе,
а paddingнабивка.

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

Обычно сложности возникают с элементами с неявными границами, но если мы сравним как эти свойства меняют элемент с фоном и рамкой, то разница в поведении будет хорошо заметна:

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

Кстати, определяя тип отступа, попробуйте представить, что у размечаемого блока есть фон или рамка. Это может помочь понять, где именно вам нужно пространство, внутри или снаружи.

Воспроизводите, а не копируйте

А если выразиться точнее: воспроизводите поведение, а не копируйте картинку.

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

Именно поэтому стремительно теряет популярность подход Pixel Perfect: важна гибкость верстки, хорошая работа с контентом разного объема, легкая модифицируемость и хорошая адаптация под разные устройства. И все это про поведение.

Возьмем простейший пример. Чтобы сверстать текст как в квадрате справа сверху, вам достаточно будет добавить отступы по 10px сверху и слева.
Но дизайнер вряд ли задумывал такое поведение, ведь возможен набор слов, при котором буквы “прилипнут” к правому краю. Задуман там отступ внутри элемента со всех сторон, что и следует воспроизвести в макете.

Кстати, такие отступы можно назвать “охранная область”, поскольку они обезопашивают от прилипания текста или других элементов. Если вы хотите обезопасить элемент от прилипаний контента внутри — нужен padding. Если же вы хотите, чтобы к элементу снаружи не располагались вплотную другие элементы — нужен margin.

Может уже конкретнее, а?

Ладно-ладно, согласен, долго уже ходим вокруг да около. Давайте разберемся на конкретных примерах.

Я поделил примеры на 3 части: интерактив, группы элементов и крупные блоки. По степени конкретности и понятности.

Интерактивные элементы

С ними проще всего. Например, кнопки в большинстве случаев — прямоугольные и либо с фоном, либо в рамочке. Тут все очень просто, правда? Внутри рамки — padding, снаружи — margin.
Иногда, конечно, бывают исключения, но чаще всего можно посмотреть подсказку в стайлгайде, так как при взаимодействии ранее невидимые границы могут стать видимыми:

Тут ролик, я пока не реализовал встраивание на сайте, так что кликаем и смотрим =Р

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

Не перепутайте: это именно размер ссылки, а не элемента списка. При взаимодействии с интерактивным элементом в 99.8% случаев изменяется именно он, а не что-то вокруг.

А вот вопрос поинтереснее. Главное меню в проекте Нердс. Там никакие границы не подсвечены… Спокойно делаем margin, так?
Нет, не так! Только не в мою смену. Кликабельную область желательно увеличить, чтобы попасть в ссылку было проще. Мы можем использовать пространство между текстом, расположив элементы вплотную или оставив небольшой зазор (да, отступы можно и комбинировать, чтобы не создавать слишком огромные ссылки):

Группы и списки

На сайтах списки попадаются часто и в больших количествах. А еще это могут быть не списки, но и разные сгруппированные элементы.

Возьмем вот такой вот список с максимально размытыми границами. Все, что у нас есть это направляющие и текст с картинками:

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

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

Вообще-то, это может быть удобнее сделать через grid с gap'ом, но он по сути некий аналог внешнего отступа, просто очень систематичного.
Давайте на всякий случай представим, что мы это делаем на флексах, потому что у нас в требованиях совместимость с IE.

Обратим внимание на несколько моментов:

  1. Иконка находится внутри элемента, так как является его частью. Даже если мы будем ставить ее через position: absolute, мы все равно разместим ее внутри элемента, а место под нее зарезервируем с помощью какого отступа?
    Правильно, внутреннего. Так даже если мы отключим флексы, нам будут не страшны никакие схлопывания отступов и на нашу иконку ничто не посягнет.
  2. Иконка ракеты торчит наружу. Дизайнер сделал это, чтобы визуально компенсировать длину иконки и небольшой “вес” ее хвостов и носа.
    Мы могли бы и включить ее полностью, а слева добавить небольшой внутренний отступ. Это не было бы ошибкой, однако левая колонка и направляющая, показывающая границу контента непрозрачно нам намекают на то, что граница элемента идет ровно по началу текста. К тому же, нам пришлось бы смещать все элементы левее, а это все-таки сложнее, чем сдвинуть иконку.

Крупные сеточные блоки

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

У больших блоков обычно не бывает проблем с тем, чтобы увидеть их границы. Тут вообще сверху синий блок, снизу серый.

Но как сделать так, чтобы текст располагался как на макете? Это же расстояния, можно сказать, поля между текстом и границами блока…

Нет, не совсем поля. Дело в том, что эти расстояния не зависят от того, какие внутри находятся элементы, в каком порядке они там идут, сколько их и прочее. Это — охранная область блока, которая не позволяет чему-либо “прилипать” к его границам. И ее не должны создавать элементы внутри, так как они могут меняться. А вот уже между элементами поля:


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

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

А было дело, мы гэпы имитировали паддингами. Потому что гэпов еще не было. Потому что еще не было гридов. И калком мы ничего считать не могли, чтобы вычесть марджин из ширины, потому что калков не было тоже. Но за байками старого верстальщика приходите в другой раз =)

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

Верстайте интерфейс, а не картинку, проще говоря.