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

plupiseo  于 2023-02-26  发布在  其他
关注(0)|答案(5)|浏览(319)

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

我的意思是:

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

为了进一步澄清

  • 如果容器的内容溢出(即,其滚动)并且用户处于内容的最顶部,则在页面的底部而不是顶部应该有阴影。
  • 如果用户在页面的底部也是如此,希望页面的顶部有一个阴影
  • 如果内容没有溢出容器,则应该显示 no 阴影以保持内容干净。

我有工作的javascript解决方案,但我想要一些纯粹的css性能的原因。
有什么想法吗?

qqrboqgw

qqrboqgw1#

我想你在找这样的东西
参考: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>
xeufq47z

xeufq47z2#

我很抱歉在这里回答我自己的问题,但经过一些谷歌搜索,我发现了一个很好的CSS唯一的解决方案,在macOS上的 chrome 工程。
@Hash提供了一个来自lea verou博客的解决方案,她的解决方案使用background-attachment: local来达到这个效果,但是目前在macOS?上的chrome 59中这个解决方案被破坏了。
它在2012年起作用了,但在2017年对我来说没有,至少现在是这样

它现在在2020年有效,所以你可以看接受的答案,而不是这个。♀🤷‍♀️

尽管如此,她的解决方案是伟大的和you should read more about it here
在她的文章(2012年)中,她提到了一个更老但更兼容的解决方案,该解决方案使用pseudoelements. This blog post is by Roman Komarov and here are some direct quotes from his article
这里有一个老的想法,但recreated与纯CSS.
最初,我有一个额外的 Package 和两个额外的伪元素,后来我决定重写代码,只使用一个元素(通过使用ra dial gra di ents)。
虽然这种方法很简单,但也有一些限制:

  • 背景必须坚实
  • 如何曾经,如果你会尝试背景-在tachment:固定...)
  • 有一些问题

但在大多数情况下,这种方法是相当bulletproof。
如果你用简单的图片替换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>
cxfofazt

cxfofazt3#

这是我整理的一个纯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>
wqlqzqxt

wqlqzqxt4#

如果您的用例允许将阴影放置在内容的后面,作为元素背景的一部分,那么公认答案中的纯CSS解决方案效果很好。
如果您的用例要求阴影位于内容之上,或者独立于元素的背景,那么您可能需要使用一些JavaScript。我满足了这些要求,并构建了一个定制元素,其工作方式与OP要求的完全相同:<scroll-shadow> element.
用法示例(垂直和水平工作,see demo here):

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

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

os8fio9y

os8fio9y5#

我能够把一个工作的CSS的唯一解决方案与阴影以上的内容使用粘性(和父div,也有一些间距内的滚动内容):
演示:https://jsfiddle.net/y79avtek/

.scroll-shadows {
  max-height: 200px;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  overflow-scrolling: touch;
}

.parent:before {
  content: '';
  background:     /* Shadow TOP */
    radial-gradient(
      farthest-side at 50% 0,
      rgba(0, 0, 0, 0.2),
      rgba(0, 0, 0, 0)
    ) center top;
  height: 10px;
  display: block;
  position: absolute;
  width: 200px;
}

.parent:after {
  content: '';
  background:       /* Shadow BOTTOM */
    radial-gradient(
      farthest-side at 50% 100%,
      rgba(0, 0, 0, 0.2),
      rgba(0, 0, 0, 0)
    ) center bottom;
  height: 10px;
  display: block;
  position: absolute;
  margin-top: -10px;
  width: 200px;
}

.scroll-shadows:before {
  background:
    /* Shadow Cover TOP */
    linear-gradient(
      white 30%,
      rgba(255, 255, 255, 0)
    ) center top;
  content: '';
  background: white;
  display: block;
  position: sticky;
  height: 10px;
}

.scroll-shadows:after {
  background:
        /* Shadow Cover BOTTOM */
    linear-gradient(
      rgba(255, 255, 255, 0), 
      white 70%
    ) center bottom;
  content: '';
  background: white;
  display: block;
  position: sticky;
  height: 10px;
  z-index: 1;
}

/* Not important to the functionality, just for this particular demo */
.scroll-shadows {
  list-style: none;
  padding-right: 0.5rem;
}
.scroll-shadows > * {
  padding: 0.2rem;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
body {
  height: 100vh;
  display: grid;
  place-items: center;
  font: 500 100% system-ui, sans-serif;
}
.scroll-shadows {
  --scrollbarBG: transparent;
  --thumbBG: #90a4ae;

  scrollbar-width: thin;
  scrollbar-color: var(--thumbBG) var(--scrollbarBG);
}
.scroll-shadows::-webkit-scrollbar {
  width: 6px;
}
.scroll-shadows::-webkit-scrollbar-track {
  background: var(--scrollbarBG);
}
.scroll-shadows::-webkit-scrollbar-thumb {
  background-color: var(--thumbBG);
  border-radius: 6px;
  border: 3px solid var(--scrollbarBG);
}
<div class="parent">
  <ul class="scroll-shadows">
    <li>Lorem, ipsum.</li>
    <li>Eligendi, repudiandae.</li>
    <li style="border: 1px solid black;background: white">Dolor, vel.</li>
    <li style="border: 1px solid black;background: white">Obcaecati, praesentium.</li>
    <li>Impedit, tenetur.</li>
    <li style="border: 1px solid black;background: white">Exercitationem, repellat!</li>
    <li>Aut, asperiores!</li>
    <li style="border: 1px solid black;background: white">Dolor, fuga.</li>
    <li>Ab, aliquid<span style="background: white; border: 1px solid black;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>!</li>
    <li style="border: 1px solid black;background: white">Adipisci, totam.</li>
    <li>Error, dicta.</li>
    <li style="border: 1px solid black;background: white">Saepe, vero?</li>
    <li>Eveniet, dolorem!</li>
    <li>Id, tempora!</li>
    <li>Voluptate, consectetur?</li>
    <li style="border: 1px solid black;background: white">Voluptatibus, omnis.</li>
    <li>Eius, fugit.</li>
    <li>Quia, non!</li>
    <li>At, laudantium?</li>
    <li>Commodi, maiores!</li>
  </ul>
</div>

相关问题