Esquinas redondeadas sin imágenes

Automatizando el proceso

Si tenemos que copiar todo ese bloque de HTML por cada elemento de la página que queramos redondear, al final acabaremos con una página tan pesada que incluso usando imágenes tardará menos en cargar. Por ello, la solución es utilizar JavaScript para generar dinámicamente las cuatro capas en aquellos elementos que nosotros queramos.

Para esta solución podríamos llamar a una función por cada elemento de la página que quisiéramos redondear, pero lo podemos hacer muchísimo mejor: vamos a hacer una función que recorra todos los elementos de la página y redondee automáticamente aquellos que tengan algún tipo de marca. Ni siquiera vamos a llamar a esta función, sino que el propio script agregará la función al evento onLoad de la página.

Vamos a comenzar viendo cómo recorreríamos automáticamente todos los elementos de la página:

  1. /*
  2.  * Agregamos la función al evento onLoad de la página.
  3.  * De esta forma, sólo tendremos que incluir el fichero
  4.  * JavaScript y nada más.
  5.  /
  6. window.addEventListener
  7. ?
  8. window.addEventListener("load", procesarDocumento, false)
  9. :
  10. window.attachEvent("onload", procesarDocumento);
  11.  
  12. function procesarDocumento()
  13. {
  14. // Si no podemos usar el DOM, no seguimos.
  15. if (!document.getElementById)
  16. {
  17. return;
  18. }
  19.  
  20. // Vamos a obtener un array con todos los elementos
  21. // de la página, y a continuación miraremos uno por uno
  22. // a ver cuáles tienen la marca que buscamos.
  23. var a = document.getElementsByTagName();
  24. for (i = 0; i != a.length; i++)
  25. {
  26. if (a[i].className != ‘’)
  27. {
  28. // buscarClase es la función que usaremos
  29. // para comprobar si el elemento tiene la
  30. // marca.
  31. if (buscarClase(a[i]))
  32. {
  33. redondear(a[i]);
  34. }
  35. }
  36. }
  37. }

Veamos ahora la función buscarClase para explicar qué es lo que vamos a buscar:

  1. function buscarClase(o)
  2. {
  3. var re = /\{rounded .+ .+\}/i;
  4. // Comprobaremos si el atributo CLASS contiene la marca.
  5. return re.test(o.className);
  6. }

Voy a explicar qué estamos buscando aquí. Para marcar una caja de forma que la función redondear la procese, buscamos algo como esto en el atributo CLASS:

{rounded estiloDelFondo colorDelBorde}

Donde estiloDelFondo puede tomar cualquier valor que se pueda poner en el atributo background de CSS, y colorDelBorde es cualquier color soportado por CSS. El hecho de que ponga estilo y no color en la parte del fondo implica que se pueden poner también imágenes de fondo en las cajas, siempre siendo conscientes de que ese mismo estilo se aplicará también a cada una de las capas que se generen.

Así, aplicando esta técnica a la caja que usamos antes obtendríamos lo siguiente:

  1. <div style="padding: 0px 5px" class="{rounded white silver}">
  2. Esto es una caja.
  3. </div>

Veámoslo en acción:

Esto es una caja.

Ahí está. La función redondear tomará los valores del color de fondo y el borde y generará las capas por encima y por debajo automáticamente.

Este es el código de la función:

  1. function redondear(o)
  2. {
  3. /*
  4. * Vamos a aplicar una expresión regular
  5. * para obtener los valores del fondo y del borde.
  6. /
  7. var re = /\{rounded (.span class=“br0”>) (.)\}/i;
  8. var m = re.exec(o.className);
  9. var fondo = m[1];
  10. var borde = m[2];
  11.  
  12. /
  13. * Quitamos la marca de la clase del elemento
  14. * para no procesarla de nuevo.
  15. /
  16. o.className = o.className.replace(re, ‘’);
  17.  
  18. /
  19. * Le quitamos los márgenes superior e
  20. * inferior a la caja, para que las capas queden
  21. * pegadas a ella.
  22. /
  23. o.style.marginTop = ‘0px’;
  24. o.style.marginBottom = ‘0px’;
  25.  
  26. // Este es el contenedor superior.
  27. var rtop = document.createElement(‘DIV’);
  28. rtop.style.fontSize = ‘1px’;
  29. rtop.style.height = ‘5px’;
  30. rtop.style.display = ‘block’;
  31. rtop.style.margin = ‘0px’;
  32. rtop.style.padding = ‘0px’;
  33.  
  34. /
  35. * El contenedor inferior es exactamente igual,
  36. * así que creamos una copia del superior.
  37. /
  38. var rbot = rtop.cloneNode(false);
  39.  
  40. /
  41. * Esta es la capa más externa. Las capas van
  42. * numeradas desde fuera hacia dentro.
  43. /
  44. var r1 = document.createElement(‘SPAN’);
  45. r1.style.fontSize = ‘1px’;
  46. r1.style.height = ‘0px’;
  47. r1.style.display = ‘block’;
  48. r1.style.borderTop = ‘1px solid ‘ + borde;
  49. r1.style.marginLeft = ‘5px’;
  50. r1.style.marginRight = ‘5px’;
  51. r1.style.overflow = ‘hidden’;
  52.  
  53. var r2 = document.createElement(‘SPAN’);
  54. r2.style.fontSize = ‘1px’;
  55. r2.style.height = ‘1px’;
  56. r2.style.display = ‘block’;
  57. r2.style.borderLeft = ‘2px solid ‘ + borde;
  58. r2.style.borderRight = ‘2px solid ‘ + borde;
  59. r2.style.background = fondo;
  60. r2.style.marginLeft = ‘3px’;
  61. r2.style.marginRight = ‘3px’;
  62. r2.style.overflow = ‘hidden’;
  63.  
  64. var r3 = document.createElement(‘SPAN’);
  65. r3.style.fontSize = ‘1px’;
  66. r3.style.height = ‘2px’;
  67. r3.style.display = ‘block’;
  68. r3.style.borderLeft = ‘1px solid ‘ + borde;
  69. r3.style.borderRight = ‘1px solid ‘ + borde;
  70. r3.style.background = fondo;
  71. r3.style.marginLeft = ‘2px’;
  72. r3.style.marginRight = ‘2px’;
  73. r3.style.overflow = ‘hidden’;
  74.  
  75. var r4 = document.createElement(‘SPAN’);
  76. r4.style.fontSize = ‘1px’;
  77. r4.style.height = ‘1px’;
  78. r4.style.display = ‘block’;
  79. r4.style.borderLeft = ‘1px solid ‘ + borde;
  80. r4.style.borderRight = ‘1px solid ‘ + borde;
  81. r4.style.background = fondo;
  82. r4.style.marginLeft = ‘1px’;
  83. r4.style.marginRight = ‘1px’;
  84. r4.style.overflow = ‘hidden’;
  85.  
  86. /
  87. * Insertamos las cuatro capas en el
  88. * contenedor superior.
  89. /
  90. rtop.appendChild(r1);
  91. rtop.appendChild(r2);
  92. rtop.appendChild(r3);
  93. rtop.appendChild(r4);
  94.  
  95. /
  96. * Insertamos copias de las cuatro capas
  97. * en el contenedor inferior.
  98. /
  99. rbot.appendChild(r4.cloneNode(false));
  100. rbot.appendChild(r3.cloneNode(false));
  101. rbot.appendChild(r2.cloneNode(false));
  102. rbot.appendChild(r1.cloneNode(false));
  103.  
  104. // Este es el contenedor de la caja.
  105. var rbody = document.createElement(‘DIV’);
  106. rbody.style.borderLeft = ‘1px solid ‘ + borde;
  107. rbody.style.borderRight = ‘1px solid ‘ + borde;
  108. rbody.style.marginTop = ‘0px’;
  109. rbody.style.marginBottom = ‘0px;’;
  110. rbody.style.background = fondo;
  111.  
  112. o.parentNode.insertBefore(rbody, o);
  113. rbody.appendChild(o);
  114.  
  115. /
  116. * Colocamos los contenedores superior e
  117. * inferior justo antes y después del de la caja.
  118. */
  119. rbody.parentNode.insertBefore(rtop, rbody);
  120. if (rbody.nextSibling)
  121. {
  122. rbody.parentNode.insertBefore(rbot, rbody.nextSibling);
  123. }
  124. else
  125. {
  126. rbody.parentNode.appendChild(rbot);
  127. }
  128. }

A grandes rasgos, lo que hace esta función es crear tres DIVs contenedores y colocar las capas superiores en el primero, la caja en el segundo y las capas inferiores en el tercero.

No está mal, ¿verdad? Sólo hay alguna que otra pega:

  • Como no podemos definir nuestros propios atributos CSS, no podemos poner esto en una hoja de estilos aparte. Como resultado, estamos mezclando presentación y datos.
  • Usando este script se redondearán las cuatro esquinas, y no hay forma de redondear sólo algunas.

Lógicamente, el siguiente paso es permitir redondear sólo ciertas esquinas de la caja. Con algunos cambios al script, podemos hacer que sólo se redondeen las esquinas de arriba, o las de abajo, o sólo las de un lado. Pero eso lo veremos en la siguiente página.