dr.Brain

doctor Brain

мир глазами веб-разработчика

CSS. Магия отступов

padding и margin в процентах, как это работает

dr.Brain

время чтения 4 мин.

Photo by M Angie Salazar on Unsplash

Существует вопрос, который я задаю многим разработчикам, но, к сожалению, не получаю верного ответа: “Что означают проценты для свойств CSS padding и margin?”

padding

Полученые ответы были несколько обескураживающими: 70% разработчиков не смогли ответить на вопрос, 30% - предположили, что это процент от свойства родительского элемента.

И для этих тридцати процентов у меня был заготовлен еще один вопрос: “Какое именно свойство родительского элемента является определяющим: width, height, margin, padding, border?”

Эти вопросы вызывают затруднения, не так ли? Не беспокойтесь, только 1% разработчиков знает правильный ответ. Итак, Вы будете удивлены, узнав что:

Свойства margin и padding вложенного элемента, установленные в процентах, являются процентами от ширины родительского элемента.

Обратимся к примеру:

<div class="parent">
    <div class="child"></div>  
</div>
.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, что подтверждается и блочной моделью вложенного элемента:

child padding

вложенный элемент с padding 10%

Итак, Вы узнали как правильно рассчитать margin и padding элемента в процентах.

Остается еще один вопрос: “Как вычислить высоту вложенного элемента? Зависит ли она от ширины родителя, так же как margin и padding?”

Давайте проверим:

.parent {
    width: 100px;
    height: 150px;
    border: 1px solid red;
}

.child {
    height: 10%;
    border: 1px dashed blue;
}
child height

вложенный элемент с height 10%

Получается не совсем то, что Вы ожидали: высота вложенного элемента пропорциональна высоте родителя.

Child Height = (Parent Height)*x%

Итак, мы определились с двумя основными правилами:

  1. margin и padding в процентах рассчитываются по ширине родительского элемента,
  2. высота (height) в процентах рассчитывается по высоте родительского элемента.

Эксперимент

Попробуем сделать адаптивный виджет в виде окружности?

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Card</title>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
    <link rel="stylesheet" href="card.css">
</head>
<body>
    <div class="row">
        <div class="offset-md-3 col-md-6">
            <div class="card">
                <div class="outer-circle">
                   <div class="inner-circle"></div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>
.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.


Спасибо за внимание.

Новые публикации

Далее

Категории

О нас

Frontend & Backend. Статьи, обзоры, заметки, код, уроки.