Using Layers
A third dimension
Layers in CSS refer to the notion that with a two dimensional medium like a monitor screen items may be considered to have a third dimension in which some data items are 'nearer' to the viewer than others, the nearer overlaying and possibly obscuring the further. The first two dimensions — horizontal or x and vertical or y — are essentially analogue and are controlled by CSS properties such as width, height, left and right, the third dimension is rigidly digital and may be controlled by the z-index property.
Layers within an element
The z-index works with elements to control how far 'forward' or how far 'back' they appear but before considering how one element may be layered against another, we need to look at the behaviour within a single element.
Each element may be considered as having a micro-structure of several layers. This is very elegantly illustrated by Jon Hicks' 3D CSS Box Model hierarchy [Ref1 ] in the image shown. In this we may note
- Two areas, margin and padding are transparent so have no visual effect
- Other content moves in the z dimension from back to front in the order
- Background colour
- Background image
- Border
- Content
Overlapping elements
In normal flow it is fairly rare for elements to overlap but there are some important exceptions.
- On every page all other elements overlap the body.
- Divs are often used to achieve a desired layout. The elements they contain overlap them.
However consider the following simple case of elements in normal flow.
Later in tree
stack on top
Rectangle 1 - Green
Rectangle 2 - Red
Rectangle 3 - Blue
The three coloured rectangles are divs which follow each other in the document tree i.e. in the source code for the page. Normally they would each start on a separate line so would not overlap but rectangles 2 and 3 have been moved from their normal position by applying left and negative top margin so that they stack on top of each other.
As might be expected those later in the tree are painted later on screen overlapping others and appearing nearer to the viewer. We say that they have a higher level in the stack. This is the normal default.
The default order may be altered using the CSS property 'z-index'. This gives us control of the stack level — the higher the z-index value the higher the element appears in the stack.
The next case shows that by applying a z-index the stacking order may be changed.
z-index
controls stack level
Rectangle 1 - Green - z-index: 0
Rectangle 2 - Red - z-index: 3;-
Rectangle 3 - Blue - z-index 2;
The tree order for the rectangles has not altered but the rectangles have been allocated z-index in the order 0 - 3 - 2 which differs from the tree order. The stacking order is now in z-index order rather than tree order.
The value for z-index may be zero or any positive or negative integer. Values do not need to be consecutive, the list may have missing values. z-index may alternatively have a value of 'auto'.
Using z-index
To use z-index there are two prerequisites:
-
z-index
applies only to positioned elements - The indexed element must be 'positioned'
(If no ancestor is positioned z-index will work based on the 'root' element giving the same effect as if based on the body.)
To be 'positioned' an element must have the CSS 'position' property assigned with a value of relative, absolute or fixed. Note this does not involve moving the element, if the element is not positioned already simply assign a value of relative.
In the demonstrations that follow the squares and rectangles are positioned divs*. The squares, with solid borders, are the parents of the rectangles with dotted borders of the same colour. Most of the divs have z-index specified as indicated, some have no z-index. The blue (left hand side) square is earlier in the tree order than the red (right) (used in demo 7 onwards). In each square the top rectangle is early in tree order followed by middle and bottom.
* Demos 1 to 6 would work equally well if the blue square was not positioned.
Demo 1
Demo 2
Demo 3
In the first three demos the parent squares have no z-index property. In the first demo the rectangles have no z-index, they are stacked in tree order, later ones partly obscuring the earlier. In the second demo the rectangles have z-index values and the stack is formed in order of the z-index. This becomes clear in demo 3 where the order of z-index differs from tree order and the z-index prevails.
Demo 4
Demo 5
In demo 4 all rectangles have the same z-index. Any possible conflict is resolved by stacking them in tree order. In demo 5 the same applies but the z-index value is auto.
Stacking context
We now turn to a very important concept — the Stacking Context.
So far the parents of our rectangles have not themselves had any z-index assigned. When a parent has a z-index, other than auto, a 'stacking context' is created. All children are stacked within that context and no other.
Demo 6 shows how that can affect the stacking order.
z-index: auto;
stacks at level of parent
z-index: integer;
establishes
stacking context
This needs some explanation
- Allocating the square a z-index establishes a stacking context
- In that context the parent (the square) is assumed to have a z-index of zero
- This is independent of the z-index property in the CSS style for the parent.
- Children are stacked within the stacking context in order lowest to highest z-index
- Any child with z-index unspecified or auto assumes a z-index the same as the parent
As a result of this the rectangles stack in the z-index order -1, auto, 1 which is effectively -1, 0, 1. (Even though the CSS style for parent assigns a z-index of 2. That number relates to the stacking context in which the square sits NOT the one it forms.)
Multiple stacking contexts
We will now look at the relationship of one stacking context to another.
In Demo 7 The blue square is joined by a red square. This is similar in design but the rectangles have been positioned so that those from the blue and red squares may impinge on each other.
Stacking contexts cannot overlap
Demo 7
Demo 8
The blue and red squares have now been allocated a z-index value, in Demo 7 the red square has the higher value. In each square the rectangles are stacked within their stacking context in z-index order. The red and blue squares exist within some other stacking context and similarly are stacked in z-index order. All the rectangles in the red square are layered above any in the blue square irrespective of the z-index value of the rectangle because the stacking contexts are independent of each other. All the blue rectangles are stacked within the stacking context of the blue square, all the red rectangles are stacked within the stacking context of the red square.
Demo 8 simply raises the z-index of the blue square so that the stacking context of the blue is higher that that of the red.
The demonstrations have shown two parallel stacking contexts. Because the rectangles are all allocated z-index with integer value they each - all six of them - also form stacking contexts so that there is the potential for them to support their own stacks but there is no need for further explanation.
Using negative z-index
Usually authors can confine themselves to using positive values of z-index. If that's all you need you can skip this section. The main application for negative z-index is probably to selectively hide elements though there are alternative ways of achieving this, for instance using display: none; Coming to grips with negative z-index can be difficult so if you do read on be prepared for the consequences.
The next set of demonstrations shows the blue and red squares as children of green rectangles. Since these have z-index : 0; they create stacking contexts within which the squares (which also create stacking contexts) are stacked. The order of the layers in any stacking context is from the lowest z-index to the highest. Even if the z-index is negative the stack forms above the parent with no elements below[Note1]. Demos 9 & 10 illustrate this.
Stacking occurs
above
stacking context
Demo 9 z-index: 0
Demo 10 z-index: 0
In the next two Demos the squares have z-index: auto; they do not establish stacking contexts so they stack at the level of whichever ancestor forms the stacking context (the green rectangle). Similarly the rectangles also stack in the same context (there being no alternative available).
z-index: auto; stacks at level of parent
Demo 11 z-index: 0
Demo 12 z-index: 0
Demo 11 illustrates this.
- The green rectangle creates a single stacking context within which all the squares and small rectangles are stacked.
- All rectangles are stacked in order of z-index
- The squares having z-index: auto; are stacked at the level of their parent i.e. as if the z-index were zero.
- Where two elements have the same z-index they stack in tree order.
Adding a background colour in Demo 12 shows that all the rectangles stack in front of the green rectangle even the one with z-index of -10[Note2].
Demo 12 shows a different issue. Everything is identical except that the blue square has a background colour.
Referring to Demo 6 we are reminded that, since the square has z-index: auto;, it stacks at the level of its parent with z-index of zero. This means that the rectangle with z-index: -2; which it contains will stack below its background and be hidden.
This method of hiding elements using negative z-index works only if they are to be hidden behind an element with z-index auto. If the square had z-index zero it would create a stacking context and all the rectangles would appear in front of it. Yet it only works because the z-index is considered to be zero so the rectangle to be hidden can slip in behind it.
Resolving the complexity
So we have a perplexing situation. Every element in a stack, irrespective of whether the z-index is positive or negative, stacks above the stacking context. In examples 11 & 12 both the element forming the stacking context (green rectangle) and the two squares are considered to have z-index zero. The rectangles with negative z-indexstack below the square butapparently above the stacking context – the green rectangle – which has the same z-index. How does this come about?
Elements normally stack one on top of each other in z-index order. The element forming the stacking context has, in its own context, z-index of zero. The three elements with z-index zero stack in tree order. This still doesn't explain how the rectangles with negative z-index slip to a lower level.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus pulvinar, magna id mattis varius, turpis nibh imperdiet quam, vel condimentum velit sem id elit. Morbi sit amet ante. Curabitur sed ligula convallis mauris pulvinar vulputate. Donec dictum. Curabitur convallis turpis et velit. Pellentesque libero leo, ultrices porta, ullamcorper id, rutrum at, mi. Suspendisse lobortis, ipsum et rhoncus venenatis, est mi malesuada massa, vitae mollis turpis purus nec lacus. Nam vel erat in ipsum scelerisque imperdiet. Phasellus tempor. Duis enim risus, facilisis ut, semper eget, porta at, sem. Mauris tristique, orci sit amet scelerisque aliquet, nunc eros dictum wisi, non auctor arcu turpis id dui. Cras turpis erat, viverra quis, venenatis vitae, malesuada dignissim, nulla. Nam sed eros in mi malesuada semper. Proin mi diam, gravida sit amet, molestie sed, rhoncus ultricies, nisl. Mauris faucibus vehicula mauris. Sed consectetuer, enim sed gravida volutpat, urna libero ullamcorper tortor, tincidunt viverra lorem nisl fermentum risus. Sed eu massa. Quisque ultricies. Vestibulum nisl libero, fermentum ut, posuere eget, commodo vitae, pede. Donec euismod vehicula leo. Duis a massa. Aenean vestibulum condimentum nibh. Donec leo lorem, elementum et, scelerisque pellentesque, tempus ut, libero. Nulla facilisi. Vivamus ante nibh, blandit eu, volutpat et, faucibus quis, libero. Quisque ornare, orci id malesuada interdum, risus urna sodales neque, porttitor tincidunt massa neque vel pede. Vestibulum ipsum neque, semper eu, luctus id, faucibus aliquam, tellus. Nam id augue sed quam viverra tristique. Suspendisse est massa, ultricies eget, ullamcorper sit amet, iaculis pulvinar, tellus. Vestibulum dapibus porta libero. Morbi vel leo et nunc volutpat blandit. Donec vehicula sem eget turpis. Mauris diam turpis, sagittis nec, adipiscing a, fringilla et, nibh. Morbi commodo elit id mauris. Praesent consequat libero a est. Nulla facilisi. Suspendisse eleifend. Phasellus interdum lorem ac felis. In hac habitasse platea dictumst. Quisque ipsum. Aliquam vel wisi. Proin ligula ipsum, vulputate vitae, facilisis ut, molestie vel, augue. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus mattis imperdiet mauris. Etiam varius pellentesque tellus. Mauris varius aliquam odio. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis mauris felis, scelerisque sed, feugiat sed, bibendum non, libero. In leo purus, aliquet eget, dapibus ac, condimentum ac, massa. Sed euismod libero. Cras aliquet odio sit amet ante. Aenean blandit est a erat. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In nec ante vel purus sollicitudin gravida. Vivamus tincidunt. Integer ante urna, pellentesque eget, eleifend tempus, fringilla sit amet, pede. Quisque sed velit id diam tincidunt viverra.
Look at it this way. When you reach the lowest level in a stack, instead of elements stacking one on top of each other the parent element splits itself. Elements with negative z-index stack in order, not on top of the parent element, but on top of its background and border but under its content. See layers within an element.
The figure on the right attempts to illustrate this. A div with dark blue border and red content creates a stacking context in which sit three further divs which have various z-index values. These divs have light blue borders and are slightly offset so that they can overlap the parent. Note the borders are solid colour NOT transparent. You can see that the div with negative z-index sits over the border but below the content of the parent, all others sit above the content.
Layered presentation is explained slightly more fully in Specifying the stack level [Ref2] which forms part of the CSS specification with more detail of stacking within an element.
Browser support
z-index is well supported by the latest versions of all browsers.
Note 1 Firefox prior to version 3 treated negative values of z-index incorrectly stacking them below the parent instead of above.
Note 2 Internet Explorer prior to version 8 treats z-index: auto; as z-index: 0. This can result in the creation new stacking contexts where none are intended. Demos 11 & 12 will fail.