Меня зовут София. Я - CSS инженер. Это мой блог.

Если вам очень больно без стилей, вы можете их.

.

Трансформации и содержащие блоки

Из спецификации нам известна фраза:

Когда значение свойства transform блока равно не none, то он становится содержащим блоком для всех своих потомков.

Что это значит?)

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

Например, в этом случае родитель .parent блока .child будет одновременно его содержащим блоком, поэтому его ширина будет 50px.

<div class="parent">
    <div class="child"></div>
</div>
<style>
    .parent { width: 100px; }
    .child { width: 50%;}
</style>

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

<div class="parent">
    <div class="child"></div>
</div>
<style>
    .parent { width: 100px; }
    .child { 
        width: 50%;
        position: absolute;
        right: 0;
    }
</style>

Также можно добавить блоку .parent любое не статическое позиционирование, чтобы сделать его обратно содержащим блоком для .child:

<div class="parent">
    <div class="child"></div>
</div>
<style>
    .parent { 
        width: 100px; 
        position: relative;
    }
    .child { 
        position: absolute;
        width: 50%;
        right: 0;
    }
</style>

Вернемся к transform и еще раз посмотрим на абзац и спецификации:

Когда значение свойства transform блока равно не none, то он становится содержащим блоком для всех своих потомков.

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

Создадим в примере еще один вложенный блок и посмотрим как это работает:

<div class="gran">
    <div class="parent">
        <div class="child"></div>
    </div>
</div>
<style>
    .gran { 
        width: 200px;
        position: relative;
    }
    .parent {
        transform: rotate(0);
        width: 100px;
    }
    .child { 
        position: absolute;
        width: 50%;
        right: 10px;
    }
</style>

Если бы не трансформации на блоке .parent, ширина блока .child была бы 100px, как половина от блока .gran. Но мы помним, что трансформированный блок является содержащим для всех своих потомков, поэтому содержащим для .child будет блок .parent, а не .gran, и его ширина будет 50px. Позиционируется .child здесь тоже относительно .parent.

Кроме относительного позиционирования, также затрагивается и фиксированное. Обычно блок с position: fixed позиционируется относительно окна. То есть сохраняет свою позицию при скролле. Из этого правила есть много исключений. Одно из них как раз если среди предков фиксированно позиционированного блока есть хотя бы один трансформированный.

Вот так блок .child позиционирован относительно окна:

<div class="gran">
    <div class="parent">
        <div class="child"></div>
    </div>
</div>
<style>
    .gran { 
        width: 500px;
        position: relative;
    }
    .parent {
        width: 100px;
    }
    .child { 
        position: fixed;
        top: 0;
        right: 0;
        width: 50%;
    }
</style>

А теперь один из его предков трансформирован и стал его содержащим блоком, и блок позиционируется и вычисляет размеры относительно этого предка, а не окна:

<div class="gran">
    <div class="parent">
        <div class="child"></div>
    </div>
</div>
<style>
    .gran {
        width: 500px;
        position: relative;
    }
    .parent {
        width: 100px;
        transform: rotate(0);
    }
    .child { 
        position: fixed;
        top: 0;
        right: 0;
        width: 50%;
    }
</style>

Источники