In an SVG gradient you can set the start x y and end x y position. Is it possible to do that in CSS.
Here is the original design:
Here is my SVG with linear gradient:
.myRectangle {
width: 331px;
height: 137px;
left: 0px;
top: 0px;
}
<svg class="myRectangle">
<linearGradient id="LinearGradientFill2" spreadMethod="pad" x1="1" x2="0.5" y1="0" y2="0.5">
<stop offset="0" stop-color="#f7f7f7" stop-opacity="1" cssvalue=""></stop>
<stop offset="0.266" stop-color="#ea0000" stop-opacity="1" cssvalue=""></stop>
<stop offset="0.7685" stop-color="#6c165f" stop-opacity="1" cssvalue=""></stop>
<stop offset="1" stop-color="#272020" stop-opacity="1" cssvalue=""></stop>
</linearGradient>
<rect fill="url(#LinearGradientFill2)" id="myRectangle" rx="0" ry="0" x="0" y="0" width="331" height="137">
</rect>
</svg>
Here is my CSS linear gradient:
#rectangle {
width: 100%;
height: 200px;
position: absolute;
top: 0;
left: 0;
background: linear-gradient(225deg, rgba(255,255,255,1) 0%, rgba(250,0,0,1) 27.59%, rgba(108,22,95,1) 76.35%, rgba(39,32,32,1) 100%)
}
<div id="rectangle">
</div>
I've been referencing this page on MDN and this page on W3C.
The SVG contains the orientation of the gradient
x1="1" x2="0.5" y1="0" y2="0.5"
The element also takes several other attributes, which specify the size and appearance of the gradient. The orientation of the gradient is controlled by two points, designated by the attributes x1, x2, y1, and y2. These attributes define a line along which the gradient travels. The gradient defaults to a horizontal orientation, but it can be rotated by changing these. Gradient2 in the above example is designed to create a vertical gradient. - from https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Gradients
From other documentation:
X and Y position of the start of the gradient line, as a multiple of the object's bounding box: X=0 indicates the left edge of the bounding box and X=1 indicates the right edge. The gradient line may start or end outside the object's bounding box, so values may be < 0 or > 1.
SVG provides for two types of gradients: linear gradients and radial gradients. Once defined, gradients are then referenced using 'fill' or 'stroke' properties on a given graphics element to indicate that the given element shall be filled or stroked with the referenced gradient.
You can combine a background-image and CSS3 gradient on the same element by using several backgrounds. In our example below, we set the height and width of our <div> and add a background. Then, we set the background image fallback using the “url” value of the background-image property.
Using Angles If you want more control over the direction of the gradient, you can define an angle, instead of the predefined directions (to bottom, to top, to right, to left, to bottom right, etc.). A value of 0deg is equivalent to "to top". A value of 90deg is equivalent to "to right".
To use a gradient, we have to reference it from an object's fill or stroke attributes. This is done the same way you reference elements in CSS, using a url . In this case, the url is just a reference to our gradient, which I've given the creative ID, "Gradient". To attach it, set the fill to url(#Gradient) , and voila!
You can divide all the value of color stop by the same factor in order to reduce the size of the gradient and make it similar to the SVG one.
I used CSS variable to make it easy but it's not mandatory
.rectangle {
width: 100%;
height: 200px;
--s:2;
background:
linear-gradient(225deg,
rgba(255,255,255,1) 0%,
rgba(250,0,0,1) calc(27.59%/var(--s)),
rgba(108,22,95,1) calc(76.35%/var(--s)),
rgba(39,32,32,1) calc(100%/var(--s)));
}
<div class="rectangle">
</div>
<div class="rectangle" style="--s:1.5">
</div>
<div class="rectangle" style="--s:3">
</div>
You can add an extra variable to offset the gradient which will simulate the starting point:
.rectangle {
width: 100%;
height: 200px;
--s:2;
--p:10%;
background:
linear-gradient(225deg,
rgba(255,255,255,1) var(--p),
rgba(250,0,0,1) calc(27.59%/var(--s) + var(--p)),
rgba(108,22,95,1) calc(76.35%/var(--s) + var(--p)),
rgba(39,32,32,1) calc(100%/var(--s) + var(--p)));
}
<div class="rectangle">
</div>
<div class="rectangle" style="--s:3;--p:20%">
</div>
<div class="rectangle" style="--s:3">
</div>
Here is some comparaison between SVG and CSS gradient:
.rectangle {
background:
linear-gradient(var(--a),
#f7f7f7 var(--p),
#ea0000 calc(26.6%/var(--s) + var(--p)),
#6c165f calc(76.85%/var(--s) + var(--p)),
#272020 calc(100%/var(--s) + var(--p)));
}
.myRectangle,
.rectangle {
width:100px;
height:100px;
display:inline-block;
}
<svg class="myRectangle" viewBox="0 0 100 100">
<linearGradient id="LinearGradientFill2" spreadMethod="pad" x1="0.7" x2="0.5" y1="0.2" y2="0.5">
<stop offset="0" stop-color="#f7f7f7" ></stop>
<stop offset="0.266" stop-color="#ea0000" ></stop>
<stop offset="0.7685" stop-color="#6c165f" ></stop>
<stop offset="1" stop-color="#272020" ></stop>
</linearGradient>
<rect fill="url(#LinearGradientFill2)" rx="0" ry="0" x="0" y="0" width="100" height="100">
</rect>
</svg>
<div class="rectangle" style="--s: 3.82;--p: 23.87%;--a:213.69deg;">
</div>
<svg class="myRectangle" viewBox="0 0 100 100">
<linearGradient id="LinearGradientFill3" spreadMethod="pad" x1="0.7" x2="1" y1="0.2" y2="0.8">
<stop offset="0" stop-color="#f7f7f7" ></stop>
<stop offset="0.266" stop-color="#ea0000" ></stop>
<stop offset="0.7685" stop-color="#6c165f" ></stop>
<stop offset="1" stop-color="#272020" ></stop>
</linearGradient>
<rect fill="url(#LinearGradientFill3)" rx="0" ry="0" x="0" y="0" width="100" height="100">
</rect>
</svg>
<div class="rectangle" style="--s: 1.98;--p: 33%;--a: 153.5deg;">
</div>
<svg class="myRectangle" viewBox="0 0 100 100">
<linearGradient id="LinearGradientFill4" spreadMethod="pad" x1="0.2" x2="0.5" y1="1" y2="0.8">
<stop offset="0" stop-color="#f7f7f7" ></stop>
<stop offset="0.266" stop-color="#ea0000"></stop>
<stop offset="0.7685" stop-color="#6c165f" ></stop>
<stop offset="1" stop-color="#272020" ></stop>
</linearGradient>
<rect fill="url(#LinearGradientFill4)" rx="0" ry="0" x="0" y="0" width="100" height="100">
</rect>
</svg>
<div class="rectangle" style="--s: 3.84;--p: 12%;--a: 56.3deg;">
</div>
<svg class="myRectangle" viewBox="0 0 100 100">
<linearGradient id="LinearGradientFill5" spreadMethod="pad" x1="0.9" x2="0.2" y1="1" y2="0.8">
<stop offset="0" stop-color="#f7f7f7" ></stop>
<stop offset="0.266" stop-color="#ea0000" ></stop>
<stop offset="0.7685" stop-color="#6c165f" ></stop>
<stop offset="1" stop-color="#272020" ></stop>
</linearGradient>
<rect fill="url(#LinearGradientFill5)" rx="0" ry="0" x="0" y="0" width="100" height="100">
</rect>
</svg>
<div class="rectangle" style="--s: 1.7;--p: 10%;--a: -74.05deg;">
</div>
You keep the color and percetange values the same. For the SVG you adjust x,y values and for the CSS you adjust the variables (the angle, the offset and the divider)
The formula of the angle is like below:
angle = arctang(Height*(x2 - x1)/Width*|y2 - y1|)
if y2 > y1
we do an extra step to have angle = 180deg - angle
To find the divider we need to consider the length of the CSS gradient which is equal to
Dc = |Width * sin(angle)| + |Height * cos(angle)|
and the length of the SVG gradient which is equal to:
Ds = sqrt(Width²*(x2 - x1)² + Height²*(y2 - y1)²)
Then we do a simple division Dc/Ds
The formula of the offset p
is ((Dc/2 - d)*100) / Dc
where Dc
is the length of the CSS gradient defined previously and d
is equal to:
d = (Width²*(x1-0.5)*(x1-x2)+Height²*(y1-0.5)*(y1-y2))/(sqrt(Width²*(x2-x1)²+Height²*(y2-y1)²))
Here is an interactive demo
function update() {
var H = $('[name=h]').val();
var W = $('[name=w]').val();
var x1 = $('[name=x1]').val();
var x2 = $('[name=x2]').val();
var y1 = $('[name=y1]').val();
var y2 = $('[name=y2]').val();
$('#LinearGradientFill2').attr('x1',x1);
$('#LinearGradientFill2').attr('x2',x2);
$('#LinearGradientFill2').attr('y1',y1);
$('#LinearGradientFill2').attr('y2',y2);
$('polyline').attr('points',(x1*W)+','+(y1*H)+' '+(x2*W)+','+(y2*H));
var angle = Math.atan((H*(x2 - x1))/Math.abs(W*(y2 - y1)))
if(y2 > y1)
angle=Math.PI - angle;
$('.rectangle').css("--a", (angle * 180 / Math.PI)+"deg");
var Dc = Math.abs(W*Math.sin(angle)) + Math.abs(H*Math.cos(angle));
var Ds = Math.sqrt(W*W*(x2 - x1)*(x2 - x1) + H*H*(y2 - y1)*(y2 - y1));
var s=Dc/Ds;
$('.rectangle').css("--s", s+'');
var d = (W*W*(x1 - 0.5)*(x1 - x2)+H*H*(y1 - 0.5)*(y1 - y2))/Math.sqrt(W*W*(x2 - x1)*(x2 - x1) + H*H*(y2 - y1)*(y2 - y1));
$('.rectangle').css("--p", (((Dc/2 - d)*100) / Dc)+"%");
// update elements
$('[name=a]').val(Math.floor(angle * 180 / Math.PI));
$('rect').attr("width", W);
$('.rectangle').css("width", W);
$('.myRectangle').css("width", W);
$('rect').attr("height", H);
$('.rectangle').css("height", H);
$('.myRectangle').css("height", H);
$('.myRectangle').attr("viewBox", "0 0 " + W + " " +H);
};
$('input').change(update);
update();
.rectangle {
background:
linear-gradient(var(--a,0deg),
#f7f7f7 var(--p,0%),
#ea0000 calc(26.6%/var(--s,1) + var(--p,0%)),
#6c165f calc(76.85%/var(--s,1) + var(--p,0%)),
#272020 calc(100%/var(--s,1) + var(--p,0%)));
}
.myRectangle,
.rectangle {
width:150px;
height:100px;
display:inline-block;
margin:10px;
border:1px solid green;
}
input {
width:50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
W: <input type="number" name="w" step="1" value="100">
H: <input type="number" name="h" step="1" value="100">
A: <input type="number" name="a" disabled>
<br>
X1: <input type="number" name="x1" step="0.1" value="1">
X2: <input type="number" name="x2" step="0.1" value="0.5">
Y1: <input type="number" name="y1" step="0.1" value="0">
Y2: <input type="number" name="y2" step="0.1" value="0.5">
<br>
<svg class="myRectangle" >
<linearGradient id="LinearGradientFill2" spreadMethod="pad" x1="0" x2="0" y1="1" y2="0">
<stop offset="0" stop-color="#f7f7f7"></stop>
<stop offset="0.266" stop-color="#ea0000"></stop>
<stop offset="0.7685" stop-color="#6c165f"></stop>
<stop offset="1" stop-color="#272020"></stop>
</linearGradient>
<rect id="rect" fill="url(#LinearGradientFill2)" rx="0" ry="0" x="0" y="0" width="150" height="100">
</rect>
<polyline stroke="green" points="0,1 0,0 "/>
</svg>
<div class="rectangle">
</div>
The above gives perfect result when dealing with a square shape. For a rectangular shape there is still some difference. Checking the formula ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With