0

I'm implementing a scrollable area with "gradient" edges like this:

.container {
  height: 5em;
  overflow: auto;
  position: relative;
}

.container::before,
.container::after {
  content: "";
  display: block;
  position: sticky;
  left: 0;
  right: .5em; /* for custom scrollbar, nevermind */
  height: .6em;
}
.container::before {
  top: 0;
  background: linear-gradient(
    to bottom,
    white,
    transparent 100%
  );
}
.container::after {
  bottom: 0;
  background: linear-gradient(
    to bottom,
    transparent,
    white 100%
  );
}
<div class="container">
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
</div>

So far so good. What I don't like is the white color repeated twice (well, present at all): for instance, for dark theme I'll need to redefine this color. Sure, I can use variables, but I wonder: can I inherit the color from background somehow? May be with a shadow instead of background (but it sounds even more unlikely).

As you can see, just using inherit doesn't work:

.container {
  height: 5em;
  overflow: auto;
  position: relative;
}

.container::before,
.container::after {
  content: "";
  display: block;
  position: sticky;
  left: 0;
  right: .5em;
  height: .6em;
}
.container::before {
  top: 0;
  background: linear-gradient(
    to bottom,
    white,
    transparent 100%
  );
}
.container::after {
  bottom: 0;
  background: linear-gradient(
    to bottom,
    transparent,
    unherit 100%
  );
}
<div class="container">
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
</div>

Can I achieve this effect? How?

PS Using mask like this affects the scrollbar, so it's not an acceptable solution (and hence this is not a duplicate question):

.container {
  height: 5em;
  overflow: auto;

  -webkit-mask-image: linear-gradient(to bottom,
    transparent .5em,
    red 1em calc(100% - 1em),
    transparent calc(100% - .5em));
  mask-image: linear-gradient(to bottom,
    transparent .5em,
    red 1em calc(100% - 1em),
    transparent calc(100% - .5em));
}
<div class="container">
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
</div>

Notes about masking:

  • the main "color" can be arbitrary – I used red for short;
  • with just linear-gradient(to bottom, transparent, .5em, red, calc(100% - .5em), transparent) "fading" was to blurred, to make it more abrupt, I've read specs more carefully, done some experiments, and found that shifting the edge of the transparent part of the mask solves the issue.
YakovL
  • 7,557
  • 12
  • 62
  • 102
  • 1
    A `currentBackgroundColor` variable similar to `currentColor` has been requested and is being discussed [here](https://github.com/w3c/csswg-drafts/issues/5292). For now, as you suggested yourself, using CSS Custom Properties is probably the only way to resolve this if you are looking for a pure CSS solution. – agrm Jun 05 '23 at 08:26

1 Answers1

0

As the solution mentioned in the PS of the question affects the scrollbar, and it seems that :before and :after don't support background inheriting, I've come up with another one. Now I'm using a variable for background (so that I can change it for dark mode) and reusing that variable for the gradient (yeah, variables are out there for DRY!):

:root {
  --bg-color: white;
  background: var(--bg-color);
}
.container {
  height: 5em;
  overflow: auto;

  position: relative;
}

.container::before,
.container::after {
  content: "";
  display: block;
  position: sticky;
  left: 0;
  right: .5em;
  height: 1em;
}
.container::before {
  top: 0;
  background: var(--bg-color);
  -webkit-mask-image: linear-gradient(
    to top,
    transparent .5em,
    red 1em
  );
  mask-image: linear-gradient(
    to top,
    transparent .5em,
    red 1em
  );
}
.container::after {
  bottom: 0;
  background: var(--bg-color);
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent .5em,
    red 1em
  );
  mask-image: linear-gradient(
    to bottom,
    transparent .5em,
    red 1em
  );
}
<div class="container">
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
  <div class="content">content is here</div>
</div>

Sure, I'd prefer something like the mentioned currentBackgroundColor, but it seems that there's no simpler solution than above for now.

YakovL
  • 7,557
  • 12
  • 62
  • 102
  • *Ok, if you know what to look for, you can find that this was already discussed.* --> we call this a duplicate, if you find a solution somewhere else considering up-voting it instead of adding another Q/A – Temani Afif May 30 '23 at 21:43
  • @TemaniAfif it is a _partial_ duplicate alright, but it took me quite a while before I found it, so I think posting the question as I had it initially is in fact helpful. Also, as you can see, the issue is not fully resolved because of the scroolbar fading, so _closing_ this question is not helpful – YakovL Jun 01 '23 at 12:48