CSS. Магия отступов
padding и margin в процентах, как это работает
Существует вопрос, который я задаю многим разработчикам, но, к сожалению, не получаю верного ответа: “Что означают проценты для свойств CSS padding и margin?”
Полученые ответы были несколько обескураживающими: 70% разработчиков не смогли ответить на вопрос, 30% - предположили, что это процент от свойства родительского элемента.
И для этих тридцати процентов у меня был заготовлен еще один вопрос: “Какое именно свойство родительского элемента является определяющим: width, height, margin, padding, border?”
Эти вопросы вызывают затруднения, не так ли? Не беспокойтесь, только 1% разработчиков знает правильный ответ. Итак, Вы будете удивлены, узнав что:
Свойства margin и padding вложенного элемента, установленные в процентах, являются процентами от ширины родительского элемента.
Обратимся к примеру:
.parent {
width: 100px;
height: 150px;
margin: 2px;
padding: 1px;
border: 1px solid red;
}
.child {
margin: 10%;
padding: 10%;
border: 1px dashed blue;
}
Установленный для вложенного элемента padding: 10%;
рассчитывается следующим образом:
Child Padding = (Parent Width)*x%
В данном случае результатом будет 10px, что подтверждается и блочной моделью вложенного элемента:
Итак, Вы узнали как правильно рассчитать margin
и padding
элемента в процентах.
Остается еще один вопрос: “Как вычислить высоту вложенного элемента? Зависит ли она от ширины родителя, так же как margin и padding?”
Давайте проверим:
.parent {
width: 100px;
height: 150px;
border: 1px solid red;
}
.child {
height: 10%;
border: 1px dashed blue;
}
Получается не совсем то, что Вы ожидали: высота вложенного элемента пропорциональна высоте родителя.
Child Height = (Parent Height)*x%
Итак, мы определились с двумя основными правилами:
- margin и padding в процентах рассчитываются по ширине родительского элемента,
- высота (height) в процентах рассчитывается по высоте родительского элемента.
Эксперимент
Попробуем сделать адаптивный виджет в виде окружности?
Card
.card {
height: 300px;
background-color: #ffffff;
box-shadow: 0 20px 57px 0 rgba(51, 51, 51, 0.1);
border: none;
margin: 4%;
}
.outer-circle {
width: 100px;
height: 100px;
background: linear-gradient(to right, rgba(237, 114, 152, 0.4), rgba(236, 136, 113, 0.4));
margin: 0 auto;
border-radius: 50%;
}
.inner-circle {
width: 90px;
height: 90px;
background: linear-gradient(to right, rgb(237, 114, 152), rgb(236, 136, 113));
padding: 10px;
margin: 0 auto;
transform: translateY(6%);
border-radius: 50%;
}
Что получилось?
Получилось неплохо. Однако, спустя некоторое время Вы заметите, что виджет не изменяет свои размеры относительно родителя - карточки. В данном случае виджет, вообще, не является адаптивным.
Что должно получиться
Виджет внутри карточки должен менять ширину и высоту пропорционально изменениям ширины родителя.
Вы ошибетесь, решив что проблема решается заменой единиц измерения: пикселей на проценты.
Вспомните два правила, написанные выше: если Вы зададите высоту виджета в процентах, она будет изменяться пропорционально изменениям высоты родителя (карточки).
Так как в нашем примере изменяется только ширина карточки, а высота остается неизменной, у виджета так же будет изменяться только ширина, высота остнется неизменной. В результате круг превратится в эллипс.
Волшебство
Оказывается, у нас есть “волшебная палочка” - padding
Что произойдет, если Вы уберете свойство height
у родительского элемента (карточки) и создадите padding-bottom
в процентах?
Нижний внутренний отступ (padding-bottom) пересчитывается пропорционально ширине карточки .col-md-6
. Это означает, что свойство карточки padding-bottom
ведет себя так же, как и width
.
Великолепно! Теперь Вы можете задать высоту и ширину элементов виджета .outer-cirlce
и .inner-circle
в процентах. Свойство height
внешнего круга .outer-circle
будет зависеть от padding-bottom
родителя (а значит высота будет изменяться пропорционально изменению ширины карточки).
.card {
background-color: #ffffff;
box-shadow: 0 20px 57px 0 rgba(51, 51, 51, 0.1);
border: none;
padding-bottom: 100%;
}
.outer-circle {
width: 20%;
height: 20%;
background: linear-gradient(to right, rgba(237, 114, 152, 0.4), rgba(236, 136, 113, 0.4));
margin: 0 auto;
border-radius: 50%;
position: absolute;
left: 40%;
}
.inner-circle {
width: 90%;
height: 90%;
background: linear-gradient(to right, rgb(237, 114, 152), rgb(236, 136, 113));
border-radius: 50%;
position: absolute;
left: 5%;
top: 5%;
}
В данном случае padding-bottom
работает как “виртуальная” высота и следовательно создает действительно адаптивный блок.
Надеюсь эта статья помогла разобраться с магией отступов в CSS.
Спасибо за внимание.