Я нашел эту печально известную статью 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;?
2
leonheess 20 Дек 2019 в 20:43

1 ответ

Лучший ответ

Как белые тени могут покрывать черные, в то время как содержимое позади них остается видимым?

Контент не находится за ними, контент находится выше, что логично, поскольку контент всегда находится над фоном. Использование черной окраски тени, аналогичной окраске текста, заставляет вас думать, что тень находится сверху, но это не так.

Как размещаются градиенты путем указания процентов после объявления (linear-gradient (...) n% n%)?

0% 100% означает left 0% top 100%, который совпадает с left bottom, и поскольку фон имеет ширину, равную 100% (устанавливается с помощью background-size), он также совпадает с bottom (полная информация по теме: Использование процентных значений с background-position на linear-gradient)

.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 в сокращении (related Проблемы с" background-position "в сокращенном свойстве" background ").

Что именно делает дальняя сторона при 50% 0?

Он создает конечную форму , центр которой находится в точке 50% 0 (left 50% top 0 или center 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?

Как контролировать высоту эллипса в радиальном градиенте

Почему не работает без background-color: white ;?

Он отлично работает без:

.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>
6
Temani Afif 14 Янв 2021 в 10:37