13

I want to add a faded section to the top of my DIV such that, when a user scrolls, the content gradually fades out. I have set up some CSS that achieves this but has one issue.. The faded section scrolls with the content rather than staying fixed in place.

How can I fix this? Do I need help from jQuery or is it possible using CSS and will this work in anything bar CSS3 compatible browsers? (I know I dont have correct vendor prefixes on my linear-gradients yet)

Here is my code so far and a fiddle:

.fadedScroller {
  overflow: auto;
  position: relative;
  height: 100px;
}

.fadedScroller:after {
  content: '';
  top: 0;
  left: 0;
  height: 20px;
  right: 0;
  background: linear-gradient(to bottom, rgba(251,251,251,1) 0%,rgba(251,251,251,0) 100%);
  position: absolute;
}

Update

I have updated my fiddle to point out that using position: fixed doesnt actually work as the faded section then appears above the containing div not fixed to the top.

Nickofthyme
  • 3,032
  • 23
  • 40
Chris
  • 26,744
  • 48
  • 193
  • 345

4 Answers4

12

Creating a second div to hold the gradient and shifting it over the the content div works. I know this is kind of dirty and not very intuitive to write, but it works.

Demo:

.fadedScroller {
  overflow: auto;
  position: relative;
  height: 100px;
}

.fadedScroller_fade {
  content: '';
  margin-top: -100px;
  height: 40px;
  background: linear-gradient(to bottom, rgba(251, 251, 251, 1) 0%, rgba(251, 251, 251, 0) 100%);
  position: relative;
}
<div class="fadedScroller">
    awesome stuff here<br />
    awesome stuff here<br />
    awesome stuff here<br />
    awesome stuff here<br />
    awesome stuff here<br />
    awesome stuff here<br />
    awesome stuff here<br />
    awesome stuff here<br />
    awesome stuff here<br />
</div>
<div class="fadedScroller_fade"></div>

See https://jsfiddle.net/hP3wu/12/

Nickofthyme
  • 3,032
  • 23
  • 40
Cobra_Fast
  • 15,671
  • 8
  • 57
  • 102
  • 4
    +1 This is basically the same conclusion I came to: http://fiddle.jshell.net/hP3wu/15/ - One drawback is that you can't click on the top part of the scrollbar (including arrow up) because the overlay is in the way =/ – xec Jun 11 '13 at 13:02
  • 1
    Another hackish workaround could be http://fiddle.jshell.net/hP3wu/18/ - make space for the scrollbar, and use overflow: scroll so it always appears. Still bad, because width of scrollbar is unknown... – xec Jun 11 '13 at 13:07
  • I wrote a solution using JQuery, but this is probably the best solution without scripts. – pandavenger Jun 11 '13 at 13:09
  • actually you can use :before to get this done cleaner :) – Dzung Nguyen Aug 10 '14 at 06:04
  • 1
    Add `pointer-events: none; ` to .fadedScroller_fade and you can click/scroll the contents while over the faded area. – Jason Clemens Jul 24 '17 at 21:22
2

Pretty simple, use position:fixed instead of position:absolute:

.fadedScroller:after {
    content:'';
    position: fixed;
    top: 0;
    left: 0;
    height: 20px;
    right: 0;
    background: linear-gradient(to bottom, rgba(251, 251, 251, 1) 0%, rgba(251, 251, 251, 0) 100%);
}

https://jsfiddle.net/hP3wu/4/

Update1

https://jsfiddle.net/hP3wu/7/

Update2

https://jsfiddle.net/hP3wu/9/

yckart
  • 32,460
  • 9
  • 122
  • 129
  • Fading effect is extremely weakened (almost unnoticeable) for me in the fiddle. (FF21/Linux3.8.12) – Cobra_Fast Jun 11 '13 at 12:43
  • @Cobra_Fast That is because `position:absolute` is contained in `position:relative` so it is not at `top:0` of your window. So, adjust the height to e.g. `40px` :) – yckart Jun 11 '13 at 12:45
  • 2
    After giving it `position: fixed;` the position is no longer relative to `.fadedScroller` - http://fiddle.jshell.net/hP3wu/6/ – xec Jun 11 '13 at 12:46
  • Still doesn't fully fade out. I'd expect it to fade to be completely invisible (since the top of the gradient has an alpha of `1`). – Cobra_Fast Jun 11 '13 at 12:46
  • 1
    That works so long as `.fadedScroller` is at the top of the window, it is not. As it happens its positioned in the middle of the page so this doesnt work – Chris Jun 11 '13 at 12:49
  • @Cobra_Fast `body` has a padding by default, so reset padding to 0, or set your ``top` to the default `padding`-value. http://fiddle.jshell.net/hP3wu/9/ – yckart Jun 11 '13 at 12:49
  • If `.fadedScroller:after` is relative to origin instead of any parent element, it's gonna be a pain to use for anything else than fading out the entire page... – Cobra_Fast Jun 11 '13 at 12:52
  • @Cobra_Fast `position:fixed` cannot be relative to anything, except the browser-window! – yckart Jun 11 '13 at 12:53
  • Which is what I meant by "origin". – Cobra_Fast Jun 11 '13 at 13:05
1

This is a huge workaround solution, so apologies, but this is the only way I could think of: http://fiddle.jshell.net/hP3wu/17/

So first I made another div with class="after" because I cannot select the :after pseudo-element with JQuery

Then I made the div.after reposition itself each time a scroll occurs in the .fadedScrollbar div with

$(".fadedScroller").scroll(function () {
    $(".fadedScroller .after").css("top", $(this).scrollTop());
});
pandavenger
  • 1,017
  • 7
  • 20
  • +1 This is likely the best working solution, except for mobile devices because they don't fire the scroll event until the scrolling has stopped. – xec Jun 11 '13 at 13:15
  • @xec thanks, I edited it, and feel free to add anything you feel should be there. – pandavenger Jun 11 '13 at 13:20
0

http://fiddle.jshell.net/ne1baj4e/1/ This is a my modification of yckart's solution, which reduces the fade when the div is scrolled to the top. It simply adds this bit of Javascript/JQuery:

const FADE_HEIGHT = 40;
let oldStyle = $(`<style>.fadedScroller:after {top: -${FADE_HEIGHT}px;}</style>`).appendTo("head");

$(".fadedScroller").scroll(() => {
  let offset = Math.min($(".fadedScroller").scrollTop() - FADE_HEIGHT, 0);

  oldStyle.remove();

  oldStyle = $(`<style>.fadedScroller:after {top: ${offset}px;}</style>`).appendTo("head");
});

Fading at the bottom of a div is similar except you'll need to calculate the offset as

$(".fadedScroller")[0].scrollHeight - $(".fadedScroller")[0].clientHeight - $(".fadedScroller")[0].scrollTop
Tvsj
  • 1
  • 1