这个滚动阴影CSS魔术是如何工作的?



我在2012年发现了这篇臭名昭著的文章。它详细介绍了如何创建滚动阴影并且仍然工作得很好,但我真的很想了解解决方案,但我似乎无法在网上找到必要的信息。

以下是最初由@kizmarh创建并由@leaverou改进的缩小代码(博客文章(:

.scrollbox {
overflow: auto;
width: 200px;
max-height: 150px;
background: 
/* Shadow covers */
linear-gradient(white 30%, rgba(255, 255, 255, 0)), 
linear-gradient(rgba(255, 255, 255, 0), white 70%) 0 100%,
/* Shadows */
radial-gradient(farthest-side at 50% 0, rgba(0, 0, 0, .2), rgba(0, 0, 0, 0)), 
radial-gradient(farthest-side at 50% 100%, rgba(0, 0, 0, .2), rgba(0, 0, 0, 0)) 0 100%;
background-repeat: no-repeat;
background-color: white;
background-size: 100% 40px, 100% 40px, 100% 14px, 100% 14px;
background-attachment: local, local, scroll, scroll;
}
<div class="scrollbox">
<ul>
<li>Ah! Scroll below!</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>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>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>The end!</li>
<li>No shadow there.</li>
</ul>
</div>

如果有人能解释一下这种效果是如何实现的?我想我得到了一般要点(如果无法进一步滚动,则有白色阴影覆盖黑色阴影,这是通过背景附件实现的(,但我真的对许多事情感到困惑,例如:

  • 白色阴影如何覆盖黑色阴影,而它们背后的内容却保持可见?
  • 如何在声明(linear-gradient(...) n% n%(之后放置百分比来放置梯度?
  • 为什么使用后台速记时代码不起作用?
  • farthest-side at 50% 0到底在做什么?
  • 为什么没有background-color: white;就不起作用?

白色阴影如何覆盖黑色阴影,而它们背后的内容保持可见?

内容不在他们身后,内容在上面,这是合乎逻辑的,因为内容总是在背景之上。在阴影上使用黑色与文本着色相同,使您认为阴影在上方,但事实并非如此。

如何在声明后放置百分比来放置梯度(线性梯度(...( n% n%(?

0% 100%表示与left bottom相同的left 0% top 100%,并且由于背景的宽度等于100%(用background-size设置(,因此它也与bottom相同(与完整细节相关:在线性渐变上使用带有背景位置的百分比值(

.scrollbox {
overflow: auto;
width: 200px;
max-height: 150px;
background: 
/* Shadow covers */
linear-gradient(white 30%, transparent), 
linear-gradient(transparent, white 70%) bottom,
/* Shadows */
radial-gradient(farthest-side at 50% 0, rgba(0, 0, 0, .2), rgba(0, 0, 0, 0)), 
radial-gradient(farthest-side at 50% 100%, rgba(0, 0, 0, .2), rgba(0, 0, 0, 0)) bottom;
background-repeat: no-repeat;
background-color: white;
background-size: 100% 40px, 100% 40px, 100% 14px, 100% 14px;
background-attachment: local, local, scroll, scroll;
}
<div class="scrollbox">
<ul>
<li>Ah! Scroll below!</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>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>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>The end!</li>
<li>No shadow there.</li>
</ul>
</div>

为什么使用后台速记时代码不起作用?

您只需要正确编写它,如下所示:

.scrollbox {
overflow: auto;
width: 200px;
max-height: 150px;
background: 
/*Gradient                            position / size  repeat attachment*/

/* Shadow covers */
linear-gradient(white 30%, transparent) top   /100% 40px no-repeat local, 
linear-gradient(transparent, white 70%) bottom/100% 40px no-repeat local,
/* Shadows */
radial-gradient(farthest-side at 50% 0   , rgba(0, 0, 0, .2), rgba(0, 0, 0, 0)) top   /100% 14px no-repeat, 
radial-gradient(farthest-side at 50% 100%, rgba(0, 0, 0, .2), rgba(0, 0, 0, 0)) bottom/100% 14px no-repeat,
#fff;
}
<div class="scrollbox">
<ul>
<li>Ah! Scroll below!</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>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>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>The end!</li>
<li>No shadow there.</li>
</ul>
</div>

请注意我如何删除scroll因为它是默认值,您需要为所有渐变指定一个位置,因为它是强制性的,速记中的background-size(与"背景"速记属性中的"背景位置"相关问题(。

50% 0 的最远边到底在做什么?

它正在创建一个结束形状,其中中心位于50% 0(left 50% top 0center top(,它应该接触由background-size定义的背景区域的边缘。对于50% 100%来说,这是center bottom

下面是一个基本示例来说明:

.box {
width:200px;
height:100px;
background:
radial-gradient(farthest-side at center top,red 100%,transparent 100%) top/100% 50px no-repeat;
border:1px solid;
}
<div class="box"></div>

我们的背景大小100% 50px,红色曲率接触边缘,因为色标100%创建我们的半椭圆。

另一个微不足道的例子,我们将形状的中心保持在中心:

.box {
width:200px;
height:100px;
background:
radial-gradient(farthest-side,red 100%,transparent 100%) top/100% 50px no-repeat;
border:1px solid;
}
<div class="box"></div>

使用具有不同值的代码可以更好地查看:

.scrollbox {
overflow: auto;
width: 200px;
max-height: 150px;
background: 
/* Shadow covers */
linear-gradient(white 30%, transparent) top   /100% 40px no-repeat local, 
linear-gradient(transparent, white 70%) bottom/100% 40px no-repeat local,
/* Shadows */
radial-gradient(farthest-side at top    , red 100%, rgba(0, 0, 0, 0)) top   /100% 14px no-repeat, 
radial-gradient(farthest-side at bottom , red 100%, rgba(0, 0, 0, 0)) bottom/100% 14px no-repeat,
#fff;
}
<div class="scrollbox">
<ul>
<li>Ah! Scroll below!</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>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>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>The end!</li>
<li>No shadow there.</li>
</ul>
</div>

请注意我如何将center top(50% 0(简化为仅top,并且对于center bottom也是如此

一些相关问题以获取有关radial-gradient的更多详细信息:

如何使用CSS对径向渐变进行动画处理?

如何在径向渐变中控制椭圆的高度

为什么没有背景色就不起作用:白色;?

它工作正常,没有:

.scrollbox {
overflow: auto;
width: 200px;
max-height: 150px;
background: 
/* Shadow covers */
linear-gradient(white 30%, transparent) top   /100% 40px no-repeat local, 
linear-gradient(transparent, white 70%) bottom/100% 40px no-repeat local,
/* Shadows */
radial-gradient(farthest-side at top , rgba(0, 0, 0, .2), rgba(0, 0, 0, 0)) top/100% 14px no-repeat, 
radial-gradient(farthest-side at bottom , rgba(0, 0, 0, .2), rgba(0, 0, 0, 0)) bottom/100% 14px no-repeat;
}
<div class="scrollbox">
<ul>
<li>Ah! Scroll below!</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>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>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>The end!</li>
<li>No shadow there.</li>
</ul>
</div>


这是使用不同颜色和值的代码,以更好地了解每个渐变和正在发生的事情。您还可以清楚地注意到文本在上方,不需要白色背景。

.scrollbox {
overflow: auto;
width: 200px;
max-height: 150px;
font-weight:bold;
font-size:25px;
background: 
/* Shadow covers */
linear-gradient(red 30%, white) top       /100% 40px no-repeat local, 
linear-gradient(white, red 70%) bottom/100% 40px no-repeat local,
/* Shadows */
radial-gradient(farthest-side at top , yellow 100%, green 100%) top/100% 30px no-repeat, 
radial-gradient(farthest-side at bottom , yellow 100%, green 100%) bottom/100% 30px no-repeat;
}
body {
background:pink;
}
ul {
margin:0;
padding:0;
}
<div class="scrollbox">
<ul>
<li>Ah! Scroll below!</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>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>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>The end!</li>
<li>No shadow there.</li>
</ul>
</div>

以下是初始代码的优化版本:

.scrollbox {
overflow: auto;
width: 200px;
max-height: 150px;
background: 
linear-gradient(white 30%, transparent), 
radial-gradient(farthest-side at top, rgba(0, 0, 0, .2), transparent),

linear-gradient(transparent, white 70%) bottom,
radial-gradient(farthest-side at bottom, rgba(0, 0, 0, .2), transparent) bottom;
background-repeat: no-repeat;
background-size: 100% 40px,100% 14px;
background-attachment: local, scroll;
}
<div class="scrollbox">
<ul>
<li>Ah! Scroll below!</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>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>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>The end!</li>
<li>No shadow there.</li>
</ul>
</div>

另一个版本:

.scrollbox {
overflow: auto;
width: 200px;
max-height: 150px;

--rad:radial-gradient(farthest-side, rgba(0, 0, 0, .2), transparent);  
background: 
linear-gradient(white 30%, transparent), 
var(--rad) 0 -14px,

linear-gradient(transparent, white 70%) bottom,
rvar(--rad) 0 calc(100% + 14px);
background-size: 100% 40px,100% 28px;
background-attachment: local, scroll;
background-repeat: no-repeat;
}
<div class="scrollbox">
<ul>
<li>Ah! Scroll below!</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>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>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>The end!</li>
<li>No shadow there.</li>
</ul>
</div>

还有一个梯度较小的:

.scrollbox {
overflow: auto;
width: 200px;
max-height: 150px;

--rad:radial-gradient(50% 50%, rgba(0, 0, 0, .2), transparent) no-repeat;  
background: 
linear-gradient(white 12px, transparent 40px calc(100% - 40px),white calc(100% - 12px)) local, 
var(--rad) left 0 top    -14px / 100% 28px,    
var(--rad) left 0 bottom -14px / 100% 28px;

}
<div class="scrollbox">
<ul>
<li>Ah! Scroll below!</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>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>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>The end!</li>
<li>No shadow there.</li>
</ul>
</div>

最后一个(是的,最后一个..(代码较少:

.scrollbox {
overflow: auto;
width: 200px;
max-height: 150px;

--rad:radial-gradient(50% 14px, rgba(0, 0, 0, .2), transparent);  
background: 
linear-gradient(white 12px, transparent 40px calc(100% - 40px),white calc(100% - 12px)) local, 
var(--rad) top   /100% 200%,    
var(--rad) bottom/100% 200%;

}
<div class="scrollbox">
<ul>
<li>Ah! Scroll below!</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>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>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>The end!</li>
<li>No shadow there.</li>
</ul>
</div>

最新更新