SCSS и кросплатформенный градиент (ну почти)

в 7:35, , рубрики: css, css3, html-верстка, scss, Веб-разработка, Песочница, метки: , , ,

Всем доброго времени суток.
Хочу поделиться одной наработкой с использованием SCSS. Нужно было мне (кстати не однократно, но как то руки не доходили сделать как надо) сделать универсальную генерацию градиента. Универсальную, это возможность задавать несколько градиентов подряд, и должны были поддерживаться префиксы для браузеров (делать так делать).
Поиск подобного рода решения по хабру и гуглу результата не дал, поэтому пришлось справляться своими силами. Далее подробнее по делу.

Я никогда не мог запомнить как правильно записывать правила для кроссбраузерного градиента, поэтому всегда гуглю онлайн сервисы (например этот www.colorzilla.com/gradient-editor/). Сразу при загрузке мы получаем код для градиента:

background: #1e5799; /* Old browsers */
background: -moz-linear-gradient(left, #1e5799 0%, #2989d8 50%, #207cca 51%, #7db9e8 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, right top, color-stop(0%,#1e5799), color-stop(50%,#2989d8), color-stop(51%,#207cca), color-stop(100%,#7db9e8)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(left, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(left, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(left, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* IE10+ */
background: linear-gradient(to right, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#1e5799', endColorstr='#7db9e8',GradientType=1 ); /* IE6-9 */

Забегая наперёд, скажу сразу filter: для ИЕ, и -webkit-gradient для Safari4+ пришлось упустить, из-за невозможности реализовать (ну или я не нашел способа реализации). Поэтому в заголовке красуется «почти». Из вышесказаного у нас получится как то так:

background: #1e5799; /* Old browsers */
background: -moz-linear-gradient(left, #1e5799 0%, #2989d8 50%, #207cca 51%, #7db9e8 100%); /* FF3.6+ */
background: -webkit-linear-gradient(left, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(left, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(left, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* IE10+ */
background: linear-gradient(to right, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* W3C */

Вот это я и реализировал, в результате чего нужно задать для градиента «массив» из цвета и позиции, и на выходе получим правила, описанные выше. Собственно сам массив:

$gradientOptions: rgba(225,225,225,0) 0%, rgba(225,225,225,1) 10%, rgba(225,225,225,1) 90%, rgba(225,225,225,0) 100%;  
@include linearGradient(#fff, $gradientOptions , left);

Подробно изучив (методом проб и ошибок) структуру записи выше, можно выделить 2 повторяющиеся части:

background: -*-linear-gradient(left, #1e5799 0%, #2989d8 50%, #207cca 51%, #7db9e8 100%);

и

#1e5799 0%, #2989d8 50%, #207cca 51%, #7db9e8 100%

Для стоки «background: linear-gradient(to right, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%);» потом сделаем исключение, у нее все равно строка задания цвета повторяется.
Ниже функция для вывода общего кода:

$browsersPrefix: moz o webkit ms;
@mixin linearGradient($oldColor, $gradientList, $direction) {
	background: $oldColor;
	$directionRevers:null; 
	@if $direction == left {
		$directionRevers: right;
	}
	@else if $direction == right {
		$directionRevers: left;
	}
	@else if $direction == top {
		$directionRevers: bottom;
	}
	@else if $direction == bottom {
		$directionRevers: top;
	}
	@include buildGradientLine($gradientList); 
	@each $prefix in $browsersPrefix {
		background:-#{$prefix}-linear-gradient($direction, $resultLine);
	}
	background: linear-gradient(to $directionRevers, $resultLine);
}

Небольшое обьяснение: переменная $directionRevers нужна как раз для правила по W3C стандарту, где направление указывается к какой стороне идет градиент, в отличие от браузерных решений, у которых указано откуда начинается направление. Ах да, в коде возможны всего 4ре направления, но кому хочется более гибкого решения, нарастить код несложно. @each производит перебор по ранее указанных в переменной $browsersPrefix префиксах и выводит почти нужный код.

Остались упущенными строка @include buildGradientLine($gradientList) и переменная $resultLine. Строка @include buildGradientLine($gradientList) как раз и формирует «цветовую строку», а переменная $resultLine ее содержит:

$resultLine:null;
@mixin buildGradientLine($gradientList) {
	$resultLine:null;
	@for $i from 1 through length($gradientList) {
      $colors: nth($gradientList, $i);
			$color: nth($colors, 1);
			$position: nth($colors, 2);
			
      $resultLine: $resultLine $color $position;
      @if $i != length($gradientList) {
			$resultLine: $resultLine#{','}
      }
  }
}

Для начала объявляем как глобальную переменную $resultLine:null, а далее логика понятна для рядового программиста (должно быть понятно и для студента, хотя, всякое бывает). Кстати с этой частью кода у меня была проблема. Вместо цикла я использовал обычный @each, в результате чего у меня получалось то же самое, с разницей в том, что в строке, в конце, присутствовала последняя запятая, с которой градиент не захотел отображаться. Решение с циклом @for я подсмотрел тут. Кому интересно что это за хитрая часть кода:

$colors: nth($gradientList, $i);
	$color: nth($colors, 1);
	$position: nth($colors, 2);

объясняю: $colors: nth($gradientList, $i); выбирает нужную пару значений в цикле из всего массива, а $color: nth($colors, 1); $position: nth($colors, 2) запись в переменные цвета и позиции соответственно.

Вот так и получился почти кроссбраузерный градиент. Пробовал у себя с использованием процентов в качестве позиции для цвета, но должно работать и с пикселями, главное не промахнуться. RGBA тоже отрабатывает. Демо не прилагается, так как сейчас нет на это времени, появится время, обязательно добавлю.

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

Автор: hermit931

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js