Rect x and y properties not working in Firefox - css

I'm working with svgs and I have two "rect" elements. They have four css properties of width, height, x and y. It works fine on Chrome and Safari, but on Firefox the x and y properties don't show up. When I manually added them inside of the inspector there is a triangle with an exclamation point next to the x and y properties, which means it's not valid. I'm surprised by this because when I go to Mozilla developer website I can see that these are valid properties. Since the x and y are not valid according to the Firefox browser it's causing my SVG to not render. I'm not sure what I'm doing wrong. What is the workaround?
<button
class="button button--plusButton"
data-ng-click="plus.toggleState()"
data-ng-class="{'is-checked':plus.state}">
<svg viewBox="-7 9 24 24" xml:space="preserve">
<rect class="plusButton-topBar"/>
<rect class="plusButton-bottomBar"/>
</svg>
</button>
.plusButton-topBar {
x: 4px;
y: 16.5px;
width: 2px;
height: 9px;
}
.plusButton-bottomBar {
x: 0.5px;
y: 20px;
width: 9px;
height: 2px;
}
.plusButton-topBar, .plusButton-bottomBar {
fill: #656c75;
-webkit-transform: matrix(1, 0, 0, 1, 0, 0);
transform: matrix(1, 0, 0, 1, 0, 0);
transition: all 0.218s ease;
}

You have 2 issues here.
X and Y are not valid css properties.
Move them to inline attributes.
Your SVG element needs dimensions.
Add height and width.
button svg { /*add dimensions*/
height: 20px;
width: 20px;
}
.plusButton-topBar {
/*x: 4px;
y: 16.5px; Move these */
width: 2px;
height: 9px;
}
.plusButton-bottomBar {
/*x: 0.5px;
y: 20px; and these*/
width: 9px;
height: 2px;
}
.plusButton-topBar, .plusButton-bottomBar {
fill: #656c75;
-webkit-transform: matrix(1, 0, 0, 1, 0, 0);
transform: matrix(1, 0, 0, 1, 0, 0);
transition: all 0.218s ease;
}
<button class="button button--plusButton" data-ng-click="plus.toggleState()" data-ng-class="{'is-checked':plus.state}">
<svg viewBox="-7 9 24 24" xml:space="preserve">
<rect x="4" y="16.5" width="2" height="9" class="plusButton-topBar" />
<rect x="0.5" y="20" width="9" height="2" class="plusButton-bottomBar" />
</svg>
</button>
Just a thought...
You could use text rather than svg.
button{
color:#656c75;
font: 1.5em "arial";
}
<button
class="button button--plusButton"
data-ng-click="plus.toggleState()"
data-ng-class="{'is-checked':plus.state}">
+
</button>

Just a two guesses:
First, I think x and y aren't CSS properties but HTML attributes, so
you should include them inline in HTML tags.
Second, your CSS rules aren't wrapped by tag (I guess it's
just because you pasted two different parts of file here but just
making sure)

for modifying the x and y for a svg element via CSS, you can use
transform: translate(x,y) //to modify x and y axis
transform: translateX(x) //to modify only x axis
transform: translateY(y) //to modify only y axis

Related

Firefox 100: CSS 3D Transform rotateY(180deg) and SVG not playing well together

This may be a browser-bug relating to how Firefox Desktop 100.0.2. handles SVG and CSS Transforms.
Or else I'm doing something wrong to bring about this undesired effect.
I have a <button> containing two SVGs, one positioned on top of the other.
The SVG on the bottom is rotated 180 degrees (using transform: rotateY(180deg)) and invisible (using opacity: 0).
When the <button> is clicked, both SVGs rotate and at the halfway point in the rotation, the SVG on the bottom becomes visible and the SVG on the top becomes invisible.
The overall effect is that the <button> image rotates and transforms in the middle of its rotation.
Why is messing about with opacity necessary when we have backface-visibility?
Because iOS Safari doesn't support backface-visibility.
What's the issue?
The issue is that this isn't a clean rotation. The SVG which suddenly becomes visible turns into a blurry mess - like when the helicopter pilot in the original The Matrix is possessed by one of the agents - before settling into its new shape.
Click the button several times below to see this undesired effect in action. (I've slowed the transition down a little, so you have more time to see it in action.)
Working Example:
const audioButton = document.querySelector('.audioButton');
const audioOn = document.querySelector('.audio-on');
const audioOff = document.querySelector('.audio-off');
const toggleAudio = (e) => {
audioOn.classList.toggle('active');
audioOff.classList.toggle('active');
}
audioButton.addEventListener('click', toggleAudio, false);
.audioButton {
position: relative;
width: 52px;
height: 52px;
margin: 0 12px 0 0;
background-image: linear-gradient(hsl(219, 76%, 50%), hsl(219, 80%, 43%) 50%, hsl(219, 81%, 41%) 51%, hsl(219, 88%, 33%));
border: 2px solid hsl(220, 100%, 25%);
border-bottom: 2px solid hsl(220, 100%, 26%);
border-radius: 4px;
cursor: pointer;
}
.audioButton::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0);
}
.audioButton:hover::after {
background-color: rgba(0, 0, 0, 0.15);
}
.audioButtonVector {
position: absolute;
display: block;
top: 10%;
left: 10%;
width: 80%;
height: 80%;
opacity: 0;
pointer-events: none;
transform: rotateY(180deg);
transition: transform 1.2s linear, opacity 0s linear 0.6s;
}
.audio-off {
color: rgb(91, 127, 239);
}
.audio-on {
color: rgb(255, 255, 255);
}
.active {
opacity: 1;
transform: rotateY(0deg);
}
<button class="audioButton" type="button" title="Turn Audio On">
<svg xmlns="http://www.w3.org/2000/svg"
lang="en-GB"
class="audioButtonVector audio-off active"
viewBox="0 0 768 768">
<title>Mute Icon</title>
<defs><style><![CDATA[path {fill: currentColor;}]]></style></defs>
<path d="m 514.64857,746.41567 c -7.23403,-2.33279 -15.45533,-6.93789 -23.16845,-12.97761 -3.14331,-2.46136 -44.6698,-43.2877 -92.2811,-90.7252 l -86.56599,-86.25 h -67.29941 c -47.65888,0 -68.66895,-0.33827 -71.99223,-1.1591 -10.38521,-2.56509 -23.41546,-14.17469 -26.78831,-23.86766 -1.83792,-5.28188 -1.90451,-10.42057 -1.90451,-146.97324 v -141.5 l 2.89186,-6.2618 c 3.2572,-7.05289 8.40912,-12.23957 15.39549,-15.4994 2.59196,-1.20939 4.91571,-2.33594 5.16389,-2.50342 0.24818,-0.16749 -20.72025,-21.55146 -46.5965,-47.51995 -30.937231,-31.04751 -47.695971,-48.58514 -48.940811,-51.21543 -2.8746,-6.0739 -2.65973,-18.56296 0.42151,-24.500003 3.16419,-6.09687 8.64277,-11.63242 14.66456,-14.81707 4.20155,-2.222 6.27753,-2.64426 13.000001,-2.64426 6.74443,0 8.78473,0.4178 13,2.6621 3.65377,1.94535 22.6348,20.316143 70.49714,68.230673 l 65.49713,65.56856 h 31.48475 31.48474 l 89.51812,-89.32184 c 95.1437,-94.935093 95.62848,-95.37672 110.05601,-100.257898 6.53075,-2.209511 8.73786,-2.420265 25.34601,-2.420265 16.8774,0 18.51482,0.162627 22.65421,2.25 3.53889,1.784556 5.02413,3.387752 7.17979,7.75 l 2.71791,5.5 0.0321,248.502843 0.0321,248.50284 65.8925,65.88683 c 46.80175,46.79773 66.57555,67.22255 68.25005,70.49716 3.3554,6.56182 3.366,18.66705 0.022,25.11033 -3.1642,6.09686 -8.6428,11.63242 -14.6646,14.81707 -6.9012,3.64972 -18.7705,3.80022 -25.50001,0.32333 -3.02072,-1.5607 -19.21059,-17.00386 -49.25,-46.97853 l -44.75005,-44.65354 v 56.77796 c 0,62.53583 0.17139,60.72201 -6.27221,66.37956 -4.82954,4.24039 -10.80361,5.3457 -28.52701,5.27798 -11.68868,-0.0447 -15.93014,-0.4526 -20.70078,-1.99102 z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg"
lang="en-GB"
class="audioButtonVector audio-on"
viewBox="0 0 768 768">
<title>Audio Icon</title>
<defs><style><![CDATA[path {fill: currentColor;}]]></style></defs>
<path d="m 470.57734,741.2876 c -7.71475,-2.83606 -11.18777,-4.89195 -18.82603,-11.1443 -2.39807,-1.96296 -43.79807,-42.82236 -92,-90.79868 l -87.63988,-87.22967 -69.5,-0.27033 -69.5,-0.27033 -5.86156,-2.87813 c -8.69995,-4.27183 -19.79481,-15.53374 -22.7789,-23.12187 l -2.35954,-6 v -138 c 0,-131.11094 0.0914,-138.27456 1.83191,-143.5 4.32786,-12.99369 11.24782,-19.42452 26.95392,-25.04871 l 8.21417,-2.94141 66.47695,-0.005 66.47696,-0.005 90.52304,-90.2663 c 95.08695,-94.817141 94.44763,-94.232081 108.57699,-99.360761 5.97505,-2.16883 8.09265,-2.37282 24.63202,-2.37282 16.6968,0 18.4388,0.17171 22.54471,2.2223 2.44735,1.22227 5.35455,3.49301 6.46044,5.04609 4.95602,6.96009 4.73518,-9.62279 4.77327,358.416511 0.0249,240.3642 -0.28452,345.03405 -1.02571,347 -0.58374,1.54831 -2.49624,4.31599 -4.25,6.15042 -5.99091,6.26644 -7.33614,6.60106 -27.68867,6.88738 -18.04936,0.25392 -18.68352,0.19279 -26.03409,-2.50939 z M 600.3594,549.70163 c -5.93421,-2.20326 -10.33035,-6.14828 -13.14459,-11.79572 -5.39826,-10.83291 -3.08865,-16.71172 11.68289,-29.73724 40.36186,-35.59104 59.79177,-80.99428 57.38451,-134.09438 -2.23918,-49.39231 -20.58907,-87.5315 -58.17881,-120.9213 -12.02899,-10.68498 -14.65864,-14.55603 -14.65864,-21.5787 0,-11.90939 13.04063,-24.61151 23.75911,-23.14238 6.3213,0.86643 9.17103,2.59906 20.69094,12.58013 39.46289,34.19135 62.29527,76.84757 69.88539,130.56225 1.92863,13.64871 1.60428,48.41306 -0.58777,63 -5.75409,38.29032 -20.26693,71.24453 -44.36153,100.73141 -8.21433,10.05267 -30.26582,31.0853 -34.9257,33.312 -4.92676,2.35423 -12.81232,2.84138 -17.5458,1.08393 z" />
</svg>
</button>
Nota Bene:
I note that I if I change the transition from:
transition: transform 1.2s linear, opacity 0s linear 0.6s;
to:
transition: transform 1.2s linear, opacity 0.2s linear 0.5s;
the bizarre effect is minimised.
Using magic numbers like this, isn't an ideal compromise, I'll fall back to that if I can't get to the bottom of the issue.
A Significant Improvement:
I recalled some advice about sometimes needing to put different transitions on different elements. The updated version below is a clear improvement in that if you keep the mouse cursor hovered over the button after you click, the rotation is clean.
But if you move the mouse cursor off the button after clicking, the same messy effect is still visible.
Improved Working Example:
const audioButton = document.querySelector('.audioButton');
const audioOn = document.querySelector('.audio-on');
const audioOff = document.querySelector('.audio-off');
const toggleAudio = (e) => {
audioOn.classList.toggle('active');
audioOff.classList.toggle('active');
}
audioButton.addEventListener('click', toggleAudio, false);
.audioButton {
position: relative;
width: 52px;
height: 52px;
margin: 0 12px 0 0;
background-image: linear-gradient(hsl(219, 76%, 50%), hsl(219, 80%, 43%) 50%, hsl(219, 81%, 41%) 51%, hsl(219, 88%, 33%));
border: 2px solid hsl(220, 100%, 25%);
border-bottom: 2px solid hsl(220, 100%, 26%);
border-radius: 4px;
cursor: pointer;
}
.audioButton::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0);
}
.audioButton:hover::after {
background-color: rgba(0, 0, 0, 0.15);
}
.audioButtonVector {
position: absolute;
display: block;
top: 10%;
left: 10%;
width: 80%;
height: 80%;
transform: rotateY(180deg);
pointer-events: none;
transition: transform 0.6s linear;
}
.audioButtonVector.active {
transform: rotateY(0deg);
}
.audioButtonVector path {
opacity: 0;
transition: opacity 0s linear 0.3s;
}
.audioButtonVector.active path {
opacity: 1;
}
.audio-off {
color: rgb(91, 127, 239);
}
.audio-on {
color: rgb(255, 255, 255);
}
<button class="audioButton" type="button" title="Turn Audio On">
<svg xmlns="http://www.w3.org/2000/svg"
lang="en-GB"
class="audioButtonVector audio-off active"
viewBox="0 0 768 768">
<title>Mute Icon</title>
<defs><style><![CDATA[path {fill: currentColor;}]]></style></defs>
<path d="m 514.64857,746.41567 c -7.23403,-2.33279 -15.45533,-6.93789 -23.16845,-12.97761 -3.14331,-2.46136 -44.6698,-43.2877 -92.2811,-90.7252 l -86.56599,-86.25 h -67.29941 c -47.65888,0 -68.66895,-0.33827 -71.99223,-1.1591 -10.38521,-2.56509 -23.41546,-14.17469 -26.78831,-23.86766 -1.83792,-5.28188 -1.90451,-10.42057 -1.90451,-146.97324 v -141.5 l 2.89186,-6.2618 c 3.2572,-7.05289 8.40912,-12.23957 15.39549,-15.4994 2.59196,-1.20939 4.91571,-2.33594 5.16389,-2.50342 0.24818,-0.16749 -20.72025,-21.55146 -46.5965,-47.51995 -30.937231,-31.04751 -47.695971,-48.58514 -48.940811,-51.21543 -2.8746,-6.0739 -2.65973,-18.56296 0.42151,-24.500003 3.16419,-6.09687 8.64277,-11.63242 14.66456,-14.81707 4.20155,-2.222 6.27753,-2.64426 13.000001,-2.64426 6.74443,0 8.78473,0.4178 13,2.6621 3.65377,1.94535 22.6348,20.316143 70.49714,68.230673 l 65.49713,65.56856 h 31.48475 31.48474 l 89.51812,-89.32184 c 95.1437,-94.935093 95.62848,-95.37672 110.05601,-100.257898 6.53075,-2.209511 8.73786,-2.420265 25.34601,-2.420265 16.8774,0 18.51482,0.162627 22.65421,2.25 3.53889,1.784556 5.02413,3.387752 7.17979,7.75 l 2.71791,5.5 0.0321,248.502843 0.0321,248.50284 65.8925,65.88683 c 46.80175,46.79773 66.57555,67.22255 68.25005,70.49716 3.3554,6.56182 3.366,18.66705 0.022,25.11033 -3.1642,6.09686 -8.6428,11.63242 -14.6646,14.81707 -6.9012,3.64972 -18.7705,3.80022 -25.50001,0.32333 -3.02072,-1.5607 -19.21059,-17.00386 -49.25,-46.97853 l -44.75005,-44.65354 v 56.77796 c 0,62.53583 0.17139,60.72201 -6.27221,66.37956 -4.82954,4.24039 -10.80361,5.3457 -28.52701,5.27798 -11.68868,-0.0447 -15.93014,-0.4526 -20.70078,-1.99102 z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg"
lang="en-GB"
class="audioButtonVector audio-on"
viewBox="0 0 768 768">
<title>Audio Icon</title>
<defs><style><![CDATA[path {fill: currentColor;}]]></style></defs>
<path d="m 470.57734,741.2876 c -7.71475,-2.83606 -11.18777,-4.89195 -18.82603,-11.1443 -2.39807,-1.96296 -43.79807,-42.82236 -92,-90.79868 l -87.63988,-87.22967 -69.5,-0.27033 -69.5,-0.27033 -5.86156,-2.87813 c -8.69995,-4.27183 -19.79481,-15.53374 -22.7789,-23.12187 l -2.35954,-6 v -138 c 0,-131.11094 0.0914,-138.27456 1.83191,-143.5 4.32786,-12.99369 11.24782,-19.42452 26.95392,-25.04871 l 8.21417,-2.94141 66.47695,-0.005 66.47696,-0.005 90.52304,-90.2663 c 95.08695,-94.817141 94.44763,-94.232081 108.57699,-99.360761 5.97505,-2.16883 8.09265,-2.37282 24.63202,-2.37282 16.6968,0 18.4388,0.17171 22.54471,2.2223 2.44735,1.22227 5.35455,3.49301 6.46044,5.04609 4.95602,6.96009 4.73518,-9.62279 4.77327,358.416511 0.0249,240.3642 -0.28452,345.03405 -1.02571,347 -0.58374,1.54831 -2.49624,4.31599 -4.25,6.15042 -5.99091,6.26644 -7.33614,6.60106 -27.68867,6.88738 -18.04936,0.25392 -18.68352,0.19279 -26.03409,-2.50939 z M 600.3594,549.70163 c -5.93421,-2.20326 -10.33035,-6.14828 -13.14459,-11.79572 -5.39826,-10.83291 -3.08865,-16.71172 11.68289,-29.73724 40.36186,-35.59104 59.79177,-80.99428 57.38451,-134.09438 -2.23918,-49.39231 -20.58907,-87.5315 -58.17881,-120.9213 -12.02899,-10.68498 -14.65864,-14.55603 -14.65864,-21.5787 0,-11.90939 13.04063,-24.61151 23.75911,-23.14238 6.3213,0.86643 9.17103,2.59906 20.69094,12.58013 39.46289,34.19135 62.29527,76.84757 69.88539,130.56225 1.92863,13.64871 1.60428,48.41306 -0.58777,63 -5.75409,38.29032 -20.26693,71.24453 -44.36153,100.73141 -8.21433,10.05267 -30.26582,31.0853 -34.9257,33.312 -4.92676,2.35423 -12.81232,2.84138 -17.5458,1.08393 z" />
</svg>
</button>
No Further Improvement:
In the past I've seen issues in iOS Safari related to CSS 3D Rotations.
So I've replaced:
transform: rotateY(180deg)
transform: rotateY(0deg)
with:
transform: scale(-1, 1)
transform: scale(1, 1)
The minimal flicker that was previously visible in iOS Safari (I didn't mention this before - it's an unrelated issue) has now gone.
But the CSS update above hasn't made any significant difference to the undesired visual effect in Firefox Desktop.

Why SVG rotation was not centered?

I have a simple SVG image. There is a circle inside which I would like to rotate 90 degrees. But as you can see in JSFiddle example center of the rotation is not in the middle. What am I doing wrong?
svg {
background-color: #ddd;
}
.circle1 {
fill: none;
stroke-width: 20px;
stroke: #b5b5b5;
}
.circle2 {
fill: #aaa;
transform: rotate(-20deg);
stroke-width: 15px;
stroke: #71c7ff;
}
<svg height="600" width="600">
<circle class="circle1" cx="300" cy="300" r="200"></circle>
<circle class="circle2" cx="300" cy="300" r="200"></circle>
</svg>
Here is JSFiddle example https://jsfiddle.net/oxt681gr/1/
By default, the origin of a transform should be 0px 0px, but now we have wrong info on MDN:
By default, the origin of a transform is center.
Source-link
It is wrong. But in the case if it would be in center of your circle you would not able to see the result of your rotation because you will rotate the circle in his center.
You can change the rotation center with CSS property transform-origin or with SVG transform attribute. In SVG transform attribute we have the default also on 0px 0px. To rotate SVG (without CSS) use transform="rotate(deg, cx, cy)", where deg is the degree you want to rotate and (cx, cy) define the center of rotation.
In my solution you can change it interactive with CSS and JS:
var input = document.querySelector('input'),
circle2 = document.querySelector('.circle2'),
output = document.querySelector('span');
input.onchange = function(e)
{
var newTransformOrigin = e.target.value;
output.innerHTML = newTransformOrigin + 'px' + ' ' + newTransformOrigin + 'px';
circle2.style.transformOrigin = output.innerHTML;
};
svg {background-color:#ddd}
.circle1 {fill: none; stroke-width: 20px; stroke: #b5b5b5}
.circle2
{
fill: #aaa;
transform-origin: 0 0;
transform: rotate(-20deg);
stroke-width: 15px;
stroke: #71c7ff;
}
<p>Change transform-origin <input type="range" min="0" max="600" value="0" step="50">
<span>0px 0px</span></p>
<svg height="600" width="600">
<circle class="circle1" cx="300" cy="300" r="200"></circle>
<circle class="circle2" cx="300" cy="300" r="200"></circle>
</svg>
Please change to full page to see the example.

Trying to "transform: rotate()" a <circle> element using styled-components

CodeSandbox with example:
https://codesandbox.io/s/floral-surf-l7m0x
I'm trying to rotate 180ยบ a circle element inside an SVG. I'm being able to do it with the regular <circle> tag, but I'm not being able to do it with the styled component styled.circle
LS.Svg_SVG = styled.svg`
border: 1px dotted silver;
width: 100px;
height: 100px;
`;
LS.Circle_CIRCLE = styled.circle`
stroke-dasharray: 289.0272;
stroke-dashoffset: -144.5136;
transform: rotate(180 50 50); /* <------------ IT DOES NOT WORK */
`;
export default function App() {
return (
<React.Fragment>
<LS.Container_DIV>
<LS.Svg_SVG viewBox="100 100">
<circle /* USING REGULAR <circle> */
cx="50"
cy="50"
r="46"
stroke="black"
strokeWidth="8px"
fill="none"
strokeDasharray="289.0272"
strokeDashoffset="-144.5136"
transform="rotate(180 50 50)" /* <----------------- IT WORKS */
/>
</LS.Svg_SVG>
</LS.Container_DIV>
<LS.Container_DIV>
<LS.Svg_SVG viewBox="100 100">
<LS.Circle_CIRCLE /* USING STYLED COMPONENTS */
cx="50"
cy="50"
r="46"
stroke="black"
strokeWidth="8px"
fill="none"
/>
</LS.Svg_SVG>
</LS.Container_DIV>
</React.Fragment>
);
}
The result I'm getting:
They both should be the same. The first one is rotated (using regular <circle>). The second one is not rotated (using styled-components). Even though I'm setting transform: rotate(-180 50 50); in the styled component.
In CSS, units are required (ie. 180deg, 50px)
The SVG-specific version of rotate: rotate(angle, cx, cy), is not supported in the CSS version of transform. You'll need to use transform-origin.
LS.Circle_CIRCLE = styled.circle`
stroke-dasharray: 289.0272;
stroke-dashoffset: -144.5136;
transform: rotate(180deg);
transform-origin: 50px 50px;
`;

How to scale SVG path to fit the window size?

I am having troubles to scale the SVG to fit the window size.
In this example, I have a wavy path and a text element, what I want to achieve here is to move the text element along the wavy path from left to right (which is done by GSAP) and stop in the half way of the path in the initial load; it will move to the end when users start scrolling.
My problem is that, the wavy path created by SVG is too long, even the half way of the path will be off the window, I tried to scale down the wavy path by using viewBox, failed; using css width: 100vw, failed.
I also used the css transform property, it did scale the wavy path down, but that was a fixed size, I want to make it as responsive as possible, which means regardless the window width, the text element always stops in the middle of the screen first ( half way of the wavy path ), then moves to the right hand side of the screen. Is this possible when using inline SVG element? If so, please point me in the right direction.
Thank you in advance!
(Please view the example in full page mode, that will explain my problem perfectly, but the scroll function will be disabled because the height in that mode is 100vh, there is no room for scrolling)
document.getElementById("MyPath").setAttribute("d", document.getElementById("Path").getAttribute("d"));
var tl = new TimelineMax({
repeat: 0,
delay: 1
});
tl.to("#Text", 3, {
attr: {
startOffset: '50%',
opacity: 1
}
});
window.addEventListener('scroll', function() {
tl.to("#Text", 3, {
attr: {
startOffset: '100%',
opacity: 0
}
});
}, true);
#import url(https://fonts.googleapis.com/css?family=Oswald);
body {
background-color: #222;
}
svg {
overflow: visible;
width: 100%;
height: 100%;
background-color: #fff;
left: 0;
top: 0;
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/plugins/TextPlugin.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/TweenMax.min.js"></script>
<svg xml:space="preserve">
<defs><path id="MyPath"/></defs>
<path id="Path" fill="none" stroke="#000" stroke-miterlimit="10" d="M0,188.2c186.2,84,261.8,84.9,440,66.4s295.2-130,535.2-129.4c240,0.6,357,144.3,591.1,144.3
s450.1-141.2,651.1-141.2c271.7,0,354.2,141.2,612.1,141.2c240,0,423-141.2,669.1-141.2c119.1,0,202.3,33.8,281,68.7"/>
<text font-size="7em" >
<textPath id="Text" fill='#88CE02' font-family=Oswald xlink:href="#MyPath" opacity=0 startOffset="0%" letter-spacing="5px">Love the little things.</textPath>
</text>
</svg>
If you want your SVG to scale to fit the screen (or any parent container), it needs to have a viewBox attribute. This attribute tells the browser the dimensions of the SVG content. Without it, the browser has know way of knowing how much it needs to be scaled.
Your path is about 3780 width, and the bottom of it is at y=144. So a reasonable value of viewBox would be:
viewBox="0 0 3780 150"
document.getElementById("MyPath").setAttribute("d", document.getElementById("Path").getAttribute("d"));
var tl = new TimelineMax({
repeat: 0,
delay: 1
});
tl.to("#Text", 3, {
attr: {
startOffset: '50%',
opacity: 1
}
});
window.addEventListener('scroll', function() {
tl.to("#Text", 3, {
attr: {
startOffset: '100%',
opacity: 0
}
});
}, true);
#import url(https://fonts.googleapis.com/css?family=Oswald);
body {
background-color: #222;
}
svg {
overflow: visible;
width: 100%;
height: 100%;
background-color: #fff;
left: 0;
top: 0;
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/plugins/TextPlugin.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/TweenMax.min.js"></script>
<svg viewBox="0 0 3780 150" xml:space="preserve">
<defs><path id="MyPath"/></defs>
<path id="Path" fill="none" stroke="#000" stroke-miterlimit="10" d="M0,188.2c186.2,84,261.8,84.9,440,66.4s295.2-130,535.2-129.4c240,0.6,357,144.3,591.1,144.3
s450.1-141.2,651.1-141.2c271.7,0,354.2,141.2,612.1,141.2c240,0,423-141.2,669.1-141.2c119.1,0,202.3,33.8,281,68.7"/>
<text font-size="7em" >
<textPath id="Text" fill='#88CE02' font-family=Oswald xlink:href="#MyPath" opacity=0 startOffset="0%" letter-spacing="5px">Love the little things.</textPath>
</text>
</svg>
Here's what you could do: add a media query defining the desired width and then apply the following styles separately for the text and path elements inside the svg element:
text {
font-size: 2em;
}
path {
-webkit-transform: scale(.3);
-ms-transform: scale(.3);
transform: scale(.3);
}
See the snippet below:
document.getElementById("MyPath").setAttribute("d", document.getElementById("Path").getAttribute("d"));
var tl = new TimelineMax({
repeat: 0,
delay: 1
});
tl.to("#Text", 3, {
attr: {
startOffset: '50%',
opacity: 1
}
});
window.addEventListener('scroll', function() {
tl.to("#Text", 3, {
attr: {
startOffset: '100%',
opacity: 0
}
});
}, true);
#import url(https://fonts.googleapis.com/css?family=Oswald);
body {
background-color: #222;
}
svg {
overflow: visible;
width: 100%;
height: 100%;
background-color: #fff;
left: 0;
top: 0;
position: absolute;
}
#media only screen and (max-width: 500px) {
text {
font-size: 2em;
}
path {
-webkit-transform: scale(.3);
-ms-transform: scale(.3);
transform: scale(.3);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/plugins/TextPlugin.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/TweenMax.min.js"></script>
<svg xml:space="preserve">
<defs><path id="MyPath"/></defs>
<path id="Path" fill="none" stroke="#000" stroke-miterlimit="10" d="M0,188.2c186.2,84,261.8,84.9,440,66.4s295.2-130,535.2-129.4c240,0.6,357,144.3,591.1,144.3
s450.1-141.2,651.1-141.2c271.7,0,354.2,141.2,612.1,141.2c240,0,423-141.2,669.1-141.2c119.1,0,202.3,33.8,281,68.7"/>
<text font-size="7em" >
<textPath id="Text" fill='#88CE02' font-family=Oswald xlink:href="#MyPath" opacity=0 startOffset="0%" letter-spacing="5px">Love the little things.</textPath>
</text>
</svg>
I hope it helps!

Transition svg element with css

Problem
I'm trying to simply move an svg element using transform=matrix(a,b,c,d,e,f)
The element is moving fine but when I apply a css transition it has no effect.
Question
Is this possible on svg elements without an external library like d3?
Code I'm trying
html:
<svg width="100%" height="100%" viewbox="0 0 200 200">
<rect x="20" y="20" width="50" height="50"
style="fill: #3333cc"
transform="matrix(1,0,0,1,1,1)"
id="blueBox"
/>
</svg>
<button id="boxMover">
Move it
</button>
jQuery
$(function(){
$('#boxMover').click(function(){
var blueBox = $('#blueBox');
if(blueBox.attr('transform')=='matrix(1,0,0,1,1,1)'){
blueBox.attr('transform', 'matrix(1,0,0,1,100,30)');
} else {
blueBox.attr('transform', 'matrix(1,0,0,1,1,1)');
}
})
})
CSS
svg {
display: block
}
#boxMover {
position: absolute;
left: 20px;
top: 20px;
transition: transform .5s ease;
}
Here's a fiddle I created to test it
A simpler solution:
Create the following class:
.boxEase {
transform: matrix(1,0,0,1,100,30);
transition: all .5s ease;
}
Change your jQuery code to just attach the above class to your box when the button is clicked:
$(function(){
$('#boxMover').click(function(){
var blueBox = $('#blueBox');
blueBox.attr('class', 'boxEase');
})
})
Added dynamic case with variable ending (starting) positions
Use the following jQuery code where transform and transition properties are added to the box conditionally. I imagine you can adjust the conditional to something else but I have used your original example for this case:
`$(function(){
$('#boxMover').click(function(){
var startPos = 'matrix(1,0,0,1,1,1)',
endPos = 'matrix(1,0,0,1,100,30)';
var blueBox = $('#blueBox');
if(blueBox.attr('transform') == startPos){
blueBox.attr('transform', endPos);
blueBox.css({'transform': endPos, 'transition': 'all 0.5s ease'});
} else {
blueBox.attr('transform', startPos);
blueBox.css({'transform': startPos, 'transition': 'all 0.5s ease'});
}
})
}); `
There's a horrible grey area between the CSS and SVG namespaces where things like this happen all the time.
However, you can fix your problem as follows:
Move the transform CSS statement out of the #boxMover rules and put it somewhere it can actually affect the behaviour of your #blueBox SVG element.
Changing the transform attributes of the SVG element directly still won't work because you're talking to the SVG namespace, and the CSS rules aren't having any say in the matter. Instead, set up CSS classes containing the required transform attributes, and switch between those instead. There is no class attribute in the SVG namespace, so the CSS rules will come to life.
Also note that you can't use JQuery's addClass() and removeClass() methods to change the class of an SVG element, so use attr('class') instead
This should work:
$(function() {
$('#boxMover').click(function() {
var blueBox = $('#blueBox');
if (blueBox.attr('class') == 'overHere') {
blueBox.attr('class', 'overThere');
} else {
blueBox.attr('class', 'overHere');
}
})
})
svg {
display: block
}
#boxMover {
position: absolute;
left: 20px;
top: 20px;
}
#blueBox {
transition: transform .5s ease;
}
.overHere {
transform: matrix(1, 0, 0, 1, 1, 1);
}
.overThere {
transform: matrix(1, 0, 0, 1, 100, 30);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg width="100%" height="100%" viewbox="0 0 200 200">
<rect x="20" y="20" width="50" height="50"
style="fill: #3333cc" class="overHere" id="blueBox" />
</svg>
<button id="boxMover">
Move it
</button>

Resources