Adding svg shapes and lines to a SVG clipped div - html

First: the stuff I'm trying to do is not compatible with chrome for the time being. Please use firefox to check the examples.
Here is what I've done:
http://jsfiddle.net/Robodude/ev6VF/1/
<style type="text/css">
.clip3 {
clip-path: url(#c3);
}
</style>
<svg height="0">
<defs>
</defs>
<clipPath id="c3">
<polygon points="75,0 225,0 275,100 225,200 75,200 25,100" />
</clipPath>
</svg>
<div class="container left">
<div id="Image1" class="Image1 image clip3"></div>
<div id="Image2" class="Image2 image clip3"></div>
<div id="Image3" class="Image3 image clip3"></div>
</div>
What I would like to do, is draw on top of the html elements that were clipped in order to draw some accents and borders to the cut images as seen below via ms paint. Is this possible with SVG? Perhaps I can add another property to .clip3 and link it to some svg shapes somehow?
I'm trying out lots of different things - but they are just guesses and I can't find any resources or info on how to do this.
How I had hoped it would work was something like this:
<style type="text/css">
.clip3 {
clip-path: url(#c3);
border: url(#b1);
}
</style>
<defs>
<polyline id = "b1" points="75,0 225,0 275,100 225,200 75,200 25,100" stroke = "blue" stroke-width = "5"/>
</defs>

Came up with an idea that I don't consider ideal but it works... =\
http://jsfiddle.net/Robodude/ev6VF/4/
<svg height="0">
<clipPath id="c3">
<polygon points="75,0 225,0 275,100 225,200 75,200 25,100"/>
</clipPath>
<defs>
<polyline id="top" points="225,200 75,200 25,100" style="fill:none;stroke:blue;stroke-width:10" />
<polyline id="middle" points="225,0 275,100 225,200" style="fill:none;stroke:blue;stroke-width:10" />
<polyline id="bottom" points="25,100 75,0 225,0" style="fill:none;stroke:blue;stroke-width:10" />
</defs>
</svg>
<div class="container left">
<div id="Image1" class="Image1 image clip3">
<svg width="100%" height="100%">
<use xlink:href = "#top"/>
</svg>
</div>
<div id="Image2" class="Image2 image clip3">
<svg width="100%" height="100%">
<use xlink:href = "#middle"/>
</svg>
</div>
<div id="Image3" class="Image3 image clip3">
<svg width="100%" height="100%">
<use xlink:href = "#bottom"/>
</svg>
</div>
</div>

Related

resize svg wrapped in div that is wrapped in div

I'm having a problem coverting inline SVG to be wrapped in divs. I was using nested SVGs before and now I'm told I have to use nested divs with inline SVG.
Basically, I need the SVG to be sized to the "container" - the "container" is size to the browser window.
For an example of what works before I tried the whole div thing:
SVG Only Example - works perfectly
<html>
<body>
<svg id="container" style="position:relative;border:dashed;width:100%;height:100%;" viewBox="0 0 1000 500">
<svg id="background" name="Box" x="0" y="0">
<rect width="1000" height="500" stroke="lime" fill="blue" stroke-width="10" />
<svg id="shape" name="Triangle" x="275" y="50" fill="red" stroke="yellow" stroke-width="3">
<path d="M0,378L185,0L371,378Z" />
</svg>
</svg>
</svg>
</body>
</html>
But when I try to wrap divs around them, it just stays the same size as my viewBox, no matter what I've tried. I've looked up a lot on this on SO and elsewhere and nothing seems to work: padding tricks, 100vw, width, height, etc.
Here's the latest of what I've tried:
SVG wrapped in DIV Example - doesn't behave the same
<html>
<body>
<div id="container" style="position:relative;border:dashed;width:100%;height:0;margin:5px">
<div id="background" style="position:absolute;left:0px;top:0px;width:1000px;height:500px;">
<svg name="Box" viewBox="0 0 1000 500">
<rect width="1000" height="500" stroke="lime" fill="blue" stroke-width="10" />
</svg>
<div id="shape" style="position:absolute;left:275px;top:50px;width:371px;height:378px;">
<svg name="Triangle" viewBox="0 0 371 378" fill="red" stroke="yellow" stroke-width="3">
<path d="M0,378L185,0L371,378Z" />
</svg>
</div>
</div>
</div>
</body>
</html>
I put a "border:dashed;" in the first div, just to make sure it is resizing with the browswer window and it is. It's just that everything inside that div doesn't change.
Any advice on how to get the "wrapped in div" strategy to match the "plain SVG" strategy?
More clarity:
I guess what I'm saying is that "background" shape needs to be 1000w x 500h, relative to the "container" size. Any of it's children need to be absolutely positioned inside of that 1000w 500h and relative to it. The "container" size is the available space. So if if the browser window is 3000w x 2000h, then technically the "background" shape should be 3000w x 1500h (and the child shapes resize accordingly too - but the stay in their original relative position - relative to 1000w x 500h). If the window 800 w by 600 h, the "background" and child shapes shrink to fit that, relatively. Just like the SVG example.
It might be helpful to take the SVG example above, save it as an html file, launch locally and resize your browser up and down. That's what I'm to find help with, but divs don't seem to know how to handle this.
There's no real equivalent to viewBox property of SVG on DIV elements. The closest one would transform scale. So if you give your div containers a specific size in pixel without adjusting on resize, you're going to somewhat override the viewbox calculations.
That being said, if your div containers are resized with the window, then it can work. Also with minimal javascript you can get the same result as viewbox.
For the css only solution, you define your div containers so they are 100% the size of the window. The SVG viewbox is then still making the calculations. You'll need to define a preserveAspectRatio to have the same behavior as your SVG example. Like this:
html, body {
width: 100%;
height: 100%;
padding: 0px;
margin:0px;
}
* {
box-sizing: border-box;
}
<div id="container" style="position:relative;border:dashed;width:100%;height:100%;">
<svg name="Box" style="position:relative;width:100%;height:100%;" viewBox="0 0 1000 500" preserveAspectRatio="xMinYMin">
<rect width="100%" height="100%" stroke="lime" fill="blue" stroke-width="10" />
</svg>
<div id="shape" style="position:absolute;left:0px;top:0px;height:100%;width:100%;">
<svg style="position:relative;width:100%;height:100%;" viewBox="0 0 1000 500" preserveAspectRatio="xMinYMin">
<svg id="shape" name="Triangle" x="275" y="50" width="371" height="378" fill="red" stroke="yellow" stroke-width="3">
<path d="M0,378L185,0L371,378Z" />
</svg>
</svg>
</div>
</div>
For the javascript solution, you define the size on your div containers, and your svg can then be relative and not have the positioning info. And on resize you adjust the scale based on the innerWidth. Like this:
window.onload = window.onresize = calculateScale
function calculateScale() {
var scaleFactor = innerWidth / 1000;
document.getElementById('container').style.transform = `scale(${scaleFactor})`
}
html,
body {
width: 100%;
height: 100%;
padding: 0px;
margin: 0px;
}
* {
box-sizing: border-box;
}
<div id="container" style="position:absolute;border:dashed;width:1000px;height:500px;transform-origin: left top">
<svg name="Box" style="position:relative;width:100%;height:100%;">
<rect width="100%" height="100%" stroke="lime" fill="blue" stroke-width="10" />
</svg>
<div id="shape" style="position:absolute;width: 371px;height: 378px;top: 50px;left: 275px;">
<svg style="width: 100%; height: 100%" id="shape" name="Triangle" fill="red" stroke="yellow" stroke-width="3">
<path d="M0,378L185,0L371,378Z" />
</svg>
</div>
</div>
I think I got what you are looking for but this is two different svgs not the same vector image.
I'm wrapping both svgs with a div and im overlaying the second div using an absolute position.
<html>
<body>
<div id="containerouter" style="position:relative;border:dashed;width:100%;height:100%;margin:0;">
<div id="background" style="position:relative;width:100%;height:100%;">
<svg name="Box" viewBox="0 0 1000 500">
<rect width="1000" height="500" stroke="lime" fill="blue" stroke-width="10" />
</svg>
</div>
<div id="shape" style="position:absolute;height:100%; width:auto;left:175px;top:10%;">
<svg name="Triangle" viewBox="0 0 371 378" fill="red" stroke="yellow" stroke-width="3" x="0" y="0" height="75%">
<path d="M0,378L185,0L371,378Z" />
</svg>
</div>
</div>
</body>
</html>
Like this?
<html>
<body>
<div class="container" style="width:100%; height:100%;">
<div class="container" style="width:100%; height:100%;">
<svg id="container" style="position:relative;border:dashed;width:100%;height:100%;" viewBox="0 0 1000 500">
<rect width="100%" height="100%" stroke="lime" fill="blue" stroke-width="10" />
<foreignObject x="275" y="50" width="371px" height="378px">
<div class="container" style="width:100%; height:100%;">
<svg id="shape" name="Triangle" x="0" y="0" fill="red" stroke="yellow" stroke-width="3" width="100%" height="100%">
<path d="M0,378L185,0L371,378Z" />
</svg>
</div>
</foreignObject>
</svg>
</div>
</div>
</body>
</html>
EDIT: Changed the snippet.
This version uses a <foreignObject> to wrap the inner svg with a div element. Outcome is as expected.
If you are trying to have something like this:
<div>
<div>
<svg> <!-- rect --> </svg>
</div>
<div>
<svg> <!-- triangle --> </svg>
</div>
</div>
Then you'll need to overlay the divs on top of one another and you can't manipulate the svg any further

Combining <symbol> with <use> SVG tags on a HTML page

I'm trying to combine the 'symbol' and 'use' SVG elements in an HTML page and I can't seem to get it to play ball.
I've declared the original graphic within a div at the top of the page using 'symbol', and then called this afterwards with 'use'. The original graphic then duly shows.
When I try and repeat it further down it doesn't show. When I inspect the page though, there is some space being allocated for this element despite it not showing / rendering and the svg 'shadow root' is showing.
Any help would be awesome.
#box1, #box2 {width: 300px;}
<div id="box1">
<symbol id="shapes-square" viewBox="0 0 352.16 240.77">
<svg id="square" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 195.74 129.42">
<title>Blue Square</title>
<rect x="0.5" y="0.5" width="194.74" height="128.42" fill="blue" stroke="#000" stroke-miterlimit="10"/>
</svg>
</symbol>
</div>
<!-- Declare Initial 'use' of SVG -->
<svg>
<use href="#shapes-square" />
</svg>
<br />
<!-- Div to hold the second 'use' of the SVG -->
<div id="box2">
<svg>
<use href="#shapes-square" />
</svg>
</div>
The <symbol> tag has to be wrapped inside the <svg> in order for you to use it subsequently. Please check out this article that could help you further https://css-tricks.com/svg-symbol-good-choice-icons/
#box1, #box2 {width: 300px;}
<svg xmlns="http://www.w3.org/2000/svg" style="display:none">
<symbol id="shapes-square" viewBox="0 0 195.74 129.42">
<rect x="0.5" y="0.5" width="194.74" height="128.42" fill="blue" stroke="#000" stroke-miterlimit="10"/>
</symbol>
</svg>
<!-- Declare Initial 'use' of SVG -->
<div id="box1">
<svg>
<title>Blue Square 1</title>
<use href="#shapes-square"/>
</svg>
</div>
<br />
<!-- Div to hold the second 'use' of the SVG -->
<div id="box2">
<svg>
<title>Blue Square 2</title>
<use href="#shapes-square" />
</svg>
</div>
Swap the tags <symbol> and <svg>
<symbol> serves for temporary concealment of content, it is used recently, most often in sprites, since it has its own internal viewBox, for additional positioning of elements.
#box1, #box2 {width: 300px;}
<div id="box1">
<svg id="square" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 195.74 129.42">
<symbol id="shapes-square" viewBox="0 0 352.16 240.77">
<title>Blue Square</title>
<rect x="0.5" y="0.5" width="194.74" height="128.42" fill="blue" stroke="#000" stroke-miterlimit="10"/>
</symbol>
</svg>
</div>
<!-- Declare Initial 'use' of SVG -->
<svg>
<use href="#shapes-square" />
</svg>
<br />
<!-- Div to hold the second 'use' of the SVG -->
<div id="box2">
<svg>
<use href="#shapes-square" />
</svg>
</div>
In the future, you probably want to use styling for cloned objects. In this case, there may be some nuances:
When you reuse the content with <use> it enters the shadow DOM
And it becomes impossible to change the styles of cloned objects from external tables CSS
To eliminate this defect, you can force inheritance of properties for svg elements.
rect{
fill:inherit;
stroke:inherit;
stroke-width:inherit;
}
In addition, you can use the coordinates of x andy inside
<use> for additional positioning of cloned objects.
<use class="use1" x="0" y="10" href="#shapes-square" />
Below is an example of styling cloned objects
rect{
fill:inherit;
stroke:inherit;
stroke-width:inherit;
}
.use1{ fill:red;}
.use2{ fill:yellowgreen;}
.use3{ fill:dodgerblue;}
#box1, #box2, #box3 {
background:#D5D5D5;
width: 400px;
margin:4px;
}
<div>
<svg id="square" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="195" height="129 "viewBox="0 0 195.74 129.42">
<symbol id="shapes-square" viewBox="0 0 195.74 129.42">
<title>Blue Square</title>
<rect x="0.5" y="0.5" width="194.74" height="128.42" fill="blue" stroke="#000" stroke-miterlimit="10"/>
</symbol>
</svg>
</div>
<div id="box1">
<svg>
<use class="use1" x="0" y="10" href="#shapes-square" />
</svg>
</div>
<!-- Div to hold the second 'use' of the SVG -->
<div id="box2">
<svg>
<use class="use2" x="50" y="10" href="#shapes-square" />
</svg>
</div>
<div id="box3">
<svg>
<use class="use3" x="20" y="10" href="#shapes-square" />
</svg>
</div>

SVG <use> element not visible in Chrome

I have an SVG element that is embedded into my HTML page that works perfectly on Firefox but does not work on Chrome.
I'm using a mask to cover a video background while the SVG element has a transparent fill (using CSS class on use element) to show video background through it.
I believe I identified the problem to be with the <use> tag because when I inspect it in Chrome, the use element has some dimensions but is not matching the SVG viewbox's size: <svg viewBox="0 0 1000 300" class="svg-inverted-mask"> that it lives in. In Firefox, the size of use element matches the viewbox and renders correctly.
Code:
<div class="wrap heightwrap wow fadeInDown" data-wow-delay="0.4s">
<svg viewBox="0 0 1000 300" class="svg-defs">
<!-- Symbol with Logo -->
<symbol id="s-text2">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="30%" y="-25%" width="700" height="800" viewBox="0 0 1000 800">
<defs>
<rect id="a" x="50%" y="50%" width="612" height="792"/>
</defs>
<clipPath id="b">
<use href="#a" overflow="visible"/>
</clipPath>
<path clip-path="url(#b)" d="M468.896,118.65l-80.667,254.289H145.563l-24.334-62.667h188 c0,0,26.167,0.167,33.311-18.676l15.356-50.99c20.333-62.333,22.67-67.217-34-67.667c-15.121-0.12-30.689,0.122-39.254,0.072 c-17.878-0.105-22.246,0.139-20.368-10.094l10.712-34.979c0,0,1.285-9.287,17.66-9.287"/>
<path clip-path="url(#b)" d="M275.563,267.9c28.667,0,28.013-1.13,35.833-28.5c8-28,9.457-29.082-12-29.5 c-10.548-0.205-26.166,0-26.166,0c-51.959,0-64.834,1.5-58.222-24.03c2.682-10.354,6.587-25.693,12.221-45.637 c4.024-14.247,8.103-29.353,11.369-38.006C250.481,70.74,271.842,75.708,343.23,75.9c92.334,0.249,139.333,0,139.333,0l20.333-62 h-314l-41.553,149.031c0,0-2.537,10.65-6.408-0.212L87.896,13.9h-69l89.667,254H275.563"/>
</svg>
</symbol>
<!-- Mask with text -->
<mask id="m-text2" maskunits="userSpaceOnUse" maskcontentunits="userSpaceOnUse">
<rect width="100%" height="100%" class="mask__shape">
</rect>
<use href="#s-text2" class="mask__text"></use>
</mask>
</svg>
<div class="box-with-text">
<!-- Container for video -->
<div class="text-fill">
<video class="video" src="/css/fractal3.mp4" autoplay loop></video>
</div>
<!-- Visible SVG -->
<svg viewBox="0 0 1000 300" class="svg-inverted-mask">
<rect width="100%" height="100%" mask="url(#m-text2)" class="shape--fill" />
<use href="#s-text2" class="text--transparent"></use>
</svg>
</div>
</div>
Getting rid of the unnecessary clipPaths seems to help.
They look like the sort of clips that Illustrator adds to reproduce its way of rendering strokes. But since your symbol doesn't have an stroking, they are safe to remove.
<div class="wrap heightwrap wow fadeInDown" data-wow-delay="0.4s">
<svg viewBox="0 0 1000 300" class="svg-defs">
<!-- Symbol with Logo -->
<symbol id="s-text2">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="30%" y="-25%" width="700" height="800" viewBox="0 0 1000 800">
<path d="M468.896,118.65l-80.667,254.289H145.563l-24.334-62.667h188 c0,0,26.167,0.167,33.311-18.676l15.356-50.99c20.333-62.333,22.67-67.217-34-67.667c-15.121-0.12-30.689,0.122-39.254,0.072 c-17.878-0.105-22.246,0.139-20.368-10.094l10.712-34.979c0,0,1.285-9.287,17.66-9.287"/>
<path d="M275.563,267.9c28.667,0,28.013-1.13,35.833-28.5c8-28,9.457-29.082-12-29.5 c-10.548-0.205-26.166,0-26.166,0c-51.959,0-64.834,1.5-58.222-24.03c2.682-10.354,6.587-25.693,12.221-45.637 c4.024-14.247,8.103-29.353,11.369-38.006C250.481,70.74,271.842,75.708,343.23,75.9c92.334,0.249,139.333,0,139.333,0l20.333-62 h-314l-41.553,149.031c0,0-2.537,10.65-6.408-0.212L87.896,13.9h-69l89.667,254H275.563"/>
</svg>
</symbol>
<!-- Mask with text -->
<mask id="m-text2" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse">
<rect width="100%" height="100%" class="mask__shape">
</rect>
<use href="#s-text2" class="mask__text"></use>
</mask>
</svg>
<div class="box-with-text">
<!-- Container for video -->
<div class="text-fill">
<video class="video" src="/css/fractal3.mp4" autoplay loop></video>
</div>
<!-- Visible SVG -->
<svg viewBox="0 0 1000 300" class="svg-inverted-mask">
<rect width="100%" height="100%" mask="url(#m-text2)" class="shape--fill" />
<use href="#s-text2" class="text--transparent"></use>
</svg>
</div>
</div>

Change image color in svg element

The goal is to show image but with another color inside svg.
I tried -webkit-mask-image with background-color, but this combination does not work in svg. Here is the example:
<div class="dashboard-buttons">
<svg width="367" height="243.5" viewBox="252.5 60.5 367 243.5">
<g>
<rect width="46" height="46" rx="4" ry="4" transform="translate(-23, -23)" style="fill:white" x="560" y="224"></rect>
<a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#element3" href="#element3" onclick="window.location.href = '#element3';">
<image height="32" width="32" transform="translate(-16, -16)" x="560" y="224" style="background-color: Red; -webkit-mask-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuM4zml1AAAACqSURBVFhH7ZYhDsJAFESHBMkBOCYGyQV6BQ6BQ0EwWByiuwj0Fk5AgO00+XJpCd20gpnkqfZnXrJmoCiVx+rmcWyD/2zCGXM7yZvK4c2S2InDiRIzO8uXZNkHgsM2HjC10zxJFXWwjsDEzvsnUfANVz7JpS93j+JXgSyEEs9RBRokIAEJSEACEpDA+AIcpa/UhyHg2n6A02jJabSjyH5Qms4SC1uGyt8GqAEZtGBDEZcerAAAAABJRU5ErkJggg==');width: 32px; height: 32px;"></image>
</a>
<a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#element3"><text filter="url(#fillbackground)" x="560" y="257">out</text></a>
</g>
</svg>
</div>
If you remove svg tags from it then this sample works and the color changed.
Do you know how to change image color inside svg correctly?
EDIT:
The following code works in Chrome, but not in Firefox:
<div class="wrapper">
<svg width="200" height="300" class="svg">
<defs>
<mask id="mask">
<image xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuM4zml1AAAACqSURBVFhH7ZYhDsJAFESHBMkBOCYGyQV6BQ6BQ0EwWByiuwj0Fk5AgO00+XJpCd20gpnkqfZnXrJmoCiVx+rmcWyD/2zCGXM7yZvK4c2S2InDiRIzO8uXZNkHgsM2HjC10zxJFXWwjsDEzvsnUfANVz7JpS93j+JXgSyEEs9RBRokIAEJSEACEpDA+AIcpa/UhyHg2n6A02jJabSjyH5Qms4SC1uGyt8GqAEZtGBDEZcerAAAAABJRU5ErkJggg==">
</image>
</mask>
</defs>
<rect width="50" height="50" style="fill:blue;" x="0" y="0"
mask="url(#mask)"></rect>
</svg>
</div>
Can't see your example, but:
<rect x="10" y="10" width="100" height="100" stroke="blue" fill="purple"
fill-opacity="0.5" stroke-opacity="0.8"/>
Use the fill option!
EDIT:
Now I can see your code.
If you insert an image as PNG:
data:image/png
Then I doubt you can change the color with HTML directive. PNG are bitmaps and not SVG, you would have to edit the PNG itself to achieve that.

Why the pattern image of my SVG is larger than the path made of it?

everyone!
I think I've got a problem here:
Following this tutorial, I made a path from an image (the mirror's frame) and also applied the image as a fill pattern for the svg path. I don't understand why the pattern image end up bigger, like you see on the pic. Here are the markups:
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%"
viewBox="0 0 1949 2220"
preserveAspectRatio="xMidYMid slice">
<defs>
<pattern id="mirror" height="100%" width="100%"
patternContentUnits="userSpaceOnUse"
viewBox="0 0 1 1"
preserveAspectRatio="xMidYMid slice">
<image xlink:href="mirror.jpg"
preserveAspectRatio="xMidYMid slice"
x="0" y="0"
width="1" height="1" />
</pattern>
</defs>
<path .................
and the page:
<div class="w3-container">
<div class="w3-row">
<div id="left_pallette" class="w3-quarter w3-border">
</div>
<div id="mirror" class="w3-half">
<object id="mirror_object" type="image/svg+xml" data="mirror_frame.svg">
<img src="mirror_frame.svg" onerror="this.src='mirror.jpg'"/>.
</object>
</div>
<div id="right_pallette" class="w3-quarter w3-border">
</div>
</div>
</div>
I would appreciate any ideas on how to fix this issue.
Thanks!
Your pattern is defined differently from the tutorial. Have you tried doing it the way they suggest?
<pattern id="mirror" patternUnits="userSpaceOnUse" width="1949" height="2220">
<image xlink:href="mirror.jpg" x="0" y="0" width="1949" height="2220" />
</pattern>