Horizontally repeating SVG pattern - html

Is it possible to emulate the following CSS in an SVG fill?
background-image: url(/* URL */);
background-position: 50%;
background-size: auto 100%;
background-repeat: repeat-x;
i.e. A background image that has its aspect ratio preserved, has the same height as its container, is centred, and repeats horizontally. This JSBin demonstrates the behaviour I'm trying to implement, using an animation to show how the background responds to height changes.

It's awkward, to say the least, and it is far from perfect. As the outermost element, I have set a html <div> element, but it could also be a <svg> element. The key point is to remember that you need an inner <svg> with overflow: visible, and an outer element with overflow: hidden (which would be the default for an <svg> element.
#keyframes shrink {
0% { height: 200px; }
100% { height: 50px; }
}
div {
animation: 2s ease-in-out 0s infinite alternate shrink;
border: 1px solid #000;
height: 200px;
width: 200px;
overflow: hidden;
}
<div>
<svg width="100%" height="100%" viewBox="-0.675 0 0.1 1"
preserveAspectRatio="xMidYMid meet" overflow="visible">
<pattern id="p1" viewBox="0 0 100 80" height="1" width="1.25"
patternUnits="userSpaceOnUse">
<image xlink:href="http://static.jsbin.com/images/dave.min.svg"
width="100" height="80" />
<rect width="100" height="80" fill="none" stroke="brown" />
</pattern>
<rect fill="url(#p1)" x="-500" y="0" width="1000" height="1" />
</svg>
</div>
The repetitions are not conceptually endless, but merely very long - I've set 1000 / 1.
If the container is higher than wide in respect to the aspect ratio of the svg viewBox, the image will only scale so far that the viewBox still fits inside. This is due to the meet keyword being always applied for both directions. Therefore, the viewBox width needs to be small - I've set 1 / 10.
The size of the image needs to be known in advance, and it must be used in four places:
The <image> width and height must be explicitely set, SVG has no notion of "natural size".
The <pattern> viewBox attribute must be set to the image size. I've added a rectangle to illustrate the image borders.
While the pattern height attribute always needs to be 1, the width has to be set to the correct apect ratio.
If the viewBox on the on the inner <svg> has a value of "x 0 ws 1", and wp is the pattern width, then x = -(wp/2 + ws) - for my example, ws=0.1, wp=1.25 => x=-0.675.

Related

Best way to create a div with a full-width slanted line going up

UPDATE: I had previously found a way to accomplish this using CSS, but the slope of the line is jagged and the aspect ratio of the triangle is not consistent for all widths. Here's a Codepen of that solution.
How can I create the effect where the top of the footer slopes upward? Most footers have a simple straight horizontal line along the top of the footer div, but I need to create an effect where the line slopes upward. Here are some different approaches:
PNG image with transparency.
CSS only
SVG
I prefer not to use a PNG image and tried using straight CSS and am now trying it using SVG. The height of the triangular shape should be no more that 200 pixels at the full width of 1440 pixels.
.main {
background: #ccc;
}
.right-triangle {
display: block;
}
.footer {
background: #333;
color: #fff;
}
<div class="main">End of main section be flush with the div below.</div>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" class="right-triangle">
<polygon points="50 25, 100 100, 0 100" />
</svg>
<div class="footer">
Next section needs to be flush with the triangle with no gap in between.
</div>
The code below should do what you want. The key is to set the height and width separately and NOT preserve the aspect ratio for the SVG.
You might need to play with values in the max function to get the narrow screen versus wide screen effects you want. And/or, change max-height to height.
CSS
.main {
background: #ccc;
}
.right-triangle {
display: block;
width: 100%;
max-height: max(20px, calc(200vw / 1440 ));
}
.footer {
background: #333; color: #fff;
}
HTML
<div class="main">
End of main section be flush with the div below.</div>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"
class="right-triangle"
preserveAspectRatio="none">
<polygon points="100 0, 100 100, 0 100" />
</svg>
<div class="footer">
Next section needs to be flush with the triangle with no gap in between.
</div>
(I am on a mobile phone, so, sorry but it is bit difficult posting this how I would like to.)

How to give strokes a specific width based on base64

i'm trying to build a stroked line, based on a svg file, cause of the color and the corner shapes that it has. Each stroke is 15px wide and has a gap between each line from also 15px. The problem is that when i try to include it via background-image it always makes the line longer than it actually should be.
.stroke-dotted {
background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTVweCIgaGVpZ2h0PSI0cHgiIHZpZXdCb3g9IjAgMCAxNSA0IiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgogICAgPGcgaWQ9IldlYnNpdGUiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJEZXNrdG9wIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTQyLjAwMDAwMCwgLTE5NDAuMDAwMDAwKSIgc3Ryb2tlPSIjMTZDREM3IiBzdHJva2Utd2lkdGg9IjMiPgogICAgICAgICAgICA8ZyBpZD0iU2VydmljZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsIDE0ODguMDAwMDAwKSI+CiAgICAgICAgICAgICAgICA8ZyBpZD0iV2ViZGVzaWduIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg2MC4wMDAwMDAsIDQzOC4wMDAwMDApIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNODIsMTYgTDk3LDE2IiBpZD0ibGluZSI+PC9wYXRoPgogICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICA8L2c+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4=);
width: 100%;
background-repeat: repeat-x;
}
<div class="stroke-dotted"></div>
Thats how it should look like:
And that's how it looks now:
Is there a way to give the lines a specific width of 15px and also an gap of 15px? I also tried to fix it with the background-size attribute, but it didn't worked out.
First things first: don't encode your SVG as a base64, it is much longer than the original code and its unnecessary as you can just add the code to the url. You might need to URL encode it for IE11 and earlier, but otherwise all browsers support it.
Now, to control your sizing in SVG tags, ommit the viewBox and simply give it a width and height of 100% and express all other values in percentage. Now you can control the size of the line by defining its pixel size, even though the points are defined in percentage:
div {
position: absolute;
width: 100%;
height: 100%;
left: 0%;
top: 0%;
background: url('data:image/svg+xml;charset=utf8,<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">\
<line x1="0%" y1="50%" x2="100%" y2="50%" stroke="cyan" stroke-width="1px" stroke-dasharray="15px 15px" />\
</svg>') no-repeat 50% 50% / cover;
}
body {
/* A reference grid */
background: url('data:image/svg+xml;charset=utf8,<svg width="15px" height="15px" xmlns="http://www.w3.org/2000/svg">\
<rect x="0" y="0" width="100%" height="100%" stroke="#222" stroke-width="1px" fill="black" />\
</svg>');
}
<div></div>
Once your SVG is correctly set up, it is as simple as defining the stroke-dasharray property with the pixel values:
<line x1="0%" y1="50%" x2="100%" y2="50%" stroke="black" stroke-width="1px" stroke-dasharray="15px 15px" />
Now you can use CSS to change your box, or even SVG to change the offsets within the SVG background.

HTML/CSS svg auto height & width

Is there a way to make the svg automatically scale to the size of the circle inside it? Something like or something. At the moment I give the svg a size, and the circle a size. Which causes them to not match (and I don't want to manually try and match both every time).
See how the blue background is bigger than the circle. I know I can just change the height and width, but it would be nice to have this change according to the circle size. I only want to change one element, not match both.
.divOrangeCircles {
display: inline-block;
background-color: aqua;
opacity: 0.5;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/styles.css">
</head>
<body>
<div class="divOrangeCircles"><svg height="200" width="200"><circle cx="90" cy="90" r="90" fill="#F48043"/></svg></div>
</body>
</html>
What you want is the viewBox='x y width height' attribute, which will define the view-box of your SVG drawings.
SVG units are (generally) relative to their parent's box, by setting the viewBox attribute, you define how much of this units your SVG should display.
.divOrangeCircles {
display: inline-block;
background-color: aqua;
opacity: 0.5;
}
svg {
display: block;
}
<div class="divOrangeCircles">
<svg viewBox="0 0 180 180" height="200" width="200">
<circle cx="90" cy="90" r="90" fill="#F48043"/>
</svg>
</div>
If you want to svg scale according to parent div then use this code. Don't be add manually dimensions in percentage.
.divOrangeCircles svg{
width: 100%;
height: 100%;
}
Give your cx, cy and r should be in percentages in order to modify according to the Parent svg size.
Sample Fiddle
For controlling sizes from css u can make svg height and width as 100% and give size from css.
<div class="divOrangeCircles"><svg height="100%" width="100%"><circle cx="50%" cy="50%" r="50%" fill="#F48043"/></svg></div>
Updated Fiddle
Help :)

Svg and div issue

I have a svg image that doesn't fit into my div. When I re-size my svg the div doesn't re-size to fit the svg. The svg should be at max size 700px and then re-size down as browser window re-sizes. I had it working with another element in Div1 that stretched the div1 to max-width:700px, but as I deleted that element it stopped working.
I removed the fiddle, since the issue is resolved.
If you have an svg image it will grow as large as its container allows.
This is both in width and height.
So if the svg element looks like this: <svg height="100%" width="100%">
It will scale up until to its container size.
I use css to modify how to control its size:
.svg-class { //put this class on your svg element
width: 100%;
}
So as long as there is room in the parent containers it will grow. Now we want to limit it to 700px: Just add max-width: 700px to the size control:
.svg-class {
width: 100%;
max-width: 700px;
}
Now it will only grow until 700px width. Even if the container is bigger.
body {
margin: 0;
}
.top {
background-color: black;
}
.sprite {
max-width: 700px;
width: 100%;
}
<div class="top">
<svg class="sprite" viewBox="0 0 100 100">
<rect x="0" y="0" width="50" height="50" fill="red" />
<rect x="50" y="0" width="50" height="50" fill="yellow" />
<rect x="0" y="50" width="50" height="50" fill="green" />
<rect x="50" y="50" width="50" height="50" fill="blue" />
</svg>
</div>
I found the answer. I added image tags around the svg and set the width. Works now.

How to get ScrollBars in SVG?

I have a SVG-element with a lot of elements inside. The SVG-element has a viewbox, so you can press a zoom-button and the elements appear bigger or smaller. Works well. Now the problem is, when the elements overflow the parent SVG-element no ScrollBars appear.
Example:
<div width="100%" height="100%">
<svg height="100%" width="100%" style="overflow-x: auto; overflow-y: auto; "viewBox="0 0 793 1122">
<g>
...
<line y2="44.9792mm" y1="44.9792mm" x1="197.203mm" x2="12.7028mm"></line>
<line y2="44.9792mm" y1="44.9792mm" x1="197.203mm" x2="12.7028mm"></line>
<text x="43.4516mm" y="52.9167mm" style="font-size: 11pt;">S</text>
<rect x="0" width="210mm" y="0" height="297mm"></rect>
...
</g>
</svg>
</div>
//here I set the viewbox after clicking the zoomOut-Button
float width = svg.getViewBox().getBaseVal().getWidth();
float height = svg.getViewBox().getBaseVal().getHeight();
svg.getViewBox().getBaseVal().setHeight((float) (height / 0.9));
svg.getViewBox().getBaseVal().setWidth((float) (width / 0.9));
Can someone help me?
I put the overflow attribut in the svg and also in the div tag. doesn't work.
Try making the SVG element bigger than the div, and let the div handle the overflow using scroll.
For example, see this jsfiddle, which utilizes the following css:
div#container {
height: 400px;
width: 400px;
border:2px solid #000;
overflow: scroll;
}
svg#sky {
height: 100px;
width: 1100px;
border:1px dotted #ccc;
background-color: #ccc;
}
Part of the point of SVG is so that it can scale to fit the screen. However, I think if you want to get something like what you are describing, then you need to set explicit width and height to the svg element. Something like http://jsfiddle.net/qTFxJ/13/ where I set the width and height in pixels to match your viewBox size.