如何在滚动时添加顶部和底部阴影,但仅在需要时添加?

时间:2017-06-28 04:03:19

标签: css

当容器溢出时,如何仅在需要时添加阴影?

我的意思是:

  • 如果有内容可以在顶部或底部滚动,请显示阴影以告知用户有更多内容要scoll
  • 如果没有要滚动的内容,则不会出现阴影

并进一步澄清

  • 如果容器的内容溢出(即滚动)并且用户位于内容的最顶部,那么页面的底部应该有阴影,而不是顶部。
  • 如果位于页面底部的用户希望顶部应该有阴影
  • ,则同样如此
  • 如果内容没有溢出容器,则应显示 no 阴影以保持清洁。

我有工作的JavaScript解决方案,但出于性能原因,我想要一些纯粹的css

有什么想法吗?

4 个答案:

答案 0 :(得分:16)

我为在这里回答我自己的问题而道歉,但经过一些谷歌搜索,我找到了一个很好的CSS解决方案,适用于macOS上的chrome。

@Hash提供了一个来自lea verou博客的解决方案。她的解决方案使用background-attachment: local来实现效果,但是目前在macOS上的chrome 59中已经破解了? (它至少在2012年开始工作,但至少在2017年没有)但是,她的解决方案非常棒you should read more about it here

在她的文章(2012年)中,她提到了一个使用伪元素的旧的更兼容的解决方案。 This blog post is by Roman Komarov and here are some direct quotes from his article

  

这是一个古老的想法,但是用纯CSS重新创建。

     

最初,我有一个额外的包装器和两个额外的伪元素。后来我决定重写代码并只使用一个元素(通过使用径向渐变)。

     

虽然这种方法很简单,但也有一些限制:

     
      
  • 背景必须是实心的      
        
    • 但是,如果您尝试使用background-attachment:fixed ...)
    •   
  •   
  • 存在一些定位问题
  •   
     

但在大多数情况下,这种方法相当防弹。

     

如果用简单的图像替换CSS渐变,这种方法可以在IE中使用。 (它可能需要一些小的修复;我没有检查。)

以下是一些直接从他的博客中复制的代码:

html {
  background: #FFF;
}

.scrollbox {
  position: relative;
  z-index: 1;
  overflow: auto;
  width: 200px;
  max-height: 200px;
  margin: 50px auto;
  background: #FFF no-repeat;
  background-image: -webkit-radial-gradient(50% 0, farthest-side, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), -webkit-radial-gradient(50% 100%, farthest-side, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0));
  background-image: -moz-radial-gradient(50% 0, farthest-side, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), -moz-radial-gradient(50% 100%, farthest-side, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0));
  background-image: radial-gradient(farthest-side at 50% 0, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), radial-gradient(farthest-side at 50% 100%, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0));
  background-position: 0 0, 0 100%;
  background-size: 100% 14px;
}

.scrollbox:before,
.scrollbox:after {
  content: "";
  position: relative;
  z-index: -1;
  display: block;
  height: 30px;
  margin: 0 0 -30px;
  background: -webkit-linear-gradient(top, #FFF, #FFF 30%, rgba(255, 255, 255, 0));
  background: -moz-linear-gradient(top, #FFF, #FFF 30%, rgba(255, 255, 255, 0));
  background: linear-gradient(to bottom, #FFF, #FFF 30%, rgba(255, 255, 255, 0));
}

.scrollbox:after {
  margin: -30px 0 0;
  background: -webkit-linear-gradient(top, rgba(255, 255, 255, 0), #FFF 70%, #FFF);
  background: -moz-linear-gradient(top, rgba(255, 255, 255, 0), #FFF 70%, #FFF);
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #FFF 70%, #FFF);
}
<div class="scrollbox">
    <ul>
        <li>Not enough content to scroll</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
</div>


<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>

答案 1 :(得分:7)

我认为你在找这样的东西;

参考:LINK

html {
  background: white;
  font: 120% sans-serif;
}

.scrollbox {
  overflow: auto;
  width: 200px;
  max-height: 200px;
  margin: 50px auto;
  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(50% 0, farthest-side, rgba(0, 0, 0, .2), rgba(0, 0, 0, 0)), radial-gradient(50% 100%, farthest-side, rgba(0, 0, 0, .2), rgba(0, 0, 0, 0)) 0 100%;
  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;
  /* Opera doesn't support this in the shorthand */
  background-attachment: local, local, scroll, scroll;
}
<div class="scrollbox">
  <ul>
    <li>I Show Below Shadow. Go Down Now</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>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>
    <li>The end!</li>
    <li>No shadow here. See Above. Go Up</li>
  </ul>
</div>

答案 2 :(得分:1)

这是我放在一起的纯CSS解决方案,将阴影放在内容的上方而不是后面。

/* Stuff that doesn't matter */

html {
  font-size: 16px;
}

body {
  margin: 0;
  padding: 0;
  font: 1rem/1.5 arial, sans-serif;
}

.c-container {
  width: 100%;
  max-width: 400px;
  margin: 0 auto;
  padding: 0 2rem;
  box-sizing: border-box;
}

.c-header {
  width: 100%;
  padding: 1rem 0;
  background: white;
}

.c-header_heading {
  margin: 0;
  font-size: 2rem;
  font-weight: bold;
}

/* Stuff that matters */

.c-scrollbox {
  position: relative;
  width: 100%;
  height: 200px;
  overflow: scroll;
}

.c-scrollbox::before {
  content: '';
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  display: block;
  height: 1px;
  background: rgba(0,0,0,.32);
}

.c-scrollbox::after {
  content: '';
  position: absolute;
  top: 0;
  display: block;
  width: 100%;
  height: 1rem;
  background: linear-gradient(rgba(255,255,255,1) 0%, rgba(255,255,255,0) 100%);
}
<div class="c-container">
  <header class="c-header">
    <h1 class="c-header_heading">Shadow on Scroll</h1>
  </header>
  <div class="c-scrollbox">
    <p>Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ullamcorper nulla non metus auctor fringilla. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
    <p>Donec id elit non mi porta gravida at eget metus. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Etiam porta sem malesuada magna mollis euismod. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>
    <p>Vestibulum id ligula porta felis euismod semper. Nullam quis risus eget urna mollis ornare vel eu leo. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nullam quis risus eget urna mollis ornare vel eu leo. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</p>
    <p>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Nulla vitae elit libero, a pharetra augue. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
  </div>
</div>

答案 3 :(得分:0)

如果您的用例可以将阴影作为元素背景的一部分放置在内容后面,那么已接受答案中的纯 CSS 解决方案会非常有效。

如果您的用例要求阴影位于内容之上,或者独立于元素的背景,则您可能需要使用一些 JavaScript。我有这些要求,并构建了一个与 OP 要求的完全相同的自定义元素:<scroll-shadow> element

示例用法(垂直和水平工作,see demo here):

<scroll-shadow>
  <nav>Content…</nav>
</scroll-shadow>

OP 要求仅使用 CSS 的解决方案,但事实并非如此。尽管如此,它还是利用了 CSS 并且不应该对性能产生负面影响。将此作为答案发布,因为从其他评论来看,似乎普遍需要在内容上方添加阴影。