Flexbox is well-known for solving common layout problems such as sticky footers and equal-height columns. Beyond those capabilities, it also provides a few other useful features that aren’t so popular. Let’s explore two of them!
Flexbox and z-index
As you probably already know, the
z-index
property works only on positioned elements. By default, all elements have position: static
and aren’t positioned. An element is “positioned” when its position
property is set to relative
, absolute
, fixed
, or sticky
.
However, an “unpositioned” element, such as a flex item can also receive the
z-index
property. The CSS Flexible Box Layout spec says:Flex items paint exactly the same as inline blocks [CSS21], except that order-modified document order is used in place of raw document order, and z-index values other than auto create a stacking context even if position is static.
To understand this behavior, consider the following example:
Here we define two elements: the
.front
element and the .back
element. The .front
element has one child, a box with a number “1”. The .front
element itself is absolutely positioned. Specifically, it has position: fixed
and covers the entire viewport.
Our
.back
element is a flex container. It contains two child elements — boxes with numbers “2” and “3”. Based on what we’ve discussed above, we can set the z-index
property of its flex items, even if they aren’t positioned elements (i.e. they have position: static
).
Notice that when we add
z-index: 2
to the flex items by clicking the button in the demo above, they are positioned on top of the .front
element.Flexbox and Auto Margins
By applying auto margins to flex items, we’re able to solve common UI patterns. To begin with, let’s assume that we want to build this typical header layout:
To build it, we’ll use flexbox. No floats, fixed widths, or anything like that.
Here’s our markup:
<header>
<nav>
<h1 class="logo">LOGO</h1>
<ul class="menu">
<li>
<a href="">About</a>
</li>
<li>
<a href="">Projects</a>
</li>
<li>
<a href="">Contact</a>
</li>
</ul>
<ul class="social">
<li>
<a href="">Facebook</a>
</li>
<li>
<a href="">Twitter</a>
</li>
</ul>
</nav>
</header>
Our CSS looks like this:
header {
background: #333;
}
nav {
display: flex;
align-items: center;
width: 90%;
max-width: 1200px;
margin: 0 auto;
}
.menu {
margin-left: 60px;
margin-right: auto;
}
In this example, our
nav
element is the flex container and the logo, main menu, and social menu the flex items. As you can see from the previous visualization, the first two flex items are aligned to the left side of the flex container along the main axis. On the contrary, the social menu is aligned to the right edge of its parent along the main axis.
One way of achieving this custom alignment is to add
margin-right: auto
to the main menu. With just one line of code, we’re able to override the default alignment for the social menu and push it all the way to the right of its container. Similarly, we use the align-self
property to override the default alignment for a flex item along the cross-axis.
Beyond auto margins, there’s a second method we can use to build the desired layout. First, we remove the
margin-right
property from the main menu and then, we add flex-grow: 1
to it.
Even though the result in both cases seems the same, there’s one big difference. With the first solution, our menu has its initial calculated width. So for example, when the viewport width is 1100px the menu width would look something like this:
On the other hand, with the second solution, the menu width gets bigger because we specify
flex-grow: 1
. Here’s its corresponding width when the viewport width is 1100px:
The Codepen demo:
Let’s now assume that we want to modify the header layout. Here’s the new desired one:
The markup remains the same. We just make a few changes in the CSS:
nav {
background: #333;
display: flex;
flex-direction: column;
height: 100vh;
width: 180px;
padding: 20px;
box-sizing: border-box;
}
.menu {
margin-top: 60px;
margin-bottom: auto;
}
In this example, notice that the social menu is aligned to the bottom edge of its parent. Again, this is done it by adding
margin-bottom: auto
to the main menu. Of course, we can also use flex-grow: 1
, yet this solution will increase the menu height.
See the Codepen demo below:
Another thing to keep in mind is that if we define the
justify-content
property in any of our examples, we won’t see any visual difference. That happens because we use auto margins to align the flex items. Only when we remove the auto margins will the justify-content
property take effect. According to the spec:If free space is distributed to auto margins, the alignment properties will have no effect in that dimension because the margins will have stolen all the free space left over after flexing.
Next, let’s create a new variation of our header:
Undoubtedly, this can be easily achieved by setting
justify-content: space-between
to the flex container. But once again, we’re able to produce the same layout with auto margins. All we have to do is to apply margin: 0 auto
to the main menu.
The Codepen demo:
How z-index and Auto Margins Work in Flexbox
Reviewed by JohnBlogger
on
1:24 AM
Rating:
No comments: