Reputation: 39728
I want to have a div with an inset box-shadow that has scrolled content in it. Unfortunately, the box-shadow doesn't get casted on the elements within the content, but rather on the background, but I want it to cover the content elements as well.
I stumbled upon this solution: http://jsfiddle.net/HPkd3/ (via). The problem is, I can't get it to work with my scrolled setup; if I position the mask inside the scrolling div, the shadow scrolls away - and if I position it outside of the div, the scrollbar has the shadow cast upon it, which looks weird.
Any ideas how to get this right?
Edit: Some example code: http://jsfiddle.net/ZSpSS/2/
I want the red squares in this example covered with the shadow, while the shadow should be persistent when I scroll through the content.
Upvotes: 17
Views: 35114
Reputation: 130351
animation-timeline
allows to infer a scrollable element and style it accordingly:
ul {
--shadow-size: 20px;
--shadow-color: #00000055;
font: 22px Arial;
border: 1px solid black;
height: 100px;
padding: 1em 2em;
overflow: auto;
resize: vertical;
}
.scrollShadow {
--shadow-size: 30px;
background-image: linear-gradient(
var(--shadow-color) 0%,
transparent calc((var(--scroll)) * var(--shadow-size)),
/* The below "transparent" color-stop starts at the bottom with an offset
* of the size of the shadow which is multiplied by a bumber from 0 to 1,
* which decreases the more is scrolled down, meanning the bottom's
* shadow size decreases the more is scrolled down.
*/
transparent calc(100% - var(--shadow-size) * (1 - var(--scroll))),
var(--shadow-color) 100%
);
background-position-y: var(--shadow-offset);
background-size: 100% calc(100% - var(--shadow-offset));
animation: scroll-shadows cubic-bezier(.25,.85,.8,.22);;
animation-timeline: scroll(self);
animation-range: 0 100%;
}
/* Aniatable custom property */
@property --scroll {
syntax: '<number>';
inherits: true;
initial-value: 0;
}
@keyframes scroll-shadows {
/* Sets the shadow-color only if the element is scrollable */
from, to { --shadow-color: #0003; }
to {
--scroll: 1;
}
}
<ul contentEditable class="scrollShadow">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
<li>13</li>
<li>14</li>
<li>15</li>
<li>16</li>
<li>17</li>
<li>18</li>
<li>19</li>
<li>20</li>
</ul>
📖 Learn everything about scroll-driven animations
👉 See support table (spoilers - no Firefox)
While this answer might not be helpful to most now, it will certainly become more and more relevant as time passes and support grows.
Upvotes: 3
Reputation: 909
Have you tried something like this:
CSS:
#test{
width:500px;
height:200px;
overflow:auto;
-moz-box-shadow: inset 1px 1px 20px 4px black;
-webkit-box-shadow: inset 1px 1px 20px 4px black;
box-shadow: inset 1px 1px 20px 4px black;
}
HTML:
<div id="test"><p>
sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd sadasd
<br /></p></div>
If you can give more details I can help with a more specific answer
Upvotes: -1
Reputation: 189
try this
box-shadow:1px 1px 1px 1px #000000 inset;
pointer-events: none;
Upvotes: 1
Reputation: 485
I totally have this working! Check out:
http://jsfiddle.net/yobert/6Ff4u/
Note the red background blocks correctly are "under" the shadows.
Caveats: Requires you to guess the size of the scrollbar in pixels. I bet there is a safe way to measure this with javascript though. If you only have a vertical scrollbar, this ends up being much simpler since you don't need to adjust the margin-bottom.
Upvotes: 8
Reputation: 1918
Here is one possible solution.
I commented my CSS styles and you should easily understand my html markup. Here is what I did.
.outer
.inner-content
overflow:scroll
to the .inner-content
div to apply your scroll bar. ( you can also change overflow:scroll
to overflow:auto
which will also give you a scroll barUpvotes: 0