Bordes: La propiedad border de CSS-3

El documento de la especificación oficial del W3C CSS Backgrounds and Borders Module Level 3 expone todo lo relacionado con bordes en CSS-3. En mi glosario XHTML 1.0 + CSS 2.1 expuse los bordes en CSS21 {border}. Las diferencias con CSS-3 se resumen a continuación:

El módulo de fondos y bordes CSS Backgrounds and Borders Module Level 3 se encuentra en fase CR Candidate Recommendation en la fecha en que escribo estos temas: 30 de Septiembre de 2011. También en esta fecha he probado los contenidos en los navegadores Firefox 7.0.1, Opera 11.51, Chrome 14.0 y Safari 5.0. Cuando mencione estos navegadores en la exposición de estos temas me estaré refiriendo a estas versiones. Tener en cuenta que lo que se expone como que no funciona para una determinada versión es posible que si lo haga en versiones más recientes cuando esté leyendo estos temas. En cuanto a Explorer he decidido ni siquiera molestarme en probarlo por ahora, aunque es posible que muchas cosas funcionen en IE9. En IE8 y anteriores nada de CSS-3 funcionará.

Esquinas redondeadas CSS-3 {border-radius}

Esta nueva propiedad {border-radius} de CSS-3 nos permite poner esquinas redondeadas a los bordes especificados con la propiedad CSS21 {border}. Realmente {border-radius} es la propiedad resumida de {border-X-radius} donde X puede ser top-right, top-left, bottom-right y bottom-left. Es decir, se declara cada esquina por separado. En este caso para cada esquina se da un valor compuesto de una pareja de longitudes y/o porcentajes. Estas dos medidas especifican los radios de una elipse, la primera el radio horizontal y la segunda el vertical, de tal forma que el borde se dibuja en base a esa elipse. Si se pasa un único valor se entiende que el segundo es igual y por tanto la elipse se convierte en un círculo.

La propiedad se puede resumir con {border-radius}, pasándose entonces de 1 a 4 valores para especificar la esquina superior izquierda, superior derecha, inferior derecha e inferior izquierda, en ese orden. Si hay menos de 4 valores, los que falten se van adjudicando siguiendo el sentido del reloj en el mismo orden en el de los valores que se pasen.

Es cuestión de hacer pruebas para ver esto. Aquí hay dos ejemplos. El primero tiene border-top-left-radius: 1em; border-top-right-radius: 1em;. El segundo tiene la resumida border-radius: 20px.

<div style="width: 10em; border: navy solid 1px;
padding: 0.5em; text-align: center; 
font: bold 1.2em 'Lucida Sans'; float: left;
background-color: navy; color: yellow;
border-top-left-radius: 1em;
border-top-right-radius: 1em;
">BORDER-RADIUS</div>

<div style="width: 10em; border: solix 1px; 
padding: 0.5em; text-align: center; margin-left: 15em;
border-radius: 20px;
">BORDER-RADIUS</div>

Ejemplo:

BORDER-RADIUS
BORDER-RADIUS

Es evidente que hay que especificar un tipo de borde para que border-radius le aplique la esquina redondeada. Un caso interesante se plantea cuando los radios de la elipse superan las medidas disponibles del contenedor apareciendo entonces una elipse completa para todo el contenedor. Aunque Safari no lo ejecuta en este caso ignorando totalmente la propiedad {border-radius}. Con otro estilo de bordes como el doble también Safari tiene algún problema en la definición de las esquinas:

<div style="width: 10em; border: solid 1px; 
padding: 0.5em; text-align: center; float: left;
border-radius: 100%;
">BORDER-RADIUS</div>

<div style="width: 10em; border: red double 5px; 
padding: 0.5em; text-align: center; margin-left: 15em;
border-radius: 1em;
">BORDER-RADIUS</div>

Ejemplo:

BORDER-RADIUS
BORDER-RADIUS

Submenú para laterales con bordes redondeados

Por último no puedo resistir a la tentación de cambiar los menús que aparecen en mi página de inicio con bordes redondeados con imágenes. Esto lo explico en cómo se hace un submenú, con un aspecto como el de esta imagen:

imagen submenú

Aunque Internet Explorer 8 no acepta los nuevos bordes redondeados, es posible que si lo haga la versión 9. En todo caso las versiones actuales del resto de navegadores si lo aceptan. Por lo tanto es el momento de hacer el cambio. La estructura HTML del submenú será ahora más simple:

<div class="sumenu-ejemplo">
    <h4>Título</h4>
    <ul>
        <li>Uno</li>
        <li>Dos</li>
        <li>Tres</li>
        <li>Cuatro</li>
    </ul>
</div>

El estilo CSS-3 se aplicará sobre esta estructura:

div.sumenu-ejemplo {
    margin-bottom: 0.5em;
    border-style: solid;
    border-color: rgb(49, 99, 98);
    border-left-width: 0.125em;
    border-right-width: 0.125em; 
    border-top-width: 0.5em;
    border-bottom-width: 0.5em;
    border-radius: 0.5em;
    box-shadow: 0 0.25em 0.1em 0.05em silver;
    -webkit-box-shadow: 0 0.25em 0.1em 0.05em silver;
    }
    
div.sumenu-ejemplo h4 {
    font-family: Arial;
    background-color: rgb(49, 99, 98);
    width: 100%;
    margin: 0;
    line-height: 0.8em;
    border-bottom: rgb(49, 99, 98) solid 0.5em;
    text-align: center; 
    color: white; 
     }        

div.sumenu-ejemplo ul {
    margin-left: 1.5em; 
    margin-top: 0; 
    margin-bottom: 0; 
    margin-right: 0; 
    padding-left: 0; 
    padding-right: 0; 
    padding-bottom: 0.2em;
    }
div.sumenu-ejemplo ul li {
    color: navy;
    margin-left: 0;
    font-size: 0.9em;
    }

Ponemos todas las longitudes proporcionales a la fuente de texto. El radio del borde debe ser igual que el grosor de los bordes superior e inferior. El borde superior se agranda anexando el encabezado <h4> con igual color de fondo. Le ponemos finalmente algo de sombra en el pie inferior. Safari necesita -webkit- para la sombra. El resto del estilo es parecido al que tenía en la versión anterior con imágenes. La simplicidad y efectividad ahora comparada con la versión con imágenes es más que evidente. El resultado es éste, al igual que los que aparecen en mi página de inicio y también en el índice de artículos.

Ejemplo:

Submenú CSS3

Título

  • Uno
  • Dos
  • Tres
  • Cuatro

Para los navegadores que no aceptan los nuevos bordes redondeados, se aplicarán los bordes antiguos de CSS-2.1, quedando por ejemplo en IE8 algo así como esta captura de pantalla. Por lo tanto aún queda aceptablemente bien y podemos seguir actualizando nuestras páginas con cosas nuevas.

submenú ie8

Bordes con imágenes resumido CSS-3 {border-image}

Esta propiedad resumida nos permite poner de una sóla vez un borde con imágenes. La sintaxis es:

border-image-source || 
border-image-slice 
[ / border-image-width ? [ / border-image-outset ]? ]? 
|| border-image-repeat

Esto lo podemos expresar como sigue:

  • {border-image-source}: Un archivo de imagen para el borde. Es un valor requerido o bien podemos pasar el valor none en cuyo caso se aplica el borde normal declarado con la propiedad {border}.
  • {border-image-slice}: Un recorte de la imagen para formar la matriz de laterales y esquinas. En CSS3 es un valor opcional con valor inicial 100%, pero para Firefox y otros navegadores es requerido (ver MDC border-image).
  • {border-image-width}: Opcionalmente junto al recorte podemos agregar una "/" y luego poner un ancho del borde de imagen. Es un valor opcional con valor inicial el propio ancho de la propiedad {border-width}.
  • {border-image-outset}: Si ponemos el ancho anterior opcionalmente también podemos poner una "/" (o dos barras "//" si obviamos la anterior) y luego esta extensión del ancho del borde. Es opcional pero los navegadores no lo admiten por ahora.
  • {border-image-repeat}: Opcionalmente podemos poner una repetición para el mosaico de imágenes en los laterales. Valor inicial es stretch. Los navegadores no admiten el valor space.

Hace algunos años cuando estudié el tema de los posicionamientos hice un ejemplo de un contenedor con bordes de imágenes. Se trataba de usar un conjunto de 8 imágenes una para cada porción del borde: esquina superior izquierda, lateral superior, esquina superior derecha, etc. Por lo tanto habían 8 archivos de imagen distintos esquina esquina esquina esquina esquina esquina esquina esquina, uno para cada porción empezando en la esquina superior izquierda y avanzando en el sentido de las agujas del reloj hasta el lateral izquierdo. No me preocupé por la calidad de las imágenes pues lo que pretendía era poder construir un contenedor con bordes personalizados con imágenes. Se construía en base a la propiedad {background} y a los posicionamientos absolutos de contenedores <div> que formaban las 8 porciones de esquinas y laterales de estos "falsos" bordes con imágenes.

En el enlace anterior puede consultar ese ejemplo y ver la gran cantidad de código que era necesario para montarlo. Y es que ahora CSS-3 lo hace más fácil con esta propiedad {border-image} que es precisamente para eso. En primer lugar necesitamos una matriz de imagen desde donde se tomarán cada una de las 8 porciones que necesitamos. Tomaré las que ya tenía y con un simple editor de imagen las uniré en un único archivo llamado bimg.gif:

bordeados

Será entonces una matriz de 45x45 píxeles con partes de 15x15 píxeles. En el ejemplo siguiente pondré un <div> con {border-image} y otro contenedor con el borde personalizado hecho como aquel ejemplo, pudiendo encontrar ese estilo en la cabecera de este documento. Para el de CSS-3 se incorpora todo el estilo con el elemento tal como sigue:

<!--  con border-image -->
<div id="con-border-image" style="width: 10em; height: 3em;
border: solid 15px; float: left;
-moz-border-image: url(ejemplos/bimg.gif) 15 round;
-webkit-border-image: url(ejemplos/bimg.gif) 15 round;
-o-border-image: url(ejemplos/bimg.gif) 15 round;      
">Con <code>border-image</code></div>

<!--  con background-image y posicionamientos absolutos -->
<div class="con-borde" style="width: 10em; height: 3em; 
margin-left: 15em; padding: 15px;">
    <div class="borde-sup"></div>
    <div class="borde-der"></div>
    <div class="borde-inf"></div>
    <div class="borde-izq"></div>
    <div class="esq-sup-izq"></div>
    <div class="esq-sup-der"></div>
    <div class="esq-inf-izq"></div>
    <div class="esq-inf-der"></div>
    Con <code>background-image</code>
</div>

Ejemplo:

Con border-image
Con background-image

La similitud es grande, pero sobre todo la facilidad con CSS-3 es más que evidente. La propiedad aún no es admitida por los navegadores escribiéndola como {border-image} y hay que anteponer -moz- para Firefox, -webkit- para Chrome-Safari y -o- para Opera.

Archivo de borde de imagen CSS-3 {border-image-source}

Una ruta como url(archivo) que referencia una imagen para ser usada como borde de imagen en lugar del estilo de borde dado por CSS21 {border-style}. El valor inicial será none. También tomará este valor computado en el caso de que la imagen no pueda ser presentanda, usándose entonces el estilo de bordes declarado con {border-style}.

Las propiedades parciales de la resumida {border-image} no están del todo implementadas en los navegadores actuales, por lo que se recomienda usar la propiedad resumida personalizada para cada navegador:

  • -moz-border-image para Firefox
  • -webkit-border-image para Safari y Chrome
  • -o-border-image para Opera

Recorte de borde imagen CSS-3 {border-image-slice}

Un recorte de porciones con números que representan píxeles por donde hay que localizar cada una de las 8 porciones para la esquina superior izquierda, lateral superior, esquina superior derecha, lateral derecho, esquina inferior derecha, lateral inferior, esquina inferior izquierda y lateral izquierdo. También admite porcentajes referidos al tamaño de la imagen. Serán de 1 a 4 valores (A B C D) que se aplican en el sentido de las agujas del reloj para dividir la imagen en 8 porciones. Realmente son 9, pues la porción del centro también es posible usarla como veremos más abajo.

border-image-slice

La sintaxis del valor es [número | porcentaje]{1,4} && fill?. Esto quiere decir que lleva de 1 a 4 valores, números enteros que serán píxeles o porcentajes y luego opcionalmente la palabra fill, con lo que se rellenará la imagen del cuadro número 9, es decir, el cuadro central de la matriz anterior. El valor inicial es 100% para cuando no se especifique ninguno, aunque los navegadores consultados requieren que siempre se especifique esta propiedad. Aunque las propiedades parciales no están implementadas en los navegadores, si lo está la resumida. En este ejemplo usamos la siguiente imagen matriz:

bolas

Se trata de una imagen de 60x60 píxeles con 8 bolas de diferentes colores. Vea como se reparten por las esquinas y lados haciendo un border-image-slice de 20 píxeles, lo que significa que recortamos 20 20 20 20, es decir, las cuatro rectas definen las 8 bolas de la imagen, cada una de 20x20 píxeles.

<div style="width: 11em; height: 3em;
border: solid 15px; 
-moz-border-image: url(ejemplos/matriz.gif) 20 round;
-webkit-border-image: url(ejemplos/matriz.gif) 20 round;
-o-border-image: url(ejemplos/matriz.gif) 20 round;                
"> </div>

Ejemplo:

 

Observe que aunque las bolas son de 20px, estableciendo el ancho del borde a 15px con border: solid 15px, las imágenes se adaptan a este ancho. El valor round debe ajustar a un número entero de bolas en cada lateral, escalando las imágenes si fuera preciso. Así funciona en Opera y Firefox, pero Chrome y Safari aplican el valor repeat en su lugar poniendo el número de imagenes que quepan, sin escalar y cortándolas si es preciso para llenar todo el espacio.

La palabra clave fill para rellenar el cuadro 9 de la matriz, es decir, el centro del contenedor, no funciona en ninguno de los navegadores consultados. Usando la siguiente matriz de imagen con un centro diferenciado:

bolas

y con este código:

<div style="width: 11em; height: 3em;
border: solid 20px; 
-moz-border-image: url(ejemplos/matriz2.gif) 20 fill round;
-webkit-border-image: url(ejemplos/matriz2.gif) 20 fill round;
-o-border-image: url(ejemplos/matriz2.gif) 20 fill round;                
"> </div>

Ejemplo:

 

Si aparece un borde verde será el del propio elemento, su propiedad border-style:solid 20px, pues el navegador no admitirá fill e ignorará toda la propiedad del borde de imagen.

Repetición de borde de imagen CSS-3{border-image-repeat}

Para repetir una imagen en los 4 laterales (no en las esquinas), con 1 o 2 entre los valores siguientes para los laterales horizontales y verticales:

  • stretch, con lo que se pondrá una única imagen ajustándola al lateral. Es decir, la imagen será estirada hasta completar el espacio de cada lateral. Este será el valor inicial cuando no se especifique ninguno.
  • repeat, la imagen se repite en forma de mosaico rellenando todo el espacio del lateral.
  • round, la imagen es repetida en forma de mosaico pero si falta o sobra espacio para una imagen más entonces todas las repeticiones son escaladas para que quepan un número entero de ellas.
  • space, la imagen es repetida en forma de mosaico pero sólo se podrán un número entero de ellas, distribuyéndolas uniformemente y rellenando con espacio lo restante.

Ejemplo con repeat se repite la imagen en forma de mosaico centrando el número de repeticiones y cortando las partes no enteras hasta rellenar todo el lateral.

<div style="width: 200px; padding: 0.5em; text-align: center;
border: solid 15px; 
-moz-border-image: url(ejemplos/matriz.gif) 20 repeat;
-webkit-border-image: url(ejemplos/matriz.gif) 20 repeat;
-o-border-image: url(ejemplos/matriz.gif) 20 repeat;                
">...</div>  

Ejemplo:

repeat

Con round se repite un número entero de bolas, escalando las imágenes para no cortar ninguna. Chrome y Safari aplican este valor como repeat.

Ejemplo:

round

Con space se supone que pondría un número entero de bolas, pero los navegadores parece que no admiten este valor. Al menos en la página de desarrollo de Mozilla MDC border-image vemos que no aparece (30-9-2011). En caso de que un valor no sea admitido por el navegador, toda la propiedad del borde de imagen (la propiedad resumida) es ignorada y se pone el borde según border:solid 20px, con el color verde dado por la propiedad color de primer plano para este ejemplo.

Ejemplo:

space

Con stretch una única imagen se estira en cada lateral:

Ejemplo:

stretch

Ancho de borde de imagen CSS-3 {border-image-width}

El borde con imagen es dibujado dentro de un área del borde de imagen. Es un área cuyos límites corresponden por defecto al borde del contenedor, lo que puede modificarse con {border-image-outset}. Los cuatro valores de border-image-width especifican las separaciones que serán usadas para dividir el área del borde de imagen en las 8 partes más la parte central. Representan distancias interiores desde el lado superior, derecha, inferior e izquierda del área respectivamente. Podemos dar porcentajes y serán relativos al tamaño del área del borde de imagen. Podemos dar números que representan múltiplos del valor computado para la propiedad {border-width}. O podemos dar el valor auto de tal forma que se ajusta a lo declarado con {border-image-slice}. El valor inicial es 1 por lo que será un múltiplo del {border-width} computado, es decir, este valor.

Veámos el ejemplo de las bolas de colores para modificar esta propiedad. En un ejemplo anterior el ancho del borde quedaba especificado por la propiedad border: solid 15px. Ahora seguimos manteniendo esto pero modificamos el ancho del área del borde de imagen para que las bolas sean de 40px:

<div style="width: 11em; height: 3em;
border: solid 15px; 
-moz-border-image: url(ejemplos/matriz.gif) 20 /40px round;
-webkit-border-image: url(ejemplos/matriz.gif) 20 /40px round;
-o-border-image: url(ejemplos/matriz.gif) 20 /40px round;                
"> </div>

Ejemplo:

 

Esta propiedad no ha funcionado en Opera. En Firefox, Safari y Chrome si funcionan, aunque estos dos últimos aplican el valor repeat para el valor dador round.

Extensión de borde de imagen CSS-3 {border-image-outset}

Extiende el área del borde de imagen más allá del borde de la caja en los 4 laterales superior, derecho, inferior e izquierdo. Permite de 1 a 4 valores que se aplican en ese orden como de costumbre: se van repartiendo los valores a los lados en ese orden (si hay menos valores que lados volvemos a empezar por la lista de valores).

Los valores pueden ser una longitud válida para el ancho del borde (la propiedad {border-width}) o un número entero que será un múltiplo de ese ancho de borde del elemento. El valor inicial es cero, con lo que el borde no será extendido.

A fecha de hoy (30-9-2011) se comprueba que no funciona en ninguno de los navegadors analizados. En la página de desarrollo de Mozilla MDC border-image tampoco sale este valor. Con la propiedad resumida hemos de especificar también el ancho del borde del área de imagen para poder incluir la extensión border-image-source borde-image-slice / border-image-width / border-image-outset border-image-repeat. O bien poner dos barras "//" si obviamos el border-image-outset. Aunque no lo he podido ver en funcionamiento (se verá el borde sólido verde según border:solid 15px), el código y el ejemplo es el siguiente:

<div style="width: 11em; height: 3em;
border: solid 15px; 
-moz-border-image: url(ejemplos/matriz.gif) 20 / 20px / 5px round;
-webkit-border-image: url(ejemplos/matriz.gif) 20 / 20px / 5px round;
-o-border-image: url(ejemplos/matriz.gif) 20 / 20px / 5px round;                
">...</div>

Ejemplo: