CSS, SVG or Canvas button, what format to choose?

Basic examples of the creation of new form objects to extend HTML 5.

To create new forms objects, three-way arise, and to get an idea of ​​their advantages and disadvantages, comparing the creation of a simple custom button in each format.

CSS 3 Button

These buttons are based on standard HTML tags, <button> for the first two, <input> for the last, and customized with a style sheet. We can combine HTML tags to create more complex objects such as a tree-view.

These buttons are CSS compatible with modern browsers.

<![if gte IE 9]> 
<link href="button.css" rel="stylesheet" type="text/css" />
<![endif]>

Canvas or SVG objects do not offer this possibility, they require to have recourse to alternative frameworks or plugins for older browsers.

SVG button

SVG button

SVG enables effects that we will be visually defined from a program like Inkscape. Unfortunately, the rendering could differ between browsers (the button is ugly on Chrome).

This demonstration is used primarily to see how the user can interact with an SVG object. This format is a mean to extend HTML 5 with new complex objects, allowing to interact with specific parts of the object. Simply attach event handlers to a tag, as it is done in this example.

Canvas button

A third possibility is the use of Canvas. It is easier to get a compatible rendering that in SVG, but to create composite interactive objects will be as complicated as creating a game. This format is appropriate to create new objects with little user interaction, such as a clock .

Conclusion: Choosing the right format for each use

It is difficult by creating a SVG or Canvas object to write code that is compatible with all browsers, each having its own interpretation of the implementation of these formats. Most of the work is therefore to solve the compatibility problems which is a waste of time, unless we find ready to use widgets.
It will be preferable to use:

Source codes

CSS

HTML code of CSS buttons:

<div class="buttonbar">  		
<button class="button red">Red button</button></li>
<button class="button blue">Blue button</button>
<input type="button" value="Gray input" class="button gray">
</div>

CSS code:

.button, .button:visited 
{
color: #fff;
text-decoration: none;
border-radius: 6px;
box-shadow: 1px 2px 4px 0 rgba(0,0,0,0.6);
text-shadow: 0 -1px 1px rgba(0,0,0,0.25);
border-bottom: 1px solid rgba(0,0,0,0.25);
border-right: 1px solid rgba(0,0,0,0.25);
position: relative;
cursor: pointer;
font-family:Calibri, Arial;
margin-left:4px;
font-size: 16px;
padding: 1px 8px 3px 8px;
} .button:active
{
top: 1px;
left:1px;
} .gray.button, .gray.button:visited
{
background-color:#CCCCCC;
box-shadow: inset 1px 1px 2px 0 rgba(255,255,255,0.6),
inset -1px -1px 1px 0 rgba(100,120,140,0.6),
1px 2px 4px 0 rgba(0,0,0,0.6);
color:#333;
border-left:1px solid #999;
border-top:1px solid #999;
text-shadow:none;
}
.gray.button:hover
{
background-color:#999;
color:#111;
}

Full CSS code. For blue and red buttons, only the color properties change.

SVG

SVG code:

<svg width="132" height="36"  id="svg1"
xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs
id="defs4">
<linearGradient id="gradient1">
<stop id="stop1" style="stop-color:#eee;stop-opacity:1;" offset="0" />
<stop id="stop2" style="stop-color:#aaa;stop-opacity:0;" offset="1" />
</linearGradient>
<linearGradient xlink:href="#gradient1" id="gradient2"
x1="0" y1="28" x2="0" y2="1"
gradientUnits="userSpaceOnUse" />
<filter id="drop-shadow" filterUnits="userSpaceOnUse" width="144" height="38">
<feGaussianBlur in="SourceAlpha" result="blur-out" stdDeviation="2" />
<feOffset in="blur-out" dx="2" dy="2"/>
<feBlend in="SourceGraphic" mode="normal"/>
</defs>
<g id="" class="buttonbar" onmousedown="svgDown()" onmouseover="svgOver()"
onmouseout="svgOut()" onmouseup="svgUp()">
<rect id="svgbutton" x="0" y="0" rx="8" ry="6" width="122" height="28"
stroke="#000066"
style="fill:url(#gradient2);fill-rule:evenodd;stroke:#000000; stroke-width:1px;stroke-linecap:butt; stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
filter="url(#drop-shadow)"
/>
<text x="28" y="18" fill="black"
font-family="Calibri, Arial" font-size="15" font-weight="500">
SVG button
</text>
<g>
</svg>

JavaScript code associated with the SVG code:

function svgOver()
{
document.getElementById("stop2").setAttribute('style', "stop-color:#000;stop-opacity:0;");
}
function svgOut()
{
document.getElementById("stop2").setAttribute('style', "stop-color:#666;stop-opacity:0;");
}
function svgDown()
{
var button= document.getElementById("svg1");
button.style.margin="1px 0 0 1px";
var x = document.getElementById("svgStorage");
x.innerHTML="Clicked on SVG button";
}
function svgUp()
{
var button= document.getElementById("svg1");
button.style.margin="0";
var x = document.getElementById("svgStorage");
x.innerHTML="";
}

We associate a function that the mouse moves over the button or left, the button is pressed (svgDown) or released (svgUp).

Canvas

Canvas code:

<canvas id="mycanvas" width="128" height="36"
onmousedown="canvasDown(this)" onmouseup="canvasUp(this)"
onmouseover="canvasOver()" onmouseout="canvasOut()">
</canvas>

<script>
canvasOut();
</script>

JavaScript code to draw the button in Canvas:

function makeButton(x, y, w, h, radius, label, color)
{
var canvas = document.getElementById("mycanvas");
var context = canvas.getContext("2d");
// clear background
context.beginPath();
context.fillStyle="white";
context.fillRect(0,0, 126, 36);
// draw button
var r = x + w;
var b = y + h;
context.moveTo(x+radius, y);
context.lineTo(r-radius, y);
context.quadraticCurveTo(r, y, r, y+radius);
context.lineTo(r, y+h-radius);
context.quadraticCurveTo(r, b, r-radius, b);
context.lineTo(x+radius, b);
context.quadraticCurveTo(x, b, x, b-radius);
context.lineTo(x, y+radius);
context.quadraticCurveTo(x, y, x+radius, y);
// background gradient
var backgrad = context.createLinearGradient(1,1,0,30);
backgrad.addColorStop(0, '#5EF');
backgrad.addColorStop(0.5, color);
context.fillStyle = backgrad;
// drop shadow
context.shadowBlur = 3;
context.shadowOffsetX = 2;
context.shadowOffsetY = 2;
context.shadowColor = "#669";
context.fill();
// the following lines before stroke are required for Chrome
context.shadowBlur = 0;
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.stroke();
// label with shadowing
context.beginPath();
context.font = "12pt Calibri,Arial";
context.fillStyle = "#FFF";
context.shadowBlur = 0;
context.shadowOffsetX = -1;
context.shadowOffsetY = -1;
context.shadowColor = "#669";
context.fillText(label, x+w*0.1, y+h*0.66);
}

Code associated with the events:

function canvasUp(button)
{
button.style.margin="0";
document.getElementById("canvasStorage").innerHTML="";
}
function canvasDown(button)
{
button.style.margin="1px 0 0 1px";
document.getElementById("canvasStorage").innerHTML="Clicked on Canvas button";
}
function canvasOver()
{
makeButton(0,0,120,28,8, "Canvas button", '#19B');
}
function canvasOut()
{
makeButton(0,0,120,28,8, "Canvas button", '#2AC');
}

These are the same events for SVG, but this time we must redraw the button to change the colors completely.

Full JavaScript code.

See also