Reputation: 2145
I was looking at how GraphQL designed their header on their website and saw that it changes after scrolling it past the hero
section without using JavaScript. It is more of an overlapping effect vs just a sticky scrollbar.
I've looked through the source code and stylesheet to see how they accomplished this effect and don't see anything that stands out to me, such as position: sticky;
.
I also tried to play around with the z-index
of both headers but still can't figure out how they layered it to overlap like this.
The things that do stand out that they used are: clip
, z-index
, and position: fixed;
.
Here is an attempt I made to recreate this effect:
/* Basic styles just for visual */
body {
margin: 0;
color: #aaa;
}
section {
min-height: 1250px;
padding: 100px;
}
.header-content {
display: flex;
justify-content: center;
}
/* Attempt at overlapping headers */
header {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
top: 0;
left: 0;
right: 0;
height: 50px;
background: white;
box-shadow: inset 0 -1px 0 0px rgba(0, 0, 0, 0.1);
z-index: 10;
}
.hero {
position: fixed;
background: #171e26;
position: relative;
min-height: 450px;
max-height: 900px;
height: 65vh;
margin-top: -50px;
padding-top: 50px;
z-index: 11;
}
.hero .abs {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
clip: rect(0, auto, auto, 0);
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.hero .header {
background: linear-gradient(rgba(23, 30, 38, 0.8), rgba(23, 30, 38, 0));
box-shadow: none;
display: block;
}
<header>
<div class="header-content">
First Header
</div>
</header>
<div class="hero">
<div class="abs">
<header>
<div class="header-content">
Header in hero
</div>
</header>
</div>
</div>
<section>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Similique, ipsum. Est exercitationem eum voluptates neque suscipit natus repudiandae perferendis minima ipsum eveniet possimus esse nam excepturi maxime, odit, debitis numquam.
</section>
This is somewhat close, but you can tell the top header is just staying white vs being transparent.
Really, I don't need a full example back as an answer, although it is welcome. I really just want to understand how they did this.
How are they able to accomplish this using only CSS?
Upvotes: 0
Views: 219
Reputation: 2850
A basic example of how this can be achieved using two navbars with absolute
and fixed
positions. This, however, does not work with the hero section as GraphQL website has as both navbars are positioned at the top of the page.
.show-when-scrolling {
background-color: #333;
position: fixed; /* Remain in position when scrolling */
z-index: 1; /* Hide navbar under main navbar */
}
.main-nav {
background-color: #666;
position: absolute; /* Show on top of other content */
z-index: 2; /* Show main navbar on top of second navbar */
}
body {
margin: 0; /* Remove browser default margin to fill whole screen */
height: 200vh; /* Makes page scrollable */
}
/* Random styling */
.nav {
width: 100%;
height: 48px;
}
.nav a {
float: left;
color: #fff;
text-align: center;
padding: 15px;
cursor: pointer;
}
.nav a:hover {
background-color: #bbb;
color: black;
}
<div class="nav main-nav">
<a>My</a>
<a>main</a>
<a>navbar</a>
</div>
<div class="nav show-when-scrolling">
<a>Visible</a>
<a>when</a>
<a>scrolling</a>
</div>
Another solution, for when you want to implement a hero section as in your example, can be done using sticky
position.
.show-when-scrolling {
background-color: #333;
position: fixed; /* Remain in position when scrolling */
z-index: -1;
}
.main-nav {
position: sticky; /* Remains inside wrapper, so it will be hidden when scrolled enough */
top: 0; /* Stick to the top */
}
body {
margin: 0; /* Remove browser default margin to fill whole screen */
height: 200vh; /* Makes page scrollable */
}
/* Random styling */
.nav {
width: 100%;
height: 48px;
}
.nav a {
float: left;
color: #f00;
text-align: center;
padding: 15px;
cursor: pointer;
}
.nav a:hover {
background-color: #bbb;
color: black;
}
.top-section {
height: 200px;
background-size: cover;
background-image: url(https://images.unsplash.com/photo-1562347810-18a0d370ba36?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1500&q=80)
}
<div class="nav show-when-scrolling">
<a>Visible</a>
<a>when</a>
<a>scrolling</a>
</div>
<div class="top-section">
<div class="nav main-nav">
<a>My</a>
<a>main</a>
<a>navbar</a>
</div>
</div>
Upvotes: 1