irregular-shaped DOM elements - html

How to make them in HTML or CSS?
For example:
http://draw.to/D11KGJr
I've heard about the map tag, but it seems it only generates an invisible clickable area, on which you can't apply CSS properties, like border or background.

If you are talking about that drawing: it's a canvas element.
See here for a tutorial: https://developer.mozilla.org/en-US/docs/Canvas_tutorial

Besides using CSS 3 techniques as the others proposed, you could also embed SVG in your HTML document.
jsFiddle
<!doctype html>
<html>
<!-- <head> ... -->
<body>
Taken from http://commons.wikimedia.org/wiki/File:SVG_example7.svg?uselang=de, thanks to Sarang!
<hr />
<svg xmlns="http://www.w3.org/2000/svg" width="304" height="290">
<path d="M2,111h300 l-242.7,176.3 92.7-285.3 92.7,285.3z" fill="#FB2" stroke="#B00" stroke-width="4" stroke-linejoin="round"/>
</svg>
</body>
</html>

This is possible - within limits, and only on newer browsers - using CSS3 techniques. For an example, see this CSS3 Twitter Fail Whale.

That uses the canvas element.
Spec: http://www.w3.org/TR/2011/WD-html5-20110525/the-canvas-element.html#the-canvas-element
Doc based on one particular browser implementation: https://developer.mozilla.org/en-US/docs/HTML/Canvas
Informal docs: http://diveintohtml5.info/canvas.html and http://www.html5canvastutorials.com/
There are other approaches for non-rectangular elements, which may be more appropriate for what you actually need, if you can say more about your specific requirements.

Related

Link in custom area inside svg image does not work

I want to create some links and hover effects inside a svg image. So, I created some custom transparent areas inside one svg image, in an online images editor, in order to do that. But when I try to apply some links in those custom areas, as show below, it does not work. How can I make it work?
<body>
<svg>
<defs></defs>
<!-- custom ellipse which the link does not work -->
<a href="some-link.com">
<ellipse />
</a>
<!-- normal path from the svg image, which the link work -->
<a href="some-link.com">
<path></path>
</a>
<!--rest of the image with many paths-->
<path></path>
</svg>
</body>
The ellipse element seems to be invalid. And since the markup has an error, it might affect even the functionality of the parent element.
The self-closing tag should have the slash at the end (since SVG is based on more strict XML) like below:
<ellipse />
Does this change solve the problem with the link?

ADA Compliance SVG issue

I am currently developing a site that needs to be ADA Compliant. When I check the site in WAVE I get a perfect score with 0 errors. However, when I put it in this checker, it says there are 6 errors that are missing alt tags.
These images are svgs and when I view page source and inspect element, I can see the alt tags, they are clearly there. For some reason the checker is looking inside the actual svg itself
Here is the code:
<div class="footer-desktop">
<img src="<?php echo get_template_directory_uri(); ?>/img/fc-footer-logo.svg" alt="Footer Logo">
</div>
I have tried adding role="image" and that just causes more errors. I've also tried adding a title tag.
Not all automated validators are accurate and they shouldn't be relied on as authoritative. They are merely tools to assist you in finding things that may be an issue. Your best bet is testing and confirming if things are accessible. That being said, here are some tips for making it a bit better for SVGs...
On your SVG, use <title> and <desc> tags and give each unique ID. Then include an aria-labelledby on the tag. For example:
<svg width="300" height="100" xmlns="http://www.w3.org/2000/svg" aria-labelledby="svgTitle svgDesc" >
<title id="svgTitle">This is my title.</title>
<desc id="svgDesc">This is my description.</desc>
<...>
</svg>
This should give you pretty good screen reader support. However, I can't claim that it will pass any specific automated tests. Alternatively, you can just use an aria-label on the SVG, but then you don't get the tooltip in standard browsers from the title tag.
Note: The <svg> tag doesn't have an "alt" attribute,so it wouldn't be valid HTML5.
BTW, it should be role="img" not role="image".

How to embed a scoped html (css) in a document

I need to be able to embed HTML snippets (nested elements and CSS) fetched from a remote api inside my document, in a way that their CSS won't affect on my whole document.
I need to fetch (random) gmail messages HTMLs and embed them in my website. The thing is that most messages have their CSS tags to style the message html. The problem is that some of these CSS mess up with my own document CSS. How can I embed an html snippet with CSS, in a way that it will have its own scope and not interact with what's outside of it?
<html>
<body>
<h1>Your gmail messages</h1>
<div id="gmail-message">
<!-- Here to be injected automatically. Changing classes, etc is not possible -->
<h1>This a gmail message</h1>
<style type="text/css">
h1 {
color: red;
}
</style>
</div>
</body>
</html>
The h1 tag outside the gmail-message div is also affected and is therefore red.
What do I need to do to get around this?
One solution would be to use an iframe.
Another solution would be to extract all css and html, then add an attribute (example: scope) to every html tag inside of gmail-messag.
Then modifiy the css and add an attribut selector.
Example:
<html>
<body>
<h1>Your gmail messages</h1>
<div id="gmail-message">
<!-- Here to be injected automatically. Changing classes, etc is not possible -->
<h1 scoped>This a gmail message</h1>
<style type="text/css">
h1[scoped] {
color: red;
}
</style>
</div>
</body>
</html>
But propably using an ifram is a more easy solution.
Easiest way is to use iframe / object / embed tag (tested on firefox).
If you can use Javascript and HTML5 you can also use shadow DOM or make custom element that uses slot tag (also in shadowRoot).
You might want to look into using The Shadow DOM
An important aspect of web components is encapsulation — being able to
keep the markup structure, style, and behavior hidden and separate
from other code on the page so that different parts do not clash, and
the code can be kept nice and clean. The Shadow DOM API is a key part
of this, providing a way to attach a hidden separated DOM to an
element.
However, be aware this is new tech and, as always, Microsoft browsers don't handle it.
I've found my solution.
First, insert an empty iframe tag somewhere.
<iframe id="iframeTag" src="about:blank"></iframe>
Second, load the html snippet into that iframe, the following way:
var doc = document.getElementById('iframeTag').contentWindow.document;
doc.open();
doc.write(<html_snippet>);
doc.close();
This way the <html_snippet>'s css won't mix up with the outer document's.
Use the srcdoc attribute on iframe to scope your HTML and CSS.
<iframe srcdoc="<p>Hello world!</p>"></iframe>
It's supported on all major browsers: https://caniuse.com/iframe-srcdoc

Custom path title for SVG

I'm currently working on a svg and I was wondering if it was possible to easily pop a tooltip while hovering some elements.
I discovered that the attribute title is available while used like this :
<path>
<title>Custom title</title>
</path>
I then thought about customizing the title element, so that it might spawn quicker, with a different background etc ...
So I tried different things like :
path[title]:hover:after { instructions }
But unfortunately it doesn't seem to work.
Does someone knows an easy way to customize title from path elements ?
Thank you for your help.
Second edit (ARRGGHH!):
The website: http://www.w3schools.com/css/tryit.asp?filename=trycss_tooltip shows how to do styling of tooltips like you wanted.
EDIT:
For SVG tooltips for a path, it is like this:
<path d="M150 0 L75 200 L225 200 Z">
<title>This is a traingle</title>
</path>
Hope this works and it does because I tested it.
===========
If you want a tooltip on an image element do this:
<img title="tooltip text"></img>
It is the same for other things too.
Also, when you put brackets in the css, that is to put:
path[attribute=value]
So you would want:
path title:hover:after {
// styling
}
I am glad to help. Hope this works!

Making an svg image object clickable with onclick, avoiding absolute positioning

I have tried to change the images on my site from img to svg, changing img tags to embed and object tags. But, implementing the onclick function, which previously was contained in the img tag, is proving most difficult.
I found onclick had no effect when placed inside the object or embed tag.
So, I made a div exclusively for the svg, and placed onclick in this div tag. But, no effect unless visitor clicks on the edges/padding of the image.
I have read about overlaying a div, but am trying to avoid using absolute positioning, or specifying position at all.
Is there another way to apply onclick to a svg?
Has anyone encountered this problem? Questions and suggestions are welcome.
You can have an onclick event in the svg itself, I do this all the time in my work. make a rect over the space of your svg, (so define it last, remember svg uses the painters model)
rect.btn {
stroke:#fff;
fill:#fff;
fill-opacity:0;
stroke-opacity:0;
}
then as an attribute to the rect add the onclick (this can be done with js or jquery as well).
<div>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<g>
<circle ... //your img svg
<rect class="btn" x="0" y="0" width="10" height="10" onclick="alert('click!')" />
</g>
</svg>
</div>
this will work in almost all browsers: http://caniuse.com/svg
If you just use inline svg there is no problem.
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" style="width: 3.5in; height: 1in">
<circle id="circle1" r="30" cx="34" cy="34" onclick="circle1.style.fill='yellow';"
style="fill: red; stroke: blue; stroke-width: 2"/>
</svg>
This started as a comment on RGB's solution but I could not fit it in so have converted it to an answer. The inspiration for which is entirely RGB's.
RGB's solution worked for me. However, I wished to note a couple of points which may help others arriving at this post (like me) who are not that familiar which SVG and who may very well have generated their SVG file from a graphics package (as I had).
So to apply RGB's solutions I used:
The CSS
<style>
rect.btn {
stroke:#fff;
fill:#fff;
fill-opacity:0;
stroke-opacity:0;
}
</style>
The jquery script
<script type="text/javascript" src="../_public/_jquery/jquery-1.7.1.js"></script>
<script type="text/javascript">
$("document").ready(function(){
$(".btn").bind("click", function(event){alert("clicked svg")});
});
</script>
The HTML to code the inclusion of your pre-existing SVG file in the group tag inside the SVG code.
<div>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<g>
<image x="0" y="0" width="10" height="10"
xlink:href="../_public/_icons/booked.svg" width="10px"/>
<rect class="btn" x="0" y="0" width="10" height="10"/>
</g>
</svg>
</div>
However, in my case I have several SVG icons which I wish to be clickable and incorporating each of these into the SVG tag was starting to become cumbersome.
So as an alternative approach where I could employ Classes I used jquery.svg. This is probably a shameful application of this plugin which can do all sorts of stuff with SVG's. But it worked using the following code:
<script type="text/javascript" src="../_public/_jquery/jquery-1.7.1.js"></script>
<script type="text/javascript" src="jquery.svg.min.js"></script>
<script type="text/javascript">
$("document").ready(function(){
$(".svgload").bind("click", function(event){alert("clicked svg")});
for (var i=0; i < 99; i++) {
$(".svgload:eq(" + i + ")").svg({
onLoad: function(){
var svg = $(".svgload:eq(" + i + ")").svg('get');
svg.load("../_public/_icons/booked.svg", {addTo: true, changeSize: false});
},
settings: {}}
);
}
});
</script>
where HTML
<div class="svgload" style="width: 10px; height: 10px;"></div>
The advantage to my thinking is that I can use the appropriate class where ever the icons are needed and avoid quite a lot of code in the body of the HTML which aids readability. And I only need to incorporate the pre-existing SVG file once.
Edit: Here is a neater version of the script courtesy of Keith Wood: using .svg's load URL setting.
<script type="text/javascript" src="../_public/_jquery/jquery-1.7.1.js"></script>
<script type="text/javascript" src="jquery.svg.min.js"></script>
<script type="text/javascript">
$("document").ready(function(){
$('.svgload').on('click', function() {
alert('clicked svg new');
}).svg({loadURL: '../_public/_icons/booked.svg'});
});
</script>
I got this working accross the latest versions of Firefox, Chrome, Safari and Opera.
It relies on a transparent div before the object that has absolute position and set width and height so it covers the object tag below.
Here it is, I've been a bit lazy and used inline styes:
<div id="toolbar" style="width: 600px; height: 100px; position: absolute; z-index: 1;"></div>
<object data="interface.svg" width="600" height="100" type="image/svg+xml">
</object>
I used the following JavaScript to hook up an event to it:
<script type="text/javascript">
var toolbar = document.getElementById("toolbar");
toolbar.onclick = function (e) {
alert("Hello");
};
</script>
In case you're fine with wrapping the svg in another element (a for example) and putting onclick on the wrapper, svg {pointer-events: none;} CSS will do the trick.
It worked by simply replacing the <embed/> tag with <img/> and deleting the type attribute.
For instance, in my code, instead of:
<embed src=\"./images/info_09c.svg\" type=\"image/svg+xml\" width=\"45\" onClick='afiseaza_indicatie($i, \"$indicatii[$i]\")'>
which does not answer the clicking, I wrote:
<img src=\"./images/info_09c.svg\" height=\"25\" width=\"25\" onClick='afiseaza_indicatie($i, \"$indicatii[$i]\")'>
It works in Internet Explorer and Google Chrome, and I hope that in the other browsers too.
You could use following code:
<style>
.svgwrapper {
position: relative;
}
.svgwrapper {
position: absolute;
z-index: -1;
}
</style>
<div class="svgwrapper" onClick="function();">
<object src="blah" />
</div>
b3ng0 wrote similar code but it does not work. z-index of parent must be auto.
When embedding same-origin SVGs using <object>, you can access the internal contents using objectElement.contentDocument.rootElement. From there, you can easily attach event handlers (e.g. via onclick, addEventListener(), etc.)
For example:
var object = /* get DOM node for <object> */;
var svg = object.contentDocument.rootElement;
svg.addEventListener('click', function() {
console.log('hooray!');
});
Note that this is not possible for cross-origin <object> elements unless you also control the <object> origin server and can set CORS headers there. For cross-origin cases without CORS headers, access to contentDocument is blocked.
Have you looked into using the CSS z-index property to make the container dev be "on top" of the svg? Because the div is (presumably) transparent, you will still see the image exactly as before.
This, I believe, is the best-practice, non-hack, intended way of solving your problem. z-index is only useful for elements that have a position property of fixed, relative, or, as you've heard, absolute. However, you don't actually have to move the object.
For example:
<style>
.svgwrapper {
position: relative;
z-index: 1;
}
</style>
<div class="svgwrapper" onClick="function();">
<object src="blah" />
</div>
For what it's worth, it would also be a little more elegant and safe to not use onClick at all, but instead to bind the click event using javascript. That's another issue altogether, though.
Assuming you don't need cross browser support (which is impossible without a plugin for IE), have you tried using svg as a background image?
Experimental stuff for sure, but thought I would mention it.
Perhaps what you're looking for is the SVG element's pointer-events property, which you can read about at the SVG w3C working group docs.
You can use CSS to set what happens to the SVG element when it is clicked, etc.
Click on SVG's <g> element in <object> with click event. Works 100%. Take a look on the nested javascript in <svg>. Don't forget to insert window.parent.location.href= if you want to redirect the parent page.
https://www.tutorialspoint.com/svg/svg_interactivity.htm
I wrapped the 'svg' tag in 'a' tag and put the onClick event in the 'a' tag
I had a similar issue: it only seems that the onclick event is not occurring, but it is firing twice
the svg tag had an onclick option, like: <svg ... onclick="someJsFunction() ...> it opens a dropdown menu, and had a class option named f.e. class-for-svg
the path (included in the svg tag) had no any class option,
in the other hand, I had a window.onclick function to close the dropdown when the user clicks on the somthing else, here the dropdown was clossing - when the object's class option matched to the svg's class option
so when I clicked on the path portion inside the svg tag - the window.onclick event accurred too, and because of the does not matching(to the class name), the dropdown was clossed imediatelly, and it seems that the onclick event is not happening )
in reality it happens twise, one opens, an the second closses the drop down
solution: add the same class option to the path tag too )
enjoy please )