0

I'm trying to build a layout with CSS Grid. I want the header element to be 'sticky'. That is, when the user scrolls, the header stays fixed to top of viewport and other content scrolls up and underneath header. I'd like to give this header a background image.

I've assigned a background image to the header, given it a position value of fixed and applied a z-index value of 999. Other elements below have been positioned and given lower z-index values.

My problem is that this setup doesn't work. I tried a few variations on the CSS but the background image either completely disappears or, on scroll, the header does not stay above other elements as they move up the screen.

What am I doing wrong? I browsed other questions in this forum and also on the web in general but can't find an answer.

Any suggestions much appreciated.

My code is shown below (including various changes to CSS - commented out in most cases).

    body {
    	display: grid;
    	grid-template-areas: "header header header" "nav article ads" "footer footer footer";
    	grid-template-rows: 250px 900px 70px;
    	grid-template-columns: 20% 1fr 15%;
    	grid-row-gap: 10px;
    	grid-column-gap: 10px;
    	height: 100vh;
    	margin: 0;
    }
    header {
    	/* position:fixed;
    z-index:999;*/
    }
    footer, article, nav, div {
    	padding: 1.2em;
    	background: gold;
    }
    #pageHeader {
    	grid-area: header;
    	padding: 1.2em;
    	background: url(https://placeimg.com/50/250/arch) left top repeat-x fixed;
    }
    #pageFooter {
    	grid-area: footer;
    }
    #mainArticle {
    	grid-area: article;
    	position: relative;
    	z-index: 9;
    }
    #mainNav {
    	grid-area: nav;
    	position: relative;
    	z-index: 8;
    }
    #siteAds {
    	grid-area: ads;
    	position: relative;
    	z-index: 7;
    }
    /* Stack the layout on small devices. */

    @media all and (max-width: 575px) {
    	body {
    		grid-template-areas: "header" "article" "ads" "nav" "footer";
    		grid-template-rows: 80px 1fr 70px 1fr 70px;
    		grid-template-columns: 1fr;
    	}
    }
<body>

  <header id="pageHeader">Header</header>

  <article id="mainArticle">Article</article>

  <nav id="mainNav">Nav</nav>

  <div id="siteAds">Ads</div>

  <footer id="pageFooter">Footer</footer>

</body>

5
  • Remove other elements z-index. add position: fixed on your header and give it a width and height then also z-index of 1 Commented Feb 2, 2018 at 7:43
  • @Gezzasa Thanks! I'll try this. Commented Feb 2, 2018 at 7:49
  • Any luck with the code? Commented Feb 2, 2018 at 11:37
  • @Gezzasa Sorry for delayed reply. Yes, your code works! Many thanks. I'm just starting to learn CSS Grid, can you explain why this works yet my original code didn't? Also. Andrew Rubin (below) says the header can't be inside the grid (?) ... why is this? Commented Feb 3, 2018 at 21:48
  • The grouping of your elements is a bit weird. I'd suggest taking a quick free course on udemy just to check the beginner markup. Will help a lot. I left you an answer regarding the z-index. Commented Feb 5, 2018 at 11:18

3 Answers 3

1

Remove other elements z-index. add position: fixed on your header and give it a width and height then also z-index of 1

Element positioned absolute works kinda like layers. The DOM and z-index (x and y axis is 2d coords and z axis is for the stacking) tells it where to sit depending on where it is on the DOM.

Read through this for a detailed explination...I will most likely screw it up if I try explain any further.

Sign up to request clarification or add additional context in comments.

Comments

0

Your <header> element needs to be placed outside of your grid. Currently, the grid encompasses everything, including the header, since it's on the body tag. Instead of using display: grid; on the body, make a container within the body that has display: grid;, and make the header live outside of that container. For example:

HTML:

<body>

    <header>Header content!</header>

    <div class="container">

        <div class="mainNav"></div>
        <div class="sidebar"></div>
        <div class="siteAds"></div>
        <!-- etc. -->

    </div>

</body>

And the CSS:

body {
    /* your normal body styles go here */
    /* but display: grid; should no longer be here */
}

header {
    position: fixed;
    z-index: 10;
    height: 100px;
}

.container {
    display: grid;
    margin-top: 100px; /* to offset the header's height */

    /* and all the rest of your grid styles */

}

What's important to remember here is that the header must not be part of the grid layout.

Comments

0

Use this Jsfiddle...

I have added some css styles and jQuery

CSS

#pageHeader.fixed {
    position: fixed;
    top:0; 
    left:0;
    width: 100%;
    z-index: 99;
}

jQuery

$(window).scroll(function(){
    var sticky = $('#pageHeader'),
    scroll = $(window).scrollTop();

    if (scroll >= $('#pageHeader').height()){
        sticky.addClass('fixed');
        $('#pageHeader').addClass('fixed');
    } else {
        sticky.removeClass('fixed');
        $('#pageHeader').removeClass('fixed');
    } 
});

4 Comments

Or use bootstrap navbar with fixed. use w3schools.com/bootstrap/bootstrap_navbar.asp
He's not using bootstrap. He's not using z-index properly is all.
@SarvanKumar Thanks for your advice. Is there a way to do this without jQuery?
with out jquery it will always fixed. you can add the fixed class only in that element and remove jquery. like this.. jsfiddle.net/635dv0k8/1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.