Header layout


z-index controls the stacking order of positioned elements only. If an element isn’t positioned then its unlikely to overlap (ignoring negative margins for now) and z-index would have no effect unless you add a value for the position property other than ‘static’.

Positioned elements will be naturally stacked with regard to their html order with elements later in the html being stacked on top of the ones before. Therefore if you want an earlier element in the html to be stacked on top of something later in the html (which also may be positioned) then you arrange the z-indexes so that the stacking order meets your requirements.

This is a simplistic view of stacking order and z-indexes because positioned elements with a z-index other than ‘auto’ become ‘atomic’ for their children and no matter the z-index of the child it cannot escape from its parents z-index in regard to other elements outside that context.

There are also special rules for certain properties that create automatic stacking indexes such as opacity and transforms etc. It’s a broad subject that needs to be studied :slight_smile:


Thanks for your explanation Paul. I know that z-index in most cases requires an element to be positioned. I think the part I don’t understand is why there’s no z-index property in the following rule


This is interesting…didn’t know we can combine flex properties with other ones like display:block. it’s good to know.


A flex item is naturally displayed as a block display. I only added it because previously it was display: none but now it’s being hidden by other means to allow the animation.

You don’t need to set the display properly for a flex container or flex item.


I was wondering if its possible to make the following changes to menu:

  1. Right now the whole menu drops down from top of the browser window. Is it possible to make it start drop down 10 -15 px from the bottom of h1 and hamburger icon? ( same behaviour as shown via link in post #47)

  2. When the hamburger icon is clicked and menu is active, on resizing browser window past 960 px the menu disappears which is correct. However, on resizing browser window back when it hits 960 px the menu gets activated (shown) without clicking on ham icon which is incorrect (behaviour expected is same as shown via link in post #47 - no menu just ham icon on resizing back…)


The menu you linked to uses a lot of JS to create the effect and I find that page very jittery when you open and close the window because they monitor the resize event. It makes the page seem unresponsive and ‘laggy’ and not a good example to follow. (There are also occasions where the page stretches for miles due to some bug they have not squashed)

The drop down is animated to its height and that can only be obtained through js and constantly monitored on resize or font-size change. I much prefer my version.

You can change my version to appear to drop down from the menu but would require some changes to the html but still wont look exactly the same.

I also find that unintuitive because if you opened the menu on small window size you theoretically would still want it open when you return to that size unless you had closed it yourself.

To make the menu close the example you pointed to again monitors the resize event in JS and removes the class that opens the window. That again is a bad move and it would be better to use matchmedia to replicate media queries and avoid the lag from using the resize event.

Here is an old example of mine that is close to what you are asking and all the code is contained in the codepen.

I am away today so can’t look at this again until this evening.


thats fine. if can point me to what changes I need to make to html. I just curious how would it look. If you are busy that’s ok no rush.


that example actually looks/works more smoothly when you click on ham button and when it drops down…


Yes that one uses clip-path to show the menu but browser support is a little spotty at the moment.

Here is a quick re-jig of your page to allow the menu to be hidden at the top so it appears to only arrive from the bottom of the header.


Just view source as I have included all css and js in the page itself.

This is accomplished by shimming a white background over the header and letting the menu hide beneath the background as it goes up. In order for this to happen the z-indexes of items in the header are carefully manipulated.

I’ve also added the matchmedia js so that the responsive class is moved when the page is wider. I also moved the responsive class to the header itself as that means you can change other things in the header at the time the menu is open (like the hamburger or whatever).

I also added classes to the header because it is bad practice to directly target elements like header and footer because they can be used in many places and if you have third party code or widgets added you may get conflicts.


Thanks a lot Paul. I quickly checked the link and the menu now looks like what I was after…even better.
I am thinking to try play with menu items height and width just for design purposes.

In terms of learning opportunity it’s gonna take me some time to try fully understand the code. I am not good with JS - just basics. Also there’s some CSS properties like clip which is new for me.

Ideally I am gonna try comment each line of code I don’t understand.
Hope you don’t mind my further questions…


Hi Paul,

I just noticed there’s slight flickering of part of the menu on the left side when I resize browser window down to 960 px.


It doesn’t happen on resizing back though…


You can fix that by adjusting the initial right position of the menu in this rule.

  .topnav ul {
    position: absolute;
    margin: 0;
    padding: 0;
    left: -999em;
    right: 999em;
    top: 0;
    opacity: 0;
    transition: transform 0.5s ease, opacity 0.5s ease, left 0s 0.5s, right 0s 0.5s;

I changed it from right:100% to right:999em which will makes sure its off the left side of the screen (unless the screen is wider than 16000px approx).

It’s a bit of a non-issue anyway because 99.9% of your visitors will not be flipping their screen size up and down all the time. It’s only developers that do that :). Most people have the browsers at the size they want when they load the page although a few will re-arrange the page but they certainly won’t keep resizing up and down every few minutes.

Actually it could be a bit of a feature as it gives you a clue that something has changed:)

Either way you can fix it with code above which has been added to the demo for testing.



Hi Paul, just to clarify as you already explained it before about positioned elements and z-index. You mentioned that position absolute makes this menu sit on top of the following content which is the above rule.

I also noticed that in your previous code was the following position relative rule with z - index.

So this is the first rule with position absolute that makes menu sit on top? Not the second rule…


Positioned elements are placed in relation to the nearest ancestor that has a value for the position property other than 'static. Therefore the .topnav element has position:relative defined and creates the stacking context for the absolutely placed child otherwise the child would be placed in relation to the viewport should no positioned parent exist.

The z-index:99 on .topnav ensures that the header (which includes the absolutely place navigation) will cover any elements that they overlap that have a lesser z-index.

If you are referring to the position of the nav where it overlaps the page content then its position is created with position:absolute (i.e. it is removed from the flow and placed on top of anything in the way). However should the content that was in the way have a z-index higher than 99 then the menu would be behind that content.

That’s a simplistic example of stacking context because I think I mentioned before that no matter what z-index an element has its the positioned parent that controls the stacking context of the absolutely placed children unless the parent’s z-index is auto.

So to place an element so that it overlaps something you need to use position:absolute.

To place that element from the current starting position (not the viewport) you need to add position:relative to the parent of that absolute element.

To layer the elements (front to back) you use z-index.

There are a lot of other rules but that’s the basics :slight_smile:


This part answers my question :slightly_smiling_face:
Thanks for the good explanation Paul.

 .header {
    flex-wrap: wrap;
    position: relative;
  .header h1 {
    position: relative;
    z-index: 1000;

.header uses position: relative in relation to the body however purpose is to create positioning context for .header h1 which is also positioned relative in order for z-index to work? Just want to make sure I understand this correctly…


The position:relative on .header is so that the header:after element can be used as an overlay and absolutely positioned over the whole header. The position:relative on the header creates the context for the absolutely placed children. It has nothing to do with the body element as such.


  .header:before {
    content: "";
    position: absolute;
    z-index: 999;
    left: 0;
    right: 0;
    bottom: 0;
    top: 0;
    transition: background 0s 0.5s;
    background: transparent;

It’s transparent at first but a media query switches its background to white for small screens. This is so that the dropdown navigation can hide behind the white background as it goes up and down to create the effect you wanted.

However when we do the above all elements in the header will be hidden unless we give them a position other than static and layer their z-indexes accordingly.

Therefore the h1 and the button are given position:relative so that a z-index greater than the overlay can be applied. The overlay is z-index:999 and the header elements apart from the nav are z-index:1000.

The nav is given a z-index of 998 which places underneath the white coloured overlay. This hides the menu while not in use but when the menu is toggled it moved down the page and can then be seen as it peeks out of the overlay which only covers the header portion.

There are three z-indexes in all that maintain how the header works. As long as any page elements that follow have a z-index less than 998 then they will not obscure the drop navigation when it appears.:slight_smile:


Is that the rule that switches it to white…?

.header.responsive:before {
    transition: background 0s 0s;
    background: #fff; /* hide nav when it scrolls up and down*/


Yes :slight_smile:


#fff is a shortcode for #ffffff which is white.

See https://en.wikipedia.org/wiki/Web_colors for more details.