CSS: SVG with shadow, rotation and image - html

On my HTML page I have to render a shadowed and rotated polygon containing an image.
If I assign the shadow to the DIV, I get a pixelated border and a blurry image.
<div style="-webkit-transform:rotate(-15deg); -webkit-filter:drop-shadow(2px 2px 1.2px rgba(26, 25, 24, 0.50)); -webkit-transform:rotate(-30deg);">
<svg>
If I add "transform:translateZ(0);" to the SVG, I get a good border, a good shadow and a blurry image.
<div style="-webkit-transform:rotate(-30deg); -webkit-filter:drop-shadow(0.73px 2.73px 1.2px rgba(26, 25, 24, 0.50));">
<svg style="-webkit-transform:translate3D(0,0,0);">
At the end I found the best way is to assign an -webkit-svg-shadow to the SVG. This gives a good shadow, a good border and a net image. Cool.
<div style="left:58.99px ; top:90.18px; width:146.5px; height:146.5px; -webkit-transform:rotate(-30deg);">
<svg width="146.5px" height="146.5px" style="-webkit-svg-shadow:2px 2px 1.2px rgba(26, 25, 24, 0.50); ">
<defs>
<clipPath id="clipPath_1">
<polygon id="poly_1" points="70,8.19 7.56,55.88 31.53,133.44 108.5,133.5 132.44,56 "/>
</clipPath>
<pattern id="pattern_1" width="1" height="1" preserveAspectRatio="none">
<image xlink:href="image_1.png" x="6.500000" y="6.500000" width="114" height="114" preserveAspectRatio="yes"></image>
</pattern>
</defs>
<use xlink:href="#poly_1" x="0" y="0" fill="url(#pattern_1)" stroke="rgb(103, 103, 103)" stroke-width="13" />
</svg>
</div>
The problem comes now. Somewhere on the HTML page, I add a shadowed and rotated rectangle containing an image.
<div style="left:58.99px ; top:90.18px; width:114px; height:114px; -webkit-filter:drop-shadow(2px 2px 1.2px rgba(26, 25, 24, 0.50)); -webkit-transform:rotate(-15deg);">
<img src="image_1.png" alt="" style="width:114px; height:114px; "/>
The image within the rectangle looks blurry. The previous image within the SVG still looks ok.
If I add the following code to the CSS file
img{
-webkit-transform:translate3D(0,0,0); /* or even -webkit-transform:translateZ(0); */
}
the image within the rectangle looks good. BUT, the previous image within the SVG looks now blurry!
I'm really puzzled. As I understand, transform:translateZ(0) turns the GPU acceleration on, and it re-blurs the SVG's image a second time.
So, how can I get the 2 images look well? Or how to turn on/off the GPU acceleration? Should I use SVG rectangles all the time? I mean, should I use SVG for any shape? I come from Cocoa and OpenGL and I am new to HTML and CSS. At the first look it seems to be buggy and not so reliable. Is it true?

Related

is there a way to reference svg from page in the css?

I see that you can reference the svg by id in some css/svg properties, as in:
<!-- the logo svg -->
<svg id="rect-container" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- left squares -->
<rect fill="url(#rect-fill)"/>
</svg>
does anyone know if we can use a svg from the page, in a css bg for example? to avoid encoding it on the css.
Something like this, which I already tried but did not seem to work the same way.
.myel {
background-image: url(#rect-svg-image);
}
First, there is a misconception to clear up.
fill: url(#source);
does not reference arbitrary SVG content, but a paint server, namely a gradient or pattern. Other uses of the CSS url() notation in SVG include the clip-path, mask and marker-start|mid|end properties that all also can only reference specific elements.
Currently, background-image needs an actual self-contained image resource or a CSS gradient. Referencing a SVG paint server with url() does not work.
But the CSS Images Module Level 4 also defines a element() functional notation that can reference fragments inside the page.
If you look at the text of the specification, there are still a lot of open questions listed to solve before this can become mainstream. There currently is only a Firefox implementation with vendor prefix, -moz-element(). You can point it to paint servers; that means you can (mis)use a <pattern> element. Although experimenting, I found there are some tradeoffs to make:
patternContentUnits="objectBoundingBox" needs all content drawn into a 1px*1px square, but makes the content scalable. Preserving the aspect ratio is not supported.
patternContentUnits="userSpaceOnUse" gives you preservation of the aspect ratio, but scaling is not supported.
svg {
display: block;
width: 0;
height: 0;
}
div {
width: 200px;
height: 150px;
border: 1px solid black;
background-image: -moz-element(#image);
background-size: cover;
}
<svg>
<pattern patternContentUnits="objectBoundingBox"
preserveAspectRatio="xMidYMid meet"
width="100%" height="100%" id="image">
<rect width=".5" height=".5" fill="red"/>
<rect width=".5" height=".5" x=".5" fill="yellow"/>
<rect width=".5" height=".5" y=".5" fill="green"/>
<rect width=".5" height=".5" x=".5" y=".5" fill="blue"/>
<circle r=".5" cx=".5" cy=".5" fill="white" opacity=".5"/>
</pattern>
</svg>
<div>

Wavy border separator on two sections with [background] images

I’ve been strugglin on making a wavy line on the transition between two sections on my page. These two sections have their respective background images. What I’ve found are examples where at least one section have a simple colored background.
The problem is that when using some of the methods found (svg, clip-path, transform), I have to always fill with a color.
What I want: https://imgur.com/R1sXk8y
What I have done so far: https://imgur.com/CtVLOE8 (This one is a sloped line example. I have to do various shapes on different borders, but its an example to show the separation that would be noticed with the wavy border too)
This is my solution: I'm using clip-path as you intended, although, as you may know, clip-path is not supported in all browsers.
The main idea is having clipPathUnits="objectBoundingBox".
MDN quote:
This value [clipPathUnits="objectBoundingBox"] indicates that all coordinates inside the element are relative to the bounding box of the element the clipping path is applied to. It means that the origin of the coordinate system is the top left corner of the object bounding box and the width and height of the object bounding box are considered to have a length of 1 unit value.
*{margin:0;padding:0;}
#top {
padding: 0;
background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/castell.jpg);
background-size: cover;
height: 50vh;
-webkit-clip-path: url(#clip);
clip-path: url(#clip);
}
body{background:url(https://images.unsplash.com/photo-1470327500070-4857199b1bcd?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ);background-size:cover}
<svg height="0" width="0" class="svg-clip" style="position:absolute">
<defs>
<clipPath id="clip" clipPathUnits="objectBoundingBox">
<path d="M0,0 L0,.5 Q.3,.2 .5,.5 T1,.5L1,0 0,0" />
</clipPath>
</defs>
</svg>
<div id="top"></div>

Is it possible to use an image in place of the stroke of an SVG path?

First off, I know this question is very similar to this question, but I tried implementing that solution with an SVG PATH and it did not work.
I also know that another solution would be to loop the PATH and set the FILL of the PATH as mentioned here and elsewhere on the web.
However, I have animated the STROKE-DASHOFFSET of the PATH so that the stroke of the PATH, which is simply an irregular line, appears as if it is being drawn onto the page; This is the effect that I want to achieve without using a color as the STROKE but instead an image. In other words, it would appear to the user as if the image (and not a solid color) is being drawn onto the page as an irregular line.
As per requested, below is the HTML of the PATH that I am using and its corresponding CSS, an image of that PATH, and also the CSS of the animation itself:
<div id="container">
<svg>
<path d="
M0,5
L184,5
C202,5 202,5 202,36
L202,86
L327,85
L421,166
L460,166
L499,132
L588,211
L617,211
L712,134
L748,165
L780,165
L830,111
L913,212
L938,212
L1028,140
L1078,184
L1107,184
L1152,140
L1263,249
L1263,248"
/>
</svg>
</div>
Image of PATH
#container {
width:1263px; height:255px;
position:absolute;
}
#container svg {
width:100%; height:100%;
fill:none;
stroke:#008066; stroke-width:8;
stroke-dasharray:1628; stroke-dashoffset:1628.1;
stroke-linecap:square;
animation:polyline 3.15s linear 0.5s forwards;
}
#keyframes polyline {
to {
stroke-dashoffset:0;
}
}
Is this possible?
Is this possible by using the CLIPPATH element and then somehow animating it?
TIA
Update
Below is the code with the PATTERN and IMAGE element, and the corresponding CSS, which doesn't seem to produce a stroke.
<defs>
<pattern id="pattern" width="1600" height="800" patternUnits="userSpaceOnUse">
<image xlink:href="http://lorempixel.com/1600/800/nature" width="1600" height="800" />
</pattern>
</defs>
#container svg {
stroke:url(#pattern);
}
That's a Chrome/Safari bug you're relying on.
stroke:url(#pattern);
is actually shorthand for
stroke:url(<this file>#pattern);
but there's no pattern in the css file. Chrome gets this wrong, Firefox gets it right. If you fix the reference Firefox will work but unfortunately Chrome won't any longer. The most compatible solution would therefore be to move your CSS (at least the bit that references the pattern) into the SVG file itself within <style> tags.
It works fine on firefox. I am not sure what the problem is that you are having.
#container svg {
fill: none;
stroke-width: 10px;
stroke: url(#pattern);
stroke-dasharray:1628;
stroke-dashoffset:1628.1;
animation:polyline 3.15s linear 0.5s forwards;
}
#keyframes polyline {
to {
stroke-dashoffset:0;
}
}
<div id="container">
<svg>
<defs>
<pattern id="pattern" width="1600" height="800" patternUnits="userSpaceOnUse">
<image xlink:href="http://lorempixel.com/1600/800/nature" width="1600" height="800" />
</pattern>
</defs>
<path d="M0,5
L184,5
C202,5 202,5 202,36
L202,86
L327,85
L421,166
L460,166
L499,132
L588,211
L617,211
L712,134
L748,165
L780,165
L830,111
L913,212
L938,212
L1028,140
L1078,184
L1107,184
L1152,140
L1263,249
L1263,248"
/>
</svg>
</div>

SVG link a PNG bitmap image ignoring transparency (without path)

I'm having difficulties with an image map-like approach for linking an image but ignoring its transparent areas. Imagine that I have a PNG button with rounded corners (bad example for simplicity's sake, I know about CSS's border-radius), and I only want to have the cursor change on the button itself, ignoring its transparency.
Of course I could just do it like this:
<image width="438" height="189" xlink:href="button.png"></image>
<a xlink:href="//google.com/">
<path id="ab" d="M351.371,342.397c-55 …" />
</a>
But what if I want to do that dynamically e.g. having a JS function generating the markup for different-sized images using the same technique? Maybe using an SVG mask?
The following snippet of course links the whole image...
<a xlink:href="//google.com">
<image width="438" height="189" xlink:href="button.png"></image>
</a>
I have come across a couple of questions here on SO with png images in svg.
There seems to be little support for this in a couple of browsers. I don't have the time to test all major browsers atm.
But your trying to create a button with rounded corns that's only clickable on the painted area, not the transparent part?
Why not use svg rect to create that button?
svg text {
fill: white;
}
svg rect {
fill: firebrick;
stroke: gray;
}
svg a:active rect {
stroke: black;
}
svg a:active text {
text-shadow: 2px 2px 2px black;
}
<svg viewBox="0 0 100 100" width="50%">
<a xlink:href="#">
<rect x="20" y="30" width="70" rx="5" height="30" />
<text x="30" y="50">Submit</text>
</a>
</svg>

SVG triangle with centered image

I am a beginner when it comes to SVG creation and have been researching this for quite a while. I've found some good resources, but I am still a bit hazy on the best way to accomplish what I am trying to do (and maybe SVG isn't the right answer - maybe jQuery or CSS3 is better).
Info
I want to have a series of equilateral SVG triangles, I plan on using them as an image thumbnails for a gallery. When you hover over them it will give you a "title" and then you can click to see the entire project (still working on getting a title to show up on hover too).
Some images will be upright, others will be inverted (upside down) - although I haven't figured out how to do this yet either.
Anyway, I have a fiddle with the triangle, image, and hover effect. All the images that will be placed within the triangles will be square. I want to do something similar to if I was using background-size: cover. Ultimately my question is, how do I center the image and fill it within the triangle.
I saw this question but I'm not sure how to integrate this within my code. Also my code thus far is based off of this question
Question
So any help with this would be greatly appreciated. My primary concern is centering and filling the image within the triage. Secondary concerns are getting some text to show up on hover and "flipping" the triangles.
Code
HTML
<svg id="svg-1" class="clip-svg">
<image id="img-1" class='svg-image' width="300" height="300" xlink:href="img/tshirt.jpg" />
<rect class='svg-describe' width="300" height="300" fill="#cccccc" />
</svg>
<svg id="svg-defs">
<defs>
<clipPath id="clip-triangle">
<polygon points="0, 200 100, 0 200, 200"/>
</clipPath>
</defs>
</svg>
CSS
.svg-describe, .svg-image {
clip-path: url(#clip-triangle);
}
.svg-describe {
opacity: 0;
transition: all 0.5s ease 0.2s;
-moz-transition: all 0.5s ease 0.2s;
-webkit-transition: all 0.5s ease 0.2s;
}
.clip-svg .svg-describe:hover {
opacity: 1;
}
jsfiddle
edit...
I was able to do a hack to center the image within the triangle by adding x="-50" y="-40" to my image tag. Although the image doesn't fill the triangle completely. I'm sure there is a better way to accomplish this though...
If you use appropriate sizes for the triangles and background images, then I think this problem will go away.
The maths is quite straightforward — if your images are all 300×300 px squares, then your equilateral triangles should be 300 px wide and 260 px tall (because 300×(√3)/2 = 260).
That means the SVG dimensions should be 300×260 px, and the embedded image should be offset vertically by 20 pixels to keep it centred.
<svg id="svg-1" class="clip-svg" width="300" height="260">
<image id="img-1" class="svg-image" width="300" height="300"
x="0" y="-20" xlink:href="http://goo.gl/l477XT" />
<rect class="svg-describe" width="300" height="260" fill="#000" />
<defs>
<clipPath id="clip-triangle">
<polygon points="0, 260 150, 0 300, 260" />
</clipPath>
</defs>
</svg>
Here's a JSFiddle