Transform stacks the rules

Many people don’t know that `transform` rules are relative to the position reached at the previous rule, rather than starting point. Take for example these transformations:

CSS

        transform: translateX(20px) translateX(30px) rotate(45deg);
      

First, the element will move 20px to the right, then additional 30px, and only then rotate 45 degrees. When you rotate an element, you also rotate the reference system, and further rules will be relative to the new reference system.

These two lines give completely different results:

CSS

        transform: translateX(100px) rotate(45deg);
transform: rotate(45deg) translateX(100px);
      
The order of transformation rules matters

The order of transformation rules matters

by Dmitry Salnikov

Vertical padding/margin are relative to the parent's width

We expect that padding-top: 50% would be relative to the parent's height, but in reality it is not: it’s relative to the parent’s width. Let’s look at this example:

HTML

        <div class="parent">
  <div class="child"></div>
</div>
      

CSS

        .parent {
  width: 400px;
  height: 200px;
  background: red;
}

.child {
  padding-top: 50%;
  background: blue;
}
      

Child's padding-top equals 50% of the parent's width, (400px * 50% = 200px) so it takes all the space now.

The child (blue) completely covers its parent (red) though we have set the padding to 50%.

The child (blue) completely covers its parent (red) though we have set the padding to 50%.

by Dmitry Salnikov

This can be useful for preserving aspect-ratio while the container is fully responsive. It’s especially useful for videos and images. In this example, we’re trying to preserve 16/9 aspect ratio for the video. For that we set for the video container `padding-bottom = 100% * 9 / 16 = 56.25%`, and then the video itself is "absolute positioned" and takes 100% of width and height of its parent:

HTML

        <article class="article">
  <div class="video-container">
    <iframe class="video"></iframe>
  </div>
</article>
      

CSS

        .article {
  width: 100vw;
  height: 10000px;
  background: yellow;
}

.video-container {
  width: 100%;
  padding-bottom: 56.25%;
  position: relative;
}

.video {
  width: 100%;
  height: 100%;
  position: absolute;
  background: black;
}
      

Video will preserve 16/9 aspect ratio while being fully responsive.

The fact that vertical padding is relative to the parent’s width can be pretty useful when you need to preserve aspect ratio for an element.

The fact that vertical padding is relative to the parent’s width can be pretty useful when you need to preserve aspect ratio for an element.

by Dmitry Salnikov

Margins can collapse

Suppose we want to create the following nested layout:

Layout with nested elements, each with its own margin.

Layout with nested elements, each with its own margin.

by Dmitry Salnikov

A browser will notice three adjacent margins blocks, and it will want to join them in one big margin block. The result will look like this:

All margins collapse into a single empty space, ruining our brilliant design.

All margins collapse into a single empty space, ruining our brilliant design.

by Dmitry Salnikov

It’s important to understand and remember when does it happen. The conditions are:

  • Only positive vertical margins (horizontal margin don’t collapse);
  • Outer elements don't contain text or other content;
  • No paddings or borders are set;
  • Display is "block";
  • Overflow is "initial" or "visible".

A similar situation happens when we define a margin between siblings:

This weird CSS behavior works also for sibling elements, collapsing adjacent margins into a single empty space.

This weird CSS behavior works also for sibling elements, collapsing adjacent margins into a single empty space.

by Dmitry Salnikov

Background supports multiple images

Few people know that "background" property supports multiple images, separated with a comma:

CSS

        background: url('first-image.jpeg'),
            url('second-image.jpeg') bottom right,
            linear-gradient(...);
      

You can use as many background images as you want, even applying additional background rules (like repeat, position, etc.). Take a look at this example on Codepen: a picture of Linus is placed above a gradient image – both via the same CSS `background` rule.

You can add as many background images as you want using a single `background` rule.

You can add as many background images as you want using a single `background` rule.

by Christian (codepen.io/crisz)

 Z-index

Z-index seems so simple: elements with a higher z-index are stacked in front of elements with a lower z-index, right?

Well, actually, no. To arrange elements along Z-axis you need to know the following rules:

  • The stacking order is the same as the order of appearance in the HTML;
  • Any positioned (not static) elements (and their children) are displayed in front of any non-positioned elements;
  • z-index only works on positioned elements;
  • z-index creates a stacking context

If you’re scratching your head trying to guess what is a “stacking context”, well... welcome to the club. Very few people know about the stacking context and how does it work. In simple words, it’s a group of elements with the same parent root element. If one stacking context has a higher z-index than another one – then all children in that another context are positioned “under” the children of the first context. And there’s no way to put them “above”, even if you set a “billion” z-index to one of its children. Take a look at this picture:

Two elements with defined z-index are forming two different stacking contexts. The butterfly on the left cannot be higher than the butterfly from another stacking context (on the right), even though it has a larger z-index value.

Two elements with defined z-index are forming two different stacking contexts. The butterfly on the left cannot be higher than the butterfly from another stacking context (on the right), even though it has a larger z-index value.

by Dmitry Salnikov

There are certain rules. A new stacking context is formed when:

  • It's a root element of a document ("html" element);
  • An element has a "position" value other than static and a "z-index" value other than auto;
  • An element has an "opacity" value less than 1, or applied "transform", "filter" and some others.

The last statement may sound weird, but seems like if a CSS property requires rendering in an offscreen context – it creates a new stacking context. Take a look at this example on Codepen.

As you see in the “Result” tab, elements with a higher z-index are positioned higher, but then If you click the button – the red square (despite having z-index = 10) gets under the blue square with the lowest z-index. Why?

Let’s break it down by element and assign a stacking order. As we already know, the stacking order is the same as the order of appearance in the HTML, but for "spans" we override the order with z-index, so we end up having this order:

HTML

        <div><!-- 1 -->
  <span class="red">z-index:10</span><!-- 6 -->
</div>
<div><!-- 2 -->
  <span class="green">z-index:2<span><!-- 5 -->
</div>
<div><!-- 3 -->
  <span class="blue">z-index:1</span><!-- 4 -->
</div>
      

When you click the button:

HTML

        <div><!-- 1 -->
  <span class="red"><!-- 1.1 --></span>
</div>
<div><!-- 2 -->
  <span class="green"><!-- 4 --><span>
</div>
<div><!-- 3 -->
  <span class="blue"><!-- 5 --></span>
</div>
      

If you find this article interesting, don’t hesitate to share with your colleagues. Thanks for reading my blog.

Helpful resources: