¡Ay! Todas estas soluciones me han llevado a la conclusión de que la casilla de verificación HTML apesta si quieres darle un estilo.
Como advertencia, esta no es una implementación de CSS. Solo pensé en compartir la solución que se me ocurrió en caso de que alguien más pueda encontrarla útil.
Utilicé el HTML5 canvas
elemento .
La ventaja de esto es que no tiene que usar imágenes externas y probablemente pueda ahorrar algo de ancho de banda.
La desventaja es que si un navegador por alguna razón no puede representarlo correctamente, entonces no hay respaldo. Aunque si esto sigue siendo un problema en 2017 es discutible.
Actualizar
El viejo código me pareció bastante feo, así que decidí volver a escribirlo.
Object.prototype.create = function(args){
var retobj = Object.create(this);
retobj.constructor(args || null);
return retobj;
}
var Checkbox = Object.seal({
width: 0,
height: 0,
state: 0,
document: null,
parent: null,
canvas: null,
ctx: null,
/*
* args:
* name default desc.
*
* width 15 width
* height 15 height
* document window.document explicit document reference
* target this.document.body target element to insert checkbox into
*/
constructor: function(args){
if(args === null)
args = {};
this.width = args.width || 15;
this.height = args.height || 15;
this.document = args.document || window.document;
this.parent = args.target || this.document.body;
this.canvas = this.document.createElement("canvas");
this.ctx = this.canvas.getContext('2d');
this.canvas.width = this.width;
this.canvas.height = this.height;
this.canvas.addEventListener("click", this.ev_click(this), false);
this.parent.appendChild(this.canvas);
this.draw();
},
ev_click: function(self){
return function(unused){
self.state = !self.state;
self.draw();
}
},
draw_rect: function(color, offset){
this.ctx.fillStyle = color;
this.ctx.fillRect(offset, offset,
this.width - offset * 2, this.height - offset * 2);
},
draw: function(){
this.draw_rect("#CCCCCC", 0);
this.draw_rect("#FFFFFF", 1);
if(this.is_checked())
this.draw_rect("#000000", 2);
},
is_checked: function(){
return !!this.state;
}
});
Aquí hay una demostración funcional .
La nueva versión utiliza prototipos y herencia diferencial para crear un sistema eficiente para crear casillas de verificación. Para crear una casilla de verificación:
var my_checkbox = Checkbox.create();
Esto agregará inmediatamente la casilla de verificación al DOM y conectará los eventos. Para consultar si una casilla de verificación está marcada:
my_checkbox.is_checked(); // True if checked, else false
También es importante tener en cuenta que me libré del bucle.
Actualización 2
Algo que no mencioné en la última actualización es que usar el lienzo tiene más ventajas que solo hacer una casilla de verificación que se ve como usted quiera. También puede crear casillas de verificación de múltiples estados , si así lo desea.
Object.prototype.create = function(args){
var retobj = Object.create(this);
retobj.constructor(args || null);
return retobj;
}
Object.prototype.extend = function(newobj){
var oldobj = Object.create(this);
for(prop in newobj)
oldobj[prop] = newobj[prop];
return Object.seal(oldobj);
}
var Checkbox = Object.seal({
width: 0,
height: 0,
state: 0,
document: null,
parent: null,
canvas: null,
ctx: null,
/*
* args:
* name default desc.
*
* width 15 width
* height 15 height
* document window.document explicit document reference
* target this.document.body target element to insert checkbox into
*/
constructor: function(args){
if(args === null)
args = {};
this.width = args.width || 15;
this.height = args.height || 15;
this.document = args.document || window.document;
this.parent = args.target || this.document.body;
this.canvas = this.document.createElement("canvas");
this.ctx = this.canvas.getContext('2d');
this.canvas.width = this.width;
this.canvas.height = this.height;
this.canvas.addEventListener("click", this.ev_click(this), false);
this.parent.appendChild(this.canvas);
this.draw();
},
ev_click: function(self){
return function(unused){
self.state = !self.state;
self.draw();
}
},
draw_rect: function(color, offsetx, offsety){
this.ctx.fillStyle = color;
this.ctx.fillRect(offsetx, offsety,
this.width - offsetx * 2, this.height - offsety * 2);
},
draw: function(){
this.draw_rect("#CCCCCC", 0, 0);
this.draw_rect("#FFFFFF", 1, 1);
this.draw_state();
},
draw_state: function(){
if(this.is_checked())
this.draw_rect("#000000", 2, 2);
},
is_checked: function(){
return this.state == 1;
}
});
var Checkbox3 = Checkbox.extend({
ev_click: function(self){
return function(unused){
self.state = (self.state + 1) % 3;
self.draw();
}
},
draw_state: function(){
if(this.is_checked())
this.draw_rect("#000000", 2, 2);
if(this.is_partial())
this.draw_rect("#000000", 2, (this.height - 2) / 2);
},
is_partial: function(){
return this.state == 2;
}
});
Modifiqué ligeramente el Checkbox
usado en el último fragmento para que sea más genérico, lo que hace posible "extenderlo" con una casilla de verificación que tiene 3 estados. Aquí hay una demostración . Como puede ver, ya tiene más funcionalidad que la casilla de verificación incorporada.
Algo a tener en cuenta al elegir entre JavaScript y CSS.
Código viejo y mal diseñado
Demo de trabajo
Primero, configura un lienzo
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
checked = 0; // The state of the checkbox
canvas.width = canvas.height = 15; // Set the width and height of the canvas
document.body.appendChild(canvas);
document.body.appendChild(document.createTextNode(' Togglable Option'));
A continuación, idee una forma de actualizar el lienzo.
(function loop(){
// Draws a border
ctx.fillStyle = '#ccc';
ctx.fillRect(0,0,15,15);
ctx.fillStyle = '#fff';
ctx.fillRect(1, 1, 13, 13);
// Fills in canvas if checked
if(checked){
ctx.fillStyle = '#000';
ctx.fillRect(2, 2, 11, 11);
}
setTimeout(loop, 1000/10); // Refresh 10 times per second
})();
La última parte es hacerla interactiva. Afortunadamente, es bastante simple:
canvas.onclick = function(){
checked = !checked;
}
Aquí es donde podría tener problemas en IE, debido a su extraño modelo de manejo de eventos en JavaScript.
Espero que esto ayude a alguien; Definitivamente se adaptaba a mis necesidades.