1

I'm trying to build my personal website where I have:

  1. A canvas element that's 100% screen height and width, with z-index -1
  2. The normal content in divs and section tags, with z-index 0
  3. The nav element that's at the highest z-index on the page

This arrangement allows me to have the canvas as the background of the entire website, it doesn't scroll because it's fixed. The nav is fixed as well so it stays at the top of the page with scrolling. (By "fixed" I mean "position: fixed" set in CSS on that element)

The nav has a transparent background, so it's "see-through", which shows the canvas content behind it, like this: navbar and canvas background (sorry I don't enough points to embed images yet)

However, because the nav is transparent and fixed, content gets shown behind it on scroll, something like this image: content goes behind nav

I would like to have the content fade as it goes behind the nav's bottom edge, but I would also like to keep the nav transparent in order to show the canvas in the background. Here's what the fade would ideally look like: text fade example (taken from https://www.youtube.com/watch?v=-vbLeY-eDkQ but it uses text clip which doesn't apply to my case)

EDIT: Hiding the content without a fade is fine as well, the target is to make the content not appear beneath the transparent nav whilst showing the background canvas. It can be an abrupt cut-off instead of a gradient fade because after some more research I've found the fade effect I'm looking for isn't widely available or supported on all elements across browsers.

I have tried checking solutions from here: Hide scrollable content behind transparent fixed position divs when scrolling the page? but they use a background image, which makes it relatively simpler. In my case, it's a canvas and the content of the canvas changes with time.

Here's my current webpage structure (Note: the CSS classes are from TailwindCSS but the naming is self-explanatory. I'm also using React)

<body class="bg-dark m-0">
  <nav id="nav_section" class="
      fixed
      block
      overflow-hidden
      font-body
      z-20
      xl:right-0 xl:mr-16 xl:inline-block xl:bottom-auto
      w-full">
  </nav>

  <div id="vector_container" class="fixed left-0 z-0 h-full">
    <canvas id="vector_canvas" class="w-full h-full stroke-2"></canvas>
  </div>

  <section id="first_screen_block" class="h-screen relative overflow-hidden">
    <div id="corner_block" class="absolute bottom-0">
      <div id="big_name_container"></div>
      <div id="click_button_container" class="xl:m-16 xl:ml-12"></div>
    </div>
  </section>

  <section id="second_screen_block" class="h-screen relative xl:mt-64">
    <div id="scroll_work_container" class="h-threequarters">
    </div>
    <div id="work_showcase_text"
      class="absolute bottom-0 xl:font-semibold font-display xl:ml-12 xl:text-8xl text-secondary">
      <span class="text-primary">Work</span>
      showcase.
    </div>
  </section>
</body>

Is there a way to achieve this with CSS and/or JS?

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
tanish2k09
  • 15
  • 8
  • I should add - I've tried checking out setting a canvas as the CSS background directly which would then allow me to use `background: inherit` in `nav` but I'm not sure if that's a good practice or even well supported in browsers. – tanish2k09 Jul 25 '20 at 01:14
  • 1
    I've devised a solution that should be suitable for you. Now you will be able to fade divs and picture. Sorry it took so long, had a lot on my plate. – Maxwell Archer Aug 01 '20 at 12:15
  • I did not know iframes could do that, it’s a clever solution. Looks like you’re using masks, which according to caniuse has 96% global users and no IE support. Not a huge deal for a personal portfolio I guess, you gain some you lose some. Thanks a lot for all the input, the question is now solved. – tanish2k09 Aug 01 '20 at 19:01
  • This was an interesting problem to delve into. I may spend more time and look for a JavaScript solution that would work with most browsers. At a loss of some performance. – Maxwell Archer Aug 01 '20 at 19:25

2 Answers2

2

Fading Content using Iframes (No JavaScript)

You will need to create an Iframe tag with src attribute set to the content file you would like fade. The main content has to have separate styles. The iframe must be in focus to allow scrolling. More details in the code below.

Demo: https://fadingiframe.netlify.app/

/* Index.html style style-sheet below */

iframe {
  position: absolute;
  top: 5rem;
  width: 100vw;
  height: calc(100vh - 6rem);
  border: none;
  -webkit-mask-image: linear-gradient( /* Mask iframe */
    transparent 1rem,
    #fff 5%,
    #fff 70%,
    transparent 90%
  );
  mask-image: linear-gradient(
    transparent 1rem,
    #fff 5%,
    #fff 70%,
    transparent 90%
  );
}

/* mainContent.html style style-sheet below */

body {
  position: absolute;
  overflow-x: hidden;
  margin-top: 2rem;
  color: aliceblue;
  width: 80vw;
  left: 5vw;
}

body::-webkit-scrollbar { /* Remove scroll bar */
  display: none;
}

body {
  -ms-overflow-style: none; /* keep in mind that it will only scroll if the iframe is in focus */
  scrollbar-width: none;
}

p {
  padding: 2rem;
  font-size: 2rem;
}
  <body>
    <nav></nav>
    <iframe id="main-content-iframe" src="mainContent.html"></iframe> 
    <!-- Add iframe and src to main content html file -->
    <canvas id="canvas1"></canvas>
    <footer></footer>
  </body>
  
  
  
  
  <!-- Separate html file in root directory -->
    
  <!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="./mainContent.css" /> <!-- Link to css file -->
  </head>
  <body>
    <section>
     <!-- Your Content here-->
    </section>
  </body>
</html>

-------------------------------------------------------------------------

For Text only -

Body Tag Has Special/Hide Properties

I think your issue is that you do not use the "body" element selector. It has special properties, that by default set the body element height to match the screen. Although it still allows to scroll the inner content. I add and extra background div for the text as well. It provides a better reading experience. Have a look at my solution it may help you solve your problem. If you have any questions don't hesitate to ask.

Demo : https://jsfiddle.net/hexzero/5yjqk43a/

body {
  background-image: black;
  background-position: center center;
  -webkit-background-size: cover;
  background-size: cover;
  background-attachment: fixed;
  color: #fff;
}

section {
  position: absolute;
  padding: 3rem 25%;
  background-image: Linear-gradient(
    transparent 6rem, <-- Should be the same as nav Height
    #fff 30%,         <-- Can set this to nav Height for abrupt cut-off
    #fff 70%,
    transparent 90%
  );
  -webkit-background-clip: text;
  background-clip: text;
  background-attachment: fixed;
  scroll-behavior: auto;
  z-index: 3;
}

nav {
  background: rgba(0, 0, 0, 0.616);
  width: 100%;
  position: fixed;
  top: 0;
  height: 6rem; <-- Navigation Height
  z-index: 4;
}

section > p {
  margin-top: 12rem;
  color: transparent;
}

.text-background {  <-- Remove this style section to have no background for the content,  
  width: 60%;       <-- along side the  <div class="text-background"></div> element 
  height: 100vh;
  right: 20%;
  position: fixed;
  top: 0;
  background-image: Linear-gradient(
    transparent 6rem,   <-- Background to nav height
    rgba(102, 51, 153, 0.924) 20%,
    rgba(102, 51, 153, 0.931) 90%,
    transparent 100%
  );
  z-index: 0;
}

canvas {
  width: 100%;
  background-color: rebeccapurple;
  position: fixed;
  top: 0;
  z-index: -1;
}

footer {
  position: fixed;
  width: 100%;
  height: 1rem;
  background: rebeccapurple;
  z-index: 1;
  bottom: 0;
}

p {
  font-size: 2rem;
}

Tell me if you would be interested in a JavaScript version, for better browsers support. Thanks

Maxwell Archer
  • 422
  • 6
  • 15
  • Your answer does help with the fade part and you seem to have the structure correct. I believe I can use something similar in my webpage. Is there any way you could perhaps block out the text content from appearing below the nav completely? Currently it goes behind the nav before the gradient fade, ideally the fade would be just below the nav's bottom. – tanish2k09 Jul 26 '20 at 03:46
  • I edited the original post, the content doesn't necessarily need to fade, and as long as it isn't visible behind the nav after scrolling, a solid chop is fine as well. – tanish2k09 Jul 26 '20 at 03:53
  • All you have to do is just set the selection background-image: Linear-gradient( transparent 6rem, #fff 30%, #fff 70%, transparent 90% ); – Maxwell Archer Jul 26 '20 at 07:39
  • I've edited the original code above so that you could easily find the values you need to change. – Maxwell Archer Jul 26 '20 at 08:09
  • I would say your answer checks most of the boxes that I require, except maybe one. The background of the content has a purple translucent shade, which makes the white canvas particles in the canvas region below it to also appear slightly purple-tinted. If that could somehow be made transparent so that the canvas content appears underneath unaffected, I’d mark this answer as the solution :) – tanish2k09 Jul 26 '20 at 09:02
  • I've just added it for readability sake the background can be removed entirely. – Maxwell Archer Jul 26 '20 at 09:14
  • I've accepted the answer, but this solution only works for text because of the background clipping on text. Is there a way to do that for all elements that aren't just text, like images? – tanish2k09 Jul 26 '20 at 21:30
  • 1
    Well you don't need to clip other element. It is only for the text because it is a work around for the gradient to be applied to the text. I will try to write up a solution for images as well tomorrow. – Maxwell Archer Jul 26 '20 at 21:37
  • More specifically, I'm interested in hiding divs, like the title says. I have found no CSS resource that can do that so I'm guessing the solution would involve JS – tanish2k09 Jul 27 '20 at 01:13
  • 1
    Sorry it had taken me a while to add fade functionality for divs, had a lot of work this week. I shall try to work it out over the weekend. – Maxwell Archer Jul 30 '20 at 05:19
0

By making the color of the nav transparent, you will be able to see through it to the canvas below. Since you did not provide your CSS for your classes; I threw together some new HTML instead. You can see the transparency effect below.

var c = document.getElementById("myCanvas");
        var ctx = c.getContext("2d");
        ctx.fillText("Hello World! This is text on a canvas that is behind the nav", 10, 10);
.nav-wrapper {
            height: 60px;
            top: 0;
            right: 0;
            left: 0;
            position: fixed;
            z-index: 5;
            background-color: #00000044;
        }

        #myCanvas {
            z-index:4;
            height: 100%;
            width: 100%;
        }
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body style="margin:0">
    <div class="nav-wrapper">
        <nav>
            a simple nav
        </nav>
    </div>
    <div style="position:fixed;top:0;left:0;bottom:0;right:0; background-color: lightblue;z-index: 4 ;">
        <canvas id="myCanvas">
            
        </canvas>
    </div>
</body>

</html>
Daniel
  • 1,392
  • 1
  • 5
  • 16
  • Your answer tells me how to show the canvas behind a transparent nav, but it says nothing about hiding other content divs under the nav upon scroll, which is the originally asked question. I left out the CSS intentionally because I mentioned I'm using TailwindCSS, and those classes are documented here: https://tailwindcss.com/docs/installation/ – tanish2k09 Jul 25 '20 at 04:03
  • I am looking for something like this: https://www.youtube.com/watch?v=cpwkAJrb6_Q except that instead of a static background image I need to display the canvas – tanish2k09 Jul 25 '20 at 04:04