Translate a SVG element relative to right of screen? - css

Is it possible to translate a SVG element relative to the right of the screen as opposed to the top left that is it's default?
<svg class="svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<text id="text" class="svgText">test text test text</text>
<rect id="border" class="textOutlineBox" x="0" y="0" width="440.5" height="90"/>
</svg>
#text, #border {
transform-origin: right center;
}
#text {
transform: translate(15vw, 20vh);
}
#border {
transform: translate(10vw, 10vh);
}
When I do this it still moves from the left of the screen. Is there a way to get it to transform relative to the right side of the screen?
jsFiddle describing my problem here!

When you use CSS translate (or translateX or translateY), you don't translate the element relative to the edge of the screen, but relative to where the element would be on the screen, were it not translated.
So if you want to move a SVG rect leftwards from the right of the screen, you first need to position it somewhere near to the right edge of the screen.
One way to do this might be to:
Give the <svg> element a viewBox so you have a parental width to work with
Subtract the width of the element from the width of the viewBox
Apply the value from 2. as the element's x value.
Now, with the rect over towards the right hand edge of the screen, you can translate it leftwards, by giving it a negative translateX value.
Working Example:
body {
margin: 0;
}
svg {
width: 99vw;
border: 1px solid gray;
}
#border {
transform: translate(-10vw, 10vh);
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1000 200">
<rect id="border" x="559.5" y="0" width="440.5" height="90" />
</svg>

Related

How to scale svg size to exactly wrap its content?

I have a very simple svg with a circle inside:
<div>
<svg className="main-svg">
<circle pathLength="25" cx="50%" cy="50%" r="25%" />
</svg>
</div>
Then if I style it:
svg {
height: 250px;
width: 250px;
}
The svg will take up 250px width and height, but the circle inside it will be much smaller, so there's unwanted white space around the circle. Is it possible to make the svg wrap the circle without adding space, so that defining the width of height of the svg will result in setting the width and height of the circle inside it?
Stackblitz link: https://stackblitz.com/edit/react-ts-fwmjzn?file=style.css
Set radius attribute value to 50%
svg {border: 2px solid red; }
<svg width="250" height="250" viewBox="0 0 250 250">
<circle pathLength="25" cx="50%" cy="50%" r="50%" />
</svg>

Making a smooth Sinusoidal wave with CSS animation and SVG worknig for someone elses SVG but not mine?

Animation of the problem (theirs vs mine). More context below:
I have gotten some code off of JSFiddle and it is as follows:
HTML:
<article id="main">
<div class="ocean">
<div class="wave"></div>
</div>
</article>
CSS:
.ocean {
height: 5%;
width:100%;
position:absolute;
bottom:0;
left:0;
background: #015871;
}
.wave {
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/85486/wave.svg) repeat-x;
position: absolute;
width: 6400px;
top:-198px;
height:198px;
animation: wave 2s linear infinite;
}
#keyframes wave {
100% {
margin-left: -1600px;
}
}
article{
width:100%;
height:100vh;
}
Now with me, I have the exact same code, but I changed out the source to an svg that I made by changing the 'background' attribute in the '.wave' class as follows:
background: url("...\my_svg.svg");
Then this is the code for that SVG:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 65">
<defs>
<style>.cls-1{stroke:#000;stroke-miterlimit:10;}</style>
</defs>
<title>bkg-side</title>
<g id="Layer_1" data-name="Layer 1">
<path class="cls-1" d="M1600.3,58.38c-64.8,0-177.4-9.65-400-28.94S866.52.5,800.4.5C735.6.5,623,10.15,400.45,29.44S66.62,58.38.5,58.38v6.89l1600,.23"/>
</g>
</svg>
Now as you'll see, there is a smooth transition for the svg that I am using and a not-so-smooth transition with the SVG that I made. Theirs will scroll infinitely to the side or at least look like it is while mine will 'reset' after the set amount of time for the animation (in this case, 5 seconds). The only difference in code is which SVG is being used and I have no idea why their SVG will scroll to the side infinitely and look like a smooth curve, while with mine, it resets and gets choppy every 5 seconds. Does it have something to do with the SVG code in of itself?
EDIT: the ends DO touch each other forming a consistent curve with both images, and I have put my image in the top left corner of Illustrator and hit 'Export Selection...'. The consistancy is there, but with this one, the wave goes on without resetting while mine DOES reset from the beginning.
It's because your wave is in the middle of a large SVG, with space all around it. Whereas theirs occupies the full width of the SVG.
When you repeat-x theirs, the left and right edges of each repeat meet up. Yours have large gaps on the left and right.
You need to move your wave shape to the left edge of the SVG and trim the page size to match the width.
Based on Paul's comment, and by comparing the svg files, I found that THEIR svg didn't have a viewbox attribute and had a width attribute, while mine DID have a viewbox attribute and didn't have a width attribute. I set the with to be the value of the margin-left value in the #key-frames animation and presto!
My old svg:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 65">
<defs>
<style>.cls-1{stroke:#000;stroke-miterlimit:10;}</style>
</defs>
<title>bkg-side</title>
<g id="Layer_1" data-name="Layer 1">
<path class="cls-1" d="M1600.3,58.38c-64.8,0-177.4-9.65-400-28.94S866.52.5,800.4.5C735.6.5,623,10.15,400.45,29.44S66.62,58.38.5,58.38v6.89l1600,.23"/>
</g>
</svg>
My new svg:
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="66">
<defs>
<style>.cls-1{stroke:#000;stroke-miterlimit:10;}</style>
</defs>
<title>bkg-side</title>
<g id="Layer_1" data-name="Layer 1">
<path class="cls-1" d="M1600.3,58.38c-64.8,0-177.4-9.65-400-28.94S866.52.5,800.4.5C735.6.5,623,10.15,400.45,29.44S66.62,58.38.5,58.38v6.89l1600,.23"/>
</g>
</svg>

Use part of CSS-Sprite as repeated background image

I have a div with a width and height of approximately 300px each. The background of this div should be filled repeatedly with a smaller image of 8px width and 8px height. This smaller image is embedded into a larger sprite image. How can I only use this 8x8 pixel tile to pave the background?
What I've tried so far:
.world {
width: 300px;
height: 300px;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4wcYFjsX3EPV0QAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAxklEQVQ4y+2UsQ3CMBBF/0VImYDKFWNQZB28AwOwQ7KOC8agomKCVJ8ituU7GwkhVxFXWT+nF8nvy0JSRFAMye0wqRghxrheTmV+Wx4A9G7BmlpfAi0lswZ0mj2DsiNjLbBx09lRw1oN+m0OAKB7hIQWvFSM43ZY5V7mI88AhB+KZCiZZSiZ9e/RN6BaP1k6MtY2Ry1rPXv01D1yET3qR2ZF+qXX+zMBDJaSuGP1VMXEV/te9q6/G8hV+h2VI2NtrvZn9uzRGzl9Uzsn2uDrAAAAAElFTkSuQmCC') 0 -16px repeat;
}
<div class="world"></div>
In this example code, the shritesheet has a width and height of 24px each. It contains 9 differently coloured points, each of which has a diameter of 7px.
I want that only one single point is used repeatedly as background for the div. However, in this code, the whole picture is repeated instead beginning at the third row of points.
Note, this exemplary spritesheet is only an example. The actual spritesheet is a little more complicated. Replacing the spritesheet
with CSS code is not a solution.
One idea is to consider SVG as background. The trick is to make the image inside the SVG and rely on viewbox to cut the image and show only the needed part then make the whole SVG a pattern for your background.
Simply edit the viewBox to select the pattern you want (x y 8 8 where x,y are equal to [0,8,16])
.box {
width: 100px;
height: 100px;
display:inline-block;
}
.one {
background: url('data:image/svg+xml;utf8,<svg viewBox="16 0 8 8" width="8" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><image xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4wcYFjsX3EPV0QAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAxklEQVQ4y+2UsQ3CMBBF/0VImYDKFWNQZB28AwOwQ7KOC8agomKCVJ8ituU7GwkhVxFXWT+nF8nvy0JSRFAMye0wqRghxrheTmV+Wx4A9G7BmlpfAi0lswZ0mj2DsiNjLbBx09lRw1oN+m0OAKB7hIQWvFSM43ZY5V7mI88AhB+KZCiZZSiZ9e/RN6BaP1k6MtY2Ry1rPXv01D1yET3qR2ZF+qXX+zMBDJaSuGP1VMXEV/te9q6/G8hV+h2VI2NtrvZn9uzRGzl9Uzsn2uDrAAAAAElFTkSuQmCC" x="0" y="0" height="24" width="24" /></svg>') repeat;
}
.two {
background: url('data:image/svg+xml;utf8,<svg viewBox="16 8 8 8" width="8" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><image xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4wcYFjsX3EPV0QAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAxklEQVQ4y+2UsQ3CMBBF/0VImYDKFWNQZB28AwOwQ7KOC8agomKCVJ8ituU7GwkhVxFXWT+nF8nvy0JSRFAMye0wqRghxrheTmV+Wx4A9G7BmlpfAi0lswZ0mj2DsiNjLbBx09lRw1oN+m0OAKB7hIQWvFSM43ZY5V7mI88AhB+KZCiZZSiZ9e/RN6BaP1k6MtY2Ry1rPXv01D1yET3qR2ZF+qXX+zMBDJaSuGP1VMXEV/te9q6/G8hV+h2VI2NtrvZn9uzRGzl9Uzsn2uDrAAAAAElFTkSuQmCC" x="0" y="0" height="24" width="24" /></svg>') repeat;
}
.three {
background: url('data:image/svg+xml;utf8,<svg viewBox="8 0 8 8" width="8" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><image xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4wcYFjsX3EPV0QAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAxklEQVQ4y+2UsQ3CMBBF/0VImYDKFWNQZB28AwOwQ7KOC8agomKCVJ8ituU7GwkhVxFXWT+nF8nvy0JSRFAMye0wqRghxrheTmV+Wx4A9G7BmlpfAi0lswZ0mj2DsiNjLbBx09lRw1oN+m0OAKB7hIQWvFSM43ZY5V7mI88AhB+KZCiZZSiZ9e/RN6BaP1k6MtY2Ry1rPXv01D1yET3qR2ZF+qXX+zMBDJaSuGP1VMXEV/te9q6/G8hV+h2VI2NtrvZn9uzRGzl9Uzsn2uDrAAAAAElFTkSuQmCC" x="0" y="0" height="24" width="24" /></svg>') repeat;
}
<div class="box one"></div>
<div class="box two"></div>
<div class="box three"></div>

How to make an svg element responsive to it's parent container?

I'm trying to acheive this:
Rendering an svg square (w:h = 1:1 rectangular) inside of div,
when the div's width is greater than height, the square should fit into the container by the height(red box is the div, green box is the svg square):
When the div's height is greater than width, the squire should fit into the container by the width:
It can be easily achieved by specifying the size of the svg view port.But if I remove the size of the svg view port, instead when I add the size to the parent div(red box), it refuses to look at the height of the container, the image turns to be:
Is there a way we can make the square responsive to the container height?
here is my code:
#main {
width: 400px;
height: 100px;
border: 4px solid red;
}
<div id="main">
<svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid Meet">
<rect x="0" y="0" width="100" height="100" fill="green"/>
</svg>
</div>
Just set the width and height attributes of the SVG to "100%". Either in the SVG, or via CSS.
Secondly, fix your other attributes:
viewBox values should not have commas.
it is preserveAspectRatio, not preserveAspect, and meet, not Meet
#main {
width: 400px;
height: 100px;
border: 4px solid red;
}
<div id="main">
<svg width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet">
<rect x="0" y="0" width="100" height="100" fill="green"/>
</svg>
</div>

Targeting Inline SVG from stylesheet

I'm surprised to be having this problem, but there must be some funniness about SVG + CSS I'm not quite getting.
Short version, this doesn't work:
HTML
<div class="svg-container>
<svg class="mybox">...</svg>
</div>
CSS from stylesheet
.mybox { max-height: 150px; }
Long version
I have some SVG "widgets", some which are 2:1 width:height ratio, others which are 1:1 width:height, and need the flexibility for anything between and beyond.
The "widgets" will be shown in a gallery, each item having a width of 318px and a height of 150px.
However, the gallery is not the only (or even primary) display of these "widgets", they will be used elsewhere, and need to scale, so adding an inline SVG style block of max-height: 150px is not an option. Each SVG is sitting in a container, 'svg-container'.
Repeat: Inline SVG styles are not an option. SVG itself probably has to be inline, as we're passing data to the SVG, so linking to the SVG as an image, etc, not an option.
Here is a CodePen (yes, it's ugly, proof of concept)
Note: the arrow inside resizes to the max-height of 150px, however, the SVG loses its aspect ratio, as you can see from the border.
The trick was to set an height on the .svg-container. This implies that the height of the SVG element is 25vw (viewport width unit) but not more than 150px at max. Since the height of the element is now known, the width is set based on the viewBox specified on the SVG. The actual value (25vw in this case) is just a random value and can be modified as necessary.
The text-align: center on the container (as you would have guessed) is to center the SVG element horizontally within the container.
.svg-container {
text-align: center;
height: 25vw;
/* This is the key. I have used vw units for responsiveness */
margin-bottom: 10px;
border: 1px solid;
}
.mybox {
max-height: 150px;
height: 100%;
}
<div class="svg-container">
<svg class="mybox" style="border: solid" x="0" y="0" viewBox="0, 0, 500, 500">
<polygon fill="orange" points="256,512 512,256 352,256 352,0.001 160,0 160,256 0,256 "></polygon>
<text text-anchor="middle" x="250" y="250" style="font-size: 100px;" stroke="black" fill="black">000</text>
</svg>
</div>
<div class="svg-container">
<svg class="mybox" style="border: solid" x="0" y="0" viewBox="0, 0, 250, 500">
<polygon fill="orange" points="128,512 256,256 176,256 176,0.001 80,0 80,256 0,256 "></polygon>
<text text-anchor="middle" x="125" y="250" style="font-size: 50px;" stroke="black" fill="black">000</text>
</svg>
</div>

Resources