Issue
I'm trying to achieve two styling at the same time, one includes a sticky position, and the other includes a parent to the sticky element :
- I want the first part of my page, let's call it the "hero section", to take the whole screen height (this section have a
bottom
element that should be at the bottom of the screen when the page is scrolled to the top, and the rest of the content should follow after) - and I also want the navbar to stick to the top of the website, but this navbar is not on top of the website at the beginning (when the page is scrolled to the top), it is in second position, right after the title
additionally, I try to find a solution that does not uses javascript, css only.
here is a code snippet to make it clear, with two columns, one for both aspects of the problem :
body {
margin: 0px 10px;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
font-size: 10px;
}
.hero_bottom {
height: 50px;
background-color: lightblue;
margin: 10px 0px;
}
main {
height: 200vh;
background-image: linear-gradient(red, yellow);
}
section.left header {
display: grid;
grid-template-rows: 1fr 1fr auto;
gap: 10px;
height: 100vh;
border: 1px solid blue;
}
nav {
position: sticky;
top: 0px;
}
<section class="left">
<!-- HERO SECTION -->
<header>
<h1>
either I have the "bottom" element at the bottom of the screen view...
</h1>
<nav>
<a href="#">link</a>
<a href="#">link</a>
<a href="#">link</a>
</nav>
<div class="hero_bottom">hero-bottom</div>
</header>
<!-- end HERO SECTION -->
<main>main content</main>
</section>
<section class="right">
<!-- HERO SECTION -->
<h1>
...or I have the navbar that stick through the entire website. But how to have both ?
</h1>
<nav>
<a href="#">link</a>
<a href="#">link</a>
<a href="#">link</a>
</nav>
<div class="hero_bottom">hero-bottom</div>
<!-- end HERO SECTION -->
<main>main content</main>
</section>
It's easy to make the navbar sticks through the entire website if it's a direct child of the body (or any element that have the height of the website, like the <section>
in my example), and it's easy to have the hero-bottom
element placed at the bottom of the hero section if everything that appears at the top of the page is inside a block-level wrapper, including the navbar.
But one prevents the other : the bottom element needs the block-level wrapper, and the wrapper prevents the navbar to stick through the entire website. That's my issue !
I don't feel like there is a solution to make the navbar sticky to it's grandparent (in this situation, because I know it's sometimes possible, if you can make the parent inline-level for example), so maybe it's better to find a solution to have the bottom
element being at the bottom of the hero section without a wrapper ?
Solution
I've found a solution, so I'll answer my own question, but it is a hacky trick, not a clean solution :/
It's a solution to the second aspect, how to place the "hero-bottom", and the rest of the page, at the bottom of the hero section, not a solution to use sticky outside the direct block-level parent
The trick is to use an invisible float element on the hero section, give it a 100vh height, and clear the main content of the page so that it follows the float element. Then, I move the "hero-bottom" part inside the main-content, and make it position absolute at the top
an example will explain it better :
body {
margin: 0px 10px;
font-size: 10px;
}
body > h1, body > nav {
border: 1px solid blue;
}
.float {
float: left;
border: 2px solid green;
height: 100vh;
}
nav {
position: sticky;
top: 0px;
z-index: 1;
}
main {
position: relative;
height: 400vh;
background-image: linear-gradient(red, yellow);
clear: both;
}
main .hero_bottom {
height: 50px;
background-color: lightblue;
margin: 10px 0px;
position: absolute;
bottom: 100%;
left: 0px;
width: 100%;
}
<div class="float"></div>
<h1>
title
</h1>
<nav>
<a href="#">link</a>
<a href="#">link</a>
<a href="#">link</a>
</nav>
<main>
<div class="hero_bottom">hero-bottom</div>
main-content
</main>
However, since the hero section cannot be inside any kind of block-level element (including flexbox and grid), it's not easy to customize the position of the title and the nav bar
It's possible to use the "clearfix" trick to achieve a little bit of customization :
body {
margin: 0px 10px;
font-size: 10px;
}
header, nav {
border: 1px solid blue;
}
body * {
margin: 0px;
padding: 0px;
}
.float {
float: left;
border: 2px solid green;
}
.float_header {
height: 60vh;
}
.float_nav {
height: 40vh;
}
.clearfix::after {
content: "";
clear: both;
display: block;
}
.clear {
clear: both;
width: 0px;
height: 0px;
}
header {
display: block;
position: relative;
}
h1 {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: 1px solid orange;
}
nav {
position: sticky;
top: 0px;
z-index: 1;
text-align: center;
}
main {
position: relative;
height: 400vh;
background-image: linear-gradient(red, yellow);
clear: both;
}
main .hero_bottom {
height: 50px;
background-color: lightblue;
margin: 10px 0px;
position: absolute;
bottom: 100%;
left: 0px;
width: 100%;
}
<div class="float float_header"></div>
<header class="clearfix">
<h1>
title
</h1>
</header>
<div class="clear"></div>
<div class="float float_nav"></div>
<nav>
<a href="#">link</a>
<a href="#">link</a>
<a href="#">link</a>
</nav>
<main>
<div class="hero_bottom">hero-bottom</div>
main-content
</main>
Now, I'm not sure I would use that in production
Answered By - hugogogo
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.