SCSS and cross-platform gradient (well, almost)

Good day to all.
I want to share one experience using SCSS. It was necessary for me (by the way not once, but somehow my hands did not reach to do it right) to make universal gradient generation. Universal, it is an opportunity to set several gradients in a row, and prefixes for browsers should be supported (to do so).
The search for this kind of solution for Habr and Google did not give a result, so I had to cope on my own. Further details on the case.

I could never remember how to write down the rules for the cross-browser gradient correctly, so I always google online services (for example, this www.colorzilla.com/gradient-editor ). Immediately upon loading, we get the code for the gradient:

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


Looking ahead, I’ll say right away filter: for IE, and -webkit-gradient for Safari4 + had to be missed, due to the inability to implement (well, or I did not find a way to implement it). Therefore, the title flaunts "almost." From the above, we get something like this:

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


This is what I implemented, as a result of which we need to set the gradient to an “array” of color and position, and at the output we will get the rules described above. Actually the array itself:

$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);


Having studied in detail (by trial and error) the structure of the record above, we can distinguish 2 repeating parts:

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


and

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


For stock “background: linear-gradient (to right, # 1e5799 0%, # 2989d8 50%, # 207cca 51%, # 7db9e8 100%);" then we will make an exception, she still has the line of setting the color repeated.
Below is the function to output the common code:

$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);
}


A little explanation: the variable is $directionReversneeded just for the rule according to the W3C standard, where the direction is indicated to which side the gradient goes, unlike browser solutions, which indicate where the direction starts from. Oh yes, there are only 4 directions in the code, but whoever wants a more flexible solution, it’s easy to build the code. @eachiterates over the $browsersPrefixprefixes previously specified in the variable and displays the almost necessary code.

Left out a string @include buildGradientLine($gradientList)and a variable $resultLine. The line @include buildGradientLine($gradientList)just forms the “color line”, and $resultLineits variable contains:

$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#{','}
      }
  }
}


To begin with, we declare it as a global variable $resultLine:null, and then the logic is understandable for the ordinary programmer (it should be clear for the student, though, anything can happen). By the way, I had a problem with this part of the code. Instead of a loop, I used the usual one @each, as a result of which I got the same thing, with the difference that in the line, at the end, there was the last comma with which the gradient did not want to be displayed. @forI spotted a solution with a loop here . Who cares what this tricky part of the code is:

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


I explain: $colors: nth($gradientList, $i);selects the desired pair of values ​​in the loop from the entire array, and $color: nth($colors, 1); $position: nth($colors, 2)writes to color and position variables, respectively.

And so it turned out almost cross-browser gradient. I tried using percentages as a position for color, but it should work with pixels, the main thing is not to miss. RGBA also fulfills. The demo is not attached, since now there is no time for this, there will be time, I will definitely add it.

PS: The code was inserted from a ready-made solution, so the names of variables can hurt the eye. With spelling, punctuation and other things you yourself know where.

Also popular now: