Coastal Media Brand

In this new tutorial, we’ll start with a full-screen section with a heading and learn how to animate it to a fixed page header on scroll. This type of effect is ideal for layouts with hero sections like a landing or a single post page.

1. Begin With the Page Markup (HTML)

We’ll define two sections:

  • The first section will be full-screen and contain a heading and page header. By default, only the heading will appear. Inside the header, we’ll position the logo and menu.
  • The second section will include some dummy content. Below this section, we can have many more.

Here’s the markup:

1
<section class="first">
2
  <h1>Full-Screen Section to Fixed Header</h1>
3
  <header class="page-header">
4
    <nav class="nav">
5
      <a href="" class="logo-wrapper uk-flex uk-flex-middle">
6
        <img width="178" height="38" src="forecastr-logo-white.svg" alt="forecastr logo">
7
      </a>
8
      <ul>
9
        <li>
10
          <a href="">Home</a>
11
        </li>
12
        <li>
13
          <a href="">About</a>
14
        </li>
15
        <li>
16
          <a href="">Contact</a>
17
        </li>
18
      </ul>
19
    </nav>
20
  </header>
21
</section>
22
<section class="second">
23
  <div class="container">...</div>
24
</section>

2. Set the Main Styles (CSS)

Let’s take note of the main styles—you can see all of them by clicking on the CSS tab of the demo project:

  • The first section will be a fixed-positioned element and full-screen. Additionally, it’ll behave as a grid container with vertically centered content. You can alter the height of the first section through the hero-height CSS variable.  For instance, if you want this section to cover only half of the screen, change the CSS value from 100vh to 50vh.
Layout with a hero section that covers half of the viewport heightLayout with a hero section that covers half of the viewport height

  • As we’ve done many times in the past, we’ll use CSS Grid to stack the heading and page header. To do so, we’ll give them grid-area: 1/1. This is the shorthand of setting grid-column: 1 and grid-row: 1
  • As we’ve already discussed, the page header will initially be invisible. To do so, we’ll give it opacity: 0 and visibility: hidden. The last rule is required to prevent click events.
  • The nav element will be a flex container with vertically centered content. On large screens, the logo will sit on the left side and the menu on the right side. On small screens (≤600px), we’ll stack them.
The nav layout on large screensThe nav layout on large screensThe nav layout on large screens
The nav layout on large screensThe nav layout on mobile screensThe nav layout on mobile screensThe nav layout on mobile screensThe nav layout on mobile screens

  • The second section should sit underneath the first one. To accomplish this, we’ll give it padding-top: 110vh. This value matches the height of the first section (100vh) plus 10vh to create the gap between the text and the section’s top edge (equal to the bottom padding). If we don’t give it any padding-top value, the second section will sit behind the first section at the top of the page. Remember that the first section is a fixed-positioned element, and thus it’s removed from the normal document flow.
The second section’s position without adding a padding-top valueThe second section’s position without adding a padding-top valueThe second section’s position without adding a padding-top value

Here are the main styles:

1
/*CUSTOM VARIABLES HERE*/
2

3
.first {
4
  position: fixed;
5
  top: 0;
6
  left: 0;
7
  width: 100%;
8
  height: var(--hero-height);
9
  background: url(mountain-full.jpg) no-repeat center / cover;
10
  background-blend-mode: multiply;
11
  display: grid;
12
  place-items: center;
13
  z-index: 1;
14
}
15

16
section,
17
.first > * {
18
  transition: all 0.6s;
19
}
20

21
.first > * {
22
  grid-area: 1/1;
23
  padding: 0 20px;
24
  width: 100%;
25
}
26

27
.first .page-header {
28
  opacity: 0;
29
  visibility: hidden;
30
}
31

32
.first .nav {
33
  display: flex;
34
  flex-wrap: wrap;
35
  align-items: center;
36
  justify-content: space-between;
37
}
38

39
.first .nav ul {
40
  display: flex;
41
  list-style: none;
42
}
43

44
.second {
45
  padding: calc(var(--hero-height) + 10vh) 0 10vh 0;
46
}
47

48
@media (max-width: 600px) {
49
  .first .nav {
50
    flex-direction: column;
51
    justify-content: center;
52
  }
53
}

3. Animate on Scroll (JavaScript)

As we start scrolling down the page, we‘ll toggle the is-sticky class of the body element.

At that point, the following actions will take place:

  • We’ll smoothly decrease the height of the first section from 100vh to 90px. Again, you can alter the value of the sticky header height through the sticky-header-height CSS variable. In addition, we’ll assign it a background color that will blend with its image and result in a purple (darker) image. Notice in the CSS above that this section has background-blend-mode: multiply.
  • We’ll smoothly reveal the page header and hide the heading.
  • We’ll smoothly decrease the padding-top value of the second section from 110vh to 90px + 10vh. 
  • We’ll sync the animations of all elements. Notice in the CSS above that their animation duration will be 0.6s.
  • We’ll define the ::before pseudo-element of the body element that will append a box shadow to the page header.
The box shadow of the page headerThe box shadow of the page headerThe box shadow of the page header

Here’s the required JavaScript code:

1
const body = document.body;
2
const toggleClass = "is-sticky";
3

4
window.addEventListener("scroll", () => {
5
  const currentScroll = window.pageYOffset;
6
  if (currentScroll > 0) {
7
    body.classList.add(toggleClass);
8
  } else {
9
    body.classList.remove(toggleClass);
10
  }
11
});

And the associated styles:

1
/*CUSTOM VARIABLES HERE*/
2

3
.is-sticky::before {
4
  content: "";
5
  position: fixed;
6
  top: 65px;
7
  left: 0;
8
  width: 100%;
9
  height: 15px;
10
  box-shadow: 0 10px 15px rgba(0, 0, 0, 0.7);
11
}
12

13
.is-sticky .first {
14
  height: var(--sticky-header-height);
15
  background-color: var(--purple);
16
}
17

18
.is-sticky .first h1 {
19
  opacity: 0;
20
  visibility: hidden;
21
}
22

23
.is-sticky .first .page-header {
24
  opacity: 1;
25
  visibility: visible;
26
}
27

28
.is-sticky .second {
29
  padding-top: calc(var(--sticky-header-height) + 10vh);
30
}

Conclusion

Another scrolling tutorial came to an end, folks! During this exercise, we covered how to transform a full-screen section to a sticky header on a page scroll by toggling just one class. Hopefully, this implementation was clear enough and inspired you to utilize it on an upcoming project! Of course, you can build on it and add some extra features like adding parallax functionality on scroll by changing perhaps the first section’s background position.

Let’s look again at our creation:

Last but not least, don’t forget to look at the Tuts+ library for more header effects tutorials on scroll.

As always, thanks a lot for reading!

Web Design Myrtle Beach

Coastal Media Brand