оригинал:The State of CSS Reflections
Примечание: чтобы облегчить понимание читателя, в этой статье используется свободный перевод, а не дословный перевод, во-вторых, исходный текст очень длинный, и автор также предлагает решение, совместимое с браузером.Этот перевод сосредоточен на введении.
box-reflex
Эффект атрибута не объясняет проблемы совместимости.Заинтересованные читатели могут нажать на исходный текст, чтобы прочитать, спасибо~Напоследок: перевод не из легких, перевод просит Звезду://github.com/qiud...
Недавно я былCodePenЯ нашел чистую реализацию CSS на заборе с градиентным отражением и эффектом 3D-вращения.Его метод реализации: использование 10<div>
Элемент создает 10 полос сетки, затем дублирует всю<div>
элемент и создайте маску градиента, чтобы сформировать эффект градиента, действующий как отражение забора.
Это похоже на почесывание затылка за правым ухом пальцами левой ноги (Переводчик понимает: значение выражения должно состоять в том, чтобы использовать сложный способ обращения с вещью, которую на самом деле можно достичь простым способом.)! Не говоря уже о том, что этот способ градиентной маскировки просто не работает для неодноцветных фонов. Разве нет лучшего способа, основанного на CSS?
Ответ — да, у нас есть лучший способ добиться этого эффекта! Но, к сожалению, совместимость этого способа недостаточно хороша, если мы не хотим использоватьcanvas
, но также надеемся, что он будет совместим со всеми основными браузерами, описанный выше метод, несомненно, является лучшим.
В этой статье мы рассмотрим все возможные варианты создания отражений, которые у нас есть сегодня, опишу эти «похожие» решения, боль, которую они вызывают в кроссбраузерных проблемах, и, наконец, обсудим мои мысли о том, что с ними делать (Перевод не очень).
Кодовая база
Прежде чем обсуждать отражения, давайте взглянем на то, как создавать, размещать и затенять полосы ограждения, так как эта часть является общей для всех браузеров.
Сначала мы создаем.loader
обертка и содержит 10.bar
элемент
<div class='loader'>
<div class='bar'></div>
<!-- 继续创建9条 -->
</div>
Помимо непосредственного написания HTML, мы также можем использовать препроцессоры, такие какHaml:
.loader
- 10.times do
.bar
Мы начинаем эти элементы из промежуточного положения в области просмотра. Обычно мы все используемtop: 50%
центрировать, но если мы используемbottom: 50%
Позже будет удобнее.
div {
position: absolute;
bottom: 50%; left: 50%;
}
Мы определяем ширину и высоту этих стержней забора и задаем фон:
$bar-w: 1.25em;
$bar-h: 5 * $bar-w;
.bar {
width: $bar-w; height: $bar-h;
background: currentColor;
}
Мы хотим, чтобы нижний край сетки перекрывал горизонтальную центральную ось окна просмотра, установив параметрbottom: 50%
Этот эффект был достигнут.
В этот момент все наши полосы сетки сложены вместе, их левый край совпадает с продольной центральной осью окна просмотра, а нижний край перекрывается с горизонтальной центральной осью,Посмотреть онлайн:
позиционирующий забор
Нам нужно расположить эти заборы так, чтобы левый край первого забора и правый край последнего забора находились на одинаковом расстоянии от продольной центральной оси, которое всегда равно количеству заборов ($n
) умножить на ширину полосы ($bar-w
) половину полученного значения. В начальной демонстрации использовались обычныеCSS
, теперь мы используемSass
чтобы упростить количество кода,Посмотреть здесь:
$bar-w
серединаСтоляр, а не минус, во избежание двусмысленности используйте его позже$bar_w
заменять
Это означает, что, начиная с позиций всех полос сетки, нам нужно переместить первую полосу сетки влево.0.5 * $n * $bar_w
. слеваx
Отрицательное направление оси, а это значит, что впереди требуется отрицательный знак, поэтому первая сеткаmargin-left
значение-.5 * $n * $bar_w
.
Позиция второй сетки состоит в том, чтобы переместить ширину сетки вправо от позиции первой сетки, затем ееmargin-left
значение должно быть-.5 * $n * $bar_w + $bar_w
;
Аналогично, третья сеткаmargin-left
значение-.5 * $n * $bar_w + 2 * $bar_w
;
Затем последняя сеткаmargin-left
то есть:-.5 * $n * $bar-w + ($n - 1) * $bar-w
.
Как показано ниже:Посмотреть онлайн
Мы выражаем это в коде как:$n: 10;
@for $i from 0 to $n {
.bar:nth-child(#{$i + 1}) {
margin-left: ($i - .5 * $n) * $bar-w;
}
}
мы устанавливаем ихbox-shadow
, поэтому мы можем четко видеть конец одного бара и начало следующего:
покрасить забор
Цвет фона забора начинается с крайнего левого угла.темно-синий(#1e3f57
) крайний правыйсветло-синий(#63a6c1
), что звучит какSass
изmix()
что делает функция.mix()
Первый параметр — светло-синий, второй параметр — темно-синий, а третий параметр (называемый относительным весом в %) — это количество светло-голубого, включенное в окончательный результат смешивания.
Для первой сетки количество голубого должно быть0% - 0%
, поэтому окончательный результат будет только темно-синим;
Точно так же для последней полосы количество голубого должно быть100% -100%
, композиция фонового цвета светло-голубая;
Для остальных баров нам нужно сделать медиану равномерно распределенной. Предположим, у нас есть$n
полосы сетки, первый0%
, последний есть100%
, то нам нужно разбить их на$n - 1
равноудаленные промежутки. Как показано ниже:
$i
Относительный вес стержней сетки:$i * 100% / ($n - 1)
, мы добавляем следующий код:
$c: #63a6c1 #1e3f57; // 1st = light 2nd = dark
@for $i from 0 to $n {
// list of mix() arguments for current bar
$args: append($c, $i * 100% / ($n - 1));
.bar:nth-child(#{$i + 1}) {
background: mix($args...);
}
}
Теперь заборы выглядят так же, как и в оригинальной демонстрации:Посмотреть онлайн
-webkit-box-reflect
box-reflect
все ещенестандартные свойства, который еще не поддерживается многими основными браузерами, к счастью, он доступен вwebkit
Он отлично работает в браузере, просто добавьте личные свойства браузера.
Давайте посмотрим, как это работает, его значение состоит из трех частей:
-webkit-box-reflect:none | <direction> <offset>? <mask-box-image>?
-
<direction>
: направление отражения, которое может бытьbelow
,left
,above
,right
любое значение в -
<offset>
: расстояние между отражением и исходным изображением, значение может быть фиксированным значением в пикселях или в процентах. -
<mask-box-image>
: Установите эффект маски отражения, который может быть фоновым изображением или градиентным изображением.
Следующая интерактивная демонстрация иллюстрирует это (вы можете щелкнуть, чтобы изменить направление, смещение и т. д. отражения):
прямое интервьюdemoИграй сам!
В нашем случае первое, что приходит на ум, это.loader
добавьте это в:
.loader {
-webkit-box-reflect: below 0 linear-gradient(rgba(#fff, 0), rgba(#fff, .7));
}
Во-вторых, мы также должны дать.loader
Установите размер, потому что содержащиеся в нем заборы в настоящее время абсолютно позиционированы..loader
Фактический размер0px X 0px
. Мы определяем его ширину как сумму всех ширин забора и его высоту как высоту забора:
$loader-w: $n * $bar-w;
.loader {
width: $loader-w; height: $bar-h;
box-shadow: 0 0 0 1px red;
}
После добавления приведенного выше кода вы увидите следующий эффект в браузере webkit:Посмотреть онлайн
Мы уже можем видеть границы загрузчика и некоторые отражения, но они уже не в правильном положении. Нам нужно отцентрировать загрузчик слева, совместив нижние части ограждений с нижними частями их родительских элементов:
.loader { margin-left: -.5 * $loader-w; }
.bar { bottom: 0; }
Это решает проблему позиционирования, и эффект следующий:
// Здесь опущен ряд схем совместимости с Firefox: element()+svg mask …
анимация
Анимация, изначально реализованная в CodePen, была очень простой, просто 3D-турникет:
@keyframes bar {
0% {
transform: rotate(-.5turn) rotateX(-1turn);
}
75%, 100% { transform: none; }
}
Применить анимацию ко всем заборам:
animation: bar 3s cubic-bezier(.81, .04, .4, .7) infinite;
Затем добавьте разные задержки для каждого такта:
animation-delay: $i*50ms;
Поскольку мы 3D-турникет, нам также необходимоloader
добавить элементperspective
Атрибуты:.
.loader {
perspective: 62.5em;
}
но это толькоwebkit
использовать в браузере-webkit-box-reflect
действует когда. Достигнут конечный эффект:Посмотреть онлайн
Последние мысли
Забудьте, этот абзац не нужно переводить!
По поводу того, что автор-webkit-box-reflect
а такжеelement()+mask
(svg
изmask
тег) для решения проблемы отражения в кроссбраузерной реализации, не влияя на наше пониманиеbox-reflect
Отлично, заинтересованные читатели могут посмотреть оригинальный текст, спасибо~