domingo, 16 de septiembre de 2012

CSS: Algunas curiosidades de 'margin collapsing'

Lo que en CSS se llama margin collapsing consiste en que cuando los margenes verticales de dos elementos de bloque se tocan, se fusionan en uno solo, del tamaño del mayor.

No encuentro una buena traducción en español así que hablaremos de margenes que se fusionan o se combinan.

Este comportamiento hace que, por ejemplo, si definimos que los párrafos tengan un margen de 10px, queden separados exactamente 10 pixels y no 20, que sería la suma del margen inferior del primer párrafo y el margen superior del segundo.



Este es el caso más sencillo y resulta fácil de comprender, pero cuando el fusionado de márgenes ocurre con elementos anidados, da lugar a situaciones un poco más confusas.

Elementos anidados

La combinación automática de margenes también se puede dar con un elemento dentro de otro. Los margenes del elemento padre y el elemento hijo se fusionan en uno sólo.

Por ejemplo, tenemos el siguiente HTML:
Se trata símplemente de un DIV dentro de otro, cada uno con su margen. Si no hubiera combinación de márgenes, lo veríamos así:



 Como vemos en la imagen superior, los márgenes top y bottom de los dos elementos están en contacto, por lo que se van a fusionar quedando sólo un margen, el mayor de los dos ( en este caso el de 30px):

 

El DIV interior queda sin margen. El DIV exterior queda con un margen de 30px.

 Lo curioso de este caso es que aunque el DIV interior sea el que tiene el margen más grande, el margen resultante se va a aplicar al DIV exterior. Cambiemos los márgenes en el HTML:
Si los margenes no se fusionan lo veríamos así:



 Igual que antes, tenemos dos DIVs cuyos márgenes están en contacto, por lo tanto se fusionan y queda un sólo margen del valor más grande.



 La conclusión es que el margen resultante se aplica siempre al elemento más externo que participa en la combinación. El DIV naranja siempre se queda sin margen. No importa cuál sea el valor que prevalece, se aplica siempre al elemento exterior.

¿Cómo evitamos que ocurra?


Es importante resaltar que para que se produzca esta combinación de márgenes, estos se tiene que tocar. Podemos evitar que ocurra si hay algo entre ellos. Basta con poner un borde o un *padding* que los separe:



 Además, cuando los elementos de bloque tienen alguna de las siguientes características, no se produce la combinación de márgenes:

  • Elementos flotantes
  • Elementos con posición absoluta
  • Elementos inline-block
  • Elementos con overflow diferente de visible. Sus márgenes no se fusionan con elementos hijo
  • Elementos con clear


References:
CSS - Auto-height and margin-collapsing
Understand CSS margins collapsing
CSS Tutorial - Margins Collapsing
Collapsing margins

viernes, 14 de septiembre de 2012

Nunca habrá CSS4

Muy clarificadora esta entrada, del blog de un miembro del grupo de trabajo de CSS en el W3C, sobre el nuevo formato modular de los estándares de CSS y porqué no tiene sentido hablar de CSS4.

CSS2.1 fué el último estandar que definía una versión completa de CSS. El grupo se dio cuenta de que continuar con versiónes monolíticas era un proceso muy lento y muy dificil de mantener. Decidieron dividirlo en módulos independientes que evolucionan a su propio ritmo y tienen su propio número de versión ( Selectors, Colors, Backgrounds and Borders, Media Queries, etc ). Cada uno de estos módulos es o será un estándar (una recomendación, para hablar con propiedad).

CSS3 es en realidad un nombre genérico para referirse a CSS posterior a CSS2.1 pero no podemos hablar de CSS de nivel 3 como una recomendación del W3C completa. Algunos módulos han empezado en el nivel 3 (si se basan en CSS2.1), otros han empezado en el 1 y otros van ya por el 4. Todos ellos forman parte de CSS3.

miércoles, 12 de septiembre de 2012

4 puntos sencillos para hacer nuestra web más rápida

Chris Coyer explica en el vídeo "Let’s Do Simple Stuff to Make Our Websites Faster" cuatro puntos importantes y sencillos para mejorar el rendimiento de nuestra web:
  1. Activar siempre la compresión HTTP  en el servidor.
  2. Cachear siempre que sea posible, tanto en el cliente como en el servidor.
  3. Optimizar las imágenes. Hay algunas herramientas especificas para esto.
  4. Combinar nuestros JS y CSS en el menor número de ficheros posible.
Aproximadamente el 80% del retardo que percibe el usuario final es debido a tareas de front-end, por lo tanto, es muy importante prestar especial atención a la optimización de la parte cliente (fuente: Steve Souders).

Estos cuatro puntos requieren muy poco esfuerzo y pueden tener un impacto enorme en el rendimiento de nuestra aplicación web.

Con el punto 1 hacemos que el servidor comprima los ficheros antes de enviarlos. El navegador los descomprime cuando lo recibe. Este proceso es rapidísimo y, en general,  siempre es mejor habilitar esta opción en el servidor.

Por otro lado, cachear, especialmente en el cliente, es importante porque la petición/envío HTTP de ficheros es lo más lento.
"La petición HTTP más rápida es la que no se hace"
Este es también el objetivo del último, evitar peticiones HTTP innecesarias al concatenar varios ficheros javascript o css.

domingo, 9 de septiembre de 2012

CSS: Pseudo-clases y pseudo-elementos

Los pseudo-elementos y las pseudo-clases se definen para poder aplicar estilos en algunos elementos, o partes de un elemento, en casos especiales que no quedan cubiertos con los selectores habituales. Nos permiten seleccionar, por ejemplo, la primera letra de una línea, la primera línea de un párrafo, un link cuando ya ha sido pulsado, etc.
La sintaxis es la misma en los dos casos:

 a:visited {
 /*esto es una pseudo-clase*/
 }

p:first-line {
 /*esto es un pseudo-elemento*/
 }
 
CSS3 introduce una diferencia, recomienda utilizar “::” para los pseudo elementos, para diferenciarlos de las pseudo clases:

 a:visited {
 /*esto es una pseudo-clase*/
 }

p::first-line {
 /*esto es un pseudo-elemento*/
 }
 
De todas formas el mismo estándar especifica que los navegadores deben continuar soportando la notación anterior para evitar problemas de compatibilidad con código CSS antiguo, al menos para los pseudo-elementos definidos en CSS1 y CSS2 ( :first-line, :first-letter, :before and :after ).

pseudo-clases

Seleccionan un elemento que cumple alguna condición o estado determinado, por ejemplo un link cuando el ratón está encima ( a:hover) o un elemento cuando es el primero dentro del elemento padre ( li:first-child). Podría ser similar a aplicar una clase temporal a un elemento en un estado determinado.

Pseudo-clases especificas para enlaces :link y :visited

 
 a:link { color: blue; }
 
Aplica a todos los enlaces que todavía no han sido visitados. Aparecerían en color azul.
 
 a:visited { color: red; }
 
Aplica a los enlaces que ya han sido visitados. Aparecerían en color rojo.

Pseudo-clases dinámicas :hover, :active, :focus

Permiten cambiar el estilo en respuesta a alguna acción del usuario. Se utilizan a menudo en los enlaces, como las anteriores, pero pueden utilizarse en otros elementos.
 
 button:hover { color: green; }
 
Define un estilo que se muestra mientras el cursos está sobre el elemento. Es muy utilizado en enlaces y botones para hacer un ligero cambio de estilo que muestra claramente sobre que opción del menú nos encontramos.
 
 a:active { color: orange; }
 
Define un estilo diferente durante el momento en el que el elemento está siendo pulsado.
input:focus{ background-color:yellow; }
Se aplica a un elemento cuando recibe el foco.

:first-child

Selecciona un elemento sólo cuando es el primer hijo del elemento padre. Por ejemplo, la siguiente declaración:
p:first-child { background:yellow; }

Se aplicará a todos los párrafos que sean el primer elemento dentro de un contenedor. Si tenemos varios divs para dividir la página en columnas, los primeros párrafos de cada columna aparecerán en amarillo.

Para hacer que el primer elemento de una lista aparezca siempre en rojo:
li:first-child{ color: red; }

Lenguaje :lang

CSS nos permite seleccionar un elemento basandonos en el lenguaje que se ha definido mediante el atributo lang ( lang=“es”). Si tuvieramos dos párrafos definidos de la siguiente forma:
 

Esto es una casa

This is a house

Podríamos seleccionarlos y darles estilos diferentes:
 
p:lang(es) { color: red; }
p:lang(en) { color: blue; }

Pseudo-classes de CSS3

El nuevo estándar añade una cantidad importante de pseudo-clases nuevas a las que dedicaré un post en detalle más adelante ( :target, :root, :empty, :only-child, :only-of-type, :last-child, :nth-child, etc).

pseudo-elementos

Permiten seleccionar ciertos ‘elementos virtuales’ que no existen como tales en el DOM, por ejemplo la primera linea de texto en un párrafo ( p:first-line) o la primera letra de una línea (p:first-letter).

:first-line y :first-letter

Permiten seleccionar la primera línea de un elemento y la primera letra de un elemento, respectivamente.

p:first-line { color: gray; }
p:first-letter { text-transform: uppercase; }
Estas dos reglas CSS harían que la primera línea de cada párrafo fuera siempre de color gris y que la primera letra de cada párrafo aparezca en mayúsculas.

Estos dos pseudo-elementos sólo pueden aplicarse a elementos de bloque y a celdas de una tabla. No pueden aplicarse a un span, por ejemplo.

:before y :after

Se utilizan para insertar contenido, generado en nuestro CSS, al principio o al final de un elemento existente. Podemos también definir el estilo de este nuevo contenido dentro de la misma regla.

La propiedad content sirve para definir el contenido nuevo que se añade.

Por ejemplo, si tenemos una lista de artículos, podriamos utilizar el siguiente código CSS para colocar una indicación de NEW delante y detras de los elementos nuevos:

 
li.new:before {
    content: "NEW - ";
    background-color: green;
}

li.new:after {
    content: " - NEW";
    background-color: green;
}

Todos los elementos de la lista a los que coloquemos la clase “new” apareceran con ese texto extra para llamar la atención.

Cuidado al colocarlos separados por comas

Al utilizar estos elementos en nuestra hoja de estilos conviene tener en cuenta que, si los colocamos en una regla de CSS junto con otros selectores, separados por comas, el navegador que no soporte el pseudo-elemento ignorará los siguientes elementos de la lista, sin aplicarles el estilo.

En el siguiente ejemplo:

p:last-child, p.special {
 /* mis estilos */
}

IE8 no soporta last-child ( de CSS3) por lo que salta al final de la lista y tampoco aplica el estilo a los párrafos p.special.

References:
W3C CSS2 Pseudo-elements and pseudo-classes

miércoles, 5 de septiembre de 2012

CSS: Para qué sirve vertical-align

Probablemente todos hemos intentado alguna vez utilizar vertical-align para centrar verticalmente un contenido ( por ejemplo, un texto ) dentro de un div.


En la imagen anterior, aunque apliquemos vertical-align: middle al div contenedor o al bloque de texto, no va cambiar nada. En los dos casos el navegador ignora esta propiedad porque no aplica a esta situación.

Entonces, ¿para qué sirve vertical-align?

Esta propiedad se define en el estándar CSS2 del W3C como aplicable sólo a elementos inline y table-cell. Esta es la razón por la que no funciona para centrar el ejemplo anterior, porque no puede aplicarse a elementos de bloque.

Además, por si el nombre no era ya bastante confuso, la propiedad tiene diferente significado según se aplique a elementos inline o a elementos con display: table-cell, por lo que veremos los dos casos por separado.

Los valores que puede tomar son:
Valores: baseline | top |  bottom | text-top | text-bottom | middle | sub | super | <porcentaje %> | <longitud (px, cm, etc)> | inherit

vertical-align para elementos inline

Sirve para establecer la posición vertical de un elemento con respecto a la línea en la que se encuentra.
En la siguiente figura podemos ver 6 líneas imaginarias que son importanes para entender lo que significa cada uno de los valores de esta propiedad:


Las líneas top y bottom quedan siempre por encima y por debajo, respectivamente, de todo el contenido. Si no hay imágenes, estas líneas pueden coincidir con text-top y text-bottom.

Las líneas text-top y text-bottom quedan por encima y por debajo, respectivamente, del punto más alto (o bajo) del texto, incluyendo símbolos y acentos.

La línea middle se coloca justo en el centro de la altura de las letras minúsculas (se toma la letra ‘x’ como referencia).

Baseline es la línea sobre la que se apoya el texto.

En los siguientes ejemplos veremos cómo se alinea una imagen y un texto (en gris) con respecto a una línea de texto sin modificar (en negro), al cambiarles el vertical-align.

El HTML sería este:
 
  This is the default linedefault alignment 
  


Al elemento <p> le pondremos un borde azul, a los dos elementos que modificaremos con el vertical-align les ponemos borde naranja y al texto por defecto del párrafo, un borde gris.

Sin ningún vertical-align, se vería así:


Para cada uno de los valores posibles de la propiedad tendríamos:

baseline


Este caso es igual a la imagen sin vertical-align que veíamoss arriba, porque este es el valor que se muestra por defecto. La baseline del texto en gris y la base de la imagen se alinean con la baseline del texto sin modificar del elemento padre ( el <p>).


top


La parte superior de los elementos se alinean respecto al punto más alto de la línea ( sea imagen o texto ).

 

bottom


La parte inferior de los elementos se alinean respecto al punto más bajo de la línea ( sea imagen o texto ).

text-top


Los elementos se alinean con el punto más alto del texto. Es importante tener en cuenta que quizá la letra que tiene el punto más alto en nuestra fuente no aparece en nuestro texto. Aun así, la colocación se realiza respecto a ese punto más alto. Las letras más altas normalmente son las mayúsculas acentuadas.


text-bottom


Caso apuesto a text-top, los elementos se alinean con la parte más baja del texto. No es lo mismo que baseline porque en este caso vamos más abajo, incluyendo las líneas que bajan por debajo de la línea de base ( letras como p, j, g, etc).


middle


En este caso el navegador trata de alinear el centro vertical de los elementos con el centro del texto del padre ( el párrafo <p>).

 Lo que los navegadores hacen es alinear el centro vertical del elemento (de su caja) con la línea de base ( baseline ) del texto del padre más la mitad de la altura de la x. Visualmente puede no ser exactamente lo que esperamos porque, al no haber letras con partes descendentes, parece un poco descentrado.

super


Se utiliza para posicionar algo como superíndice.

sub


Se utiliza para posicionar algo como subíndice.

porcentaje


Eleva la posición del elemento en el porcentaje indicado. Es un porcentaje de la altura de la caja del propio elemento que tiene el vertical-align, por eso la imagen y el texto están a alturas diferentes. El valor puede ser negativo, en ese caso la posición baja. El valor 0% corresponde a la baseline.

Longitud en pixels o otras unidades


Eleva la posición del elemento en las unidades indicadas (px, cm, etc). El valor puede ser negativo, en ese caso la posición baja. El valor 0 corresponde a la baseline.

vertical-align para celdas de una tabla o elementos con display:table-cell

En el contexto de celdas de una tabla esta propiedad tiene un significado diferente. Sirve para definir como se alinea verticalmente el contenido de una celda. En este contexto sólo aplican los valores middle, top y bottom.

Para celdas de una tabla ( <table> ) el valor por defecto es middle, pero para un div con display:table-cell, el valor por defecto es top.

La siguiente imagen muestra como queda un bloque de texto con cada uno de los valores:


















martes, 28 de agosto de 2012

Los scripts externos pueden bloquear una web

Cuando cargamos un fichero JavaScript externo mediante una etiqueta <script> incluida en nuestro HTML, estamos corriendo un riesgo importante. Ese script externo a nuestra aplicación, probablemente un banner de publicidad o un widget, puede bloquear nuestra página y dejarla en blanco durante varios minutos o incluso evitar que llegue a cargarse. Steve Souders explica el problema en su presentación “Your script just killed my site” y proporciona una demostración online.

En la siguiente imagen podemos ver al menos tres elementos que se cargan mediante javascript externo en una página web real:



Si el código que incluimos para cargar estos elementos (normalmente proporcionado también por la empresa externa) no es apropiado, puede bloquear nuestra web.

¿Porqué un simple script puede bloquear nuestra página?

Un archivo JavaScript puede cargarse de manera síncrona (bloqueante) o asíncrona (no-bloqueante). Veamos que implica cada una:


Carga síncrona (bloqueante)

Decimos que se carga de forma síncrona cuando el navegador tiene que esperar a que el archivo se haya descargado y ejecutado para continuar presentando elementos en la página. Esto ocurre cuando utilizamos una etiqueta <script> incluida en el HTML. Al encontrarla, el navegador no continua calculando y mostrando los siguientes elementos de la página, este proceso se para hasta la ejecución del fichero. Esto ocurre para todos los navegadores.

La razón por la que se bloquea es que este script, al estar incluido de forma estática en el HTML, se considera parte de la página que se está presentando y, por lo tanto, el javascript que contiene puede crear nuevos elementos en la página ( o modificarlos si se carga en el body). Se espera a ejecutarlo completo para poder presentar la página correctamente.

Carga asíncrona (no-bloqueante)

La carga es asíncrona cuando el proceso de carga se realiza sin bloquear la presentación de otros elementos de la página.

Podemos conseguir la carga no-bloqueante mediante la inserción dinámica de la etiqueta <script> o utilizando atributos como  “defer” o “async”  (HTML5). Veremos después en detalle estas opciones.

El problema con los scripts externos que pueden "matar" nuestra página, es que a veces se incluyen de forma síncrona. Si el archivo es grande va a retrasar siempre la carga de la web que lo incluye. Aunque el archivo no sea pesado, su servidor puede ser lento, estar caído, o incluso estar bloqueado ( en China, por ejemplo ). Hasta que el script no se reciba o se produzca un timeout (si lo hay) nuestra página aparecerá en blanco.


¿Qué significa exactamente no-bloqueante?


Puesto que javascript no es multi-hilo, es imposible que dos scripts se ejecuten en paralelo. Este thread es además el mismo que se encarga de renderizar los elementos de la página. Cuando hablamos de un script no-bloqueante significa que no bloquea la página (puede seguir con el renderizado de elementos del DOM) mientras se descarga, la ejecución siempre se va a realizar como tarea única, nunca en paralelo.

Tenemos entonces que el navegador tiene que realizar dos tareas con el archivo:
  1.  Descargarlo de la URL que se le indique 
  2.  Ejecutarlo
El punto 1 es normalmente el que más tiempo requiere y es el único que podemos optimizar mediante estas técnicas. La ejecución siempre va a ser bloqueante puesto que tenemos un solo hilo que se encarga de ejecutar y de presentar elementos del UI.

Formas de carga no-bloqueante


Etiqueta <script> generada dinámicamente

Lo más habitual es utilizar una etiqueta <script> que se genera dinámicamente con JavaScript. Cuando se crean de este modo, la descarga se realiza inmediatamente pero no bloquea el renderizado de otros elementos. El fichero se ejecuta cuando se ha descargado completamente:
var script = document.createElement("script");
script.type = "text/javascript";
script.src = “/path/to/script.js";
document.getElementsByTagName("head")[0].appendChild(script);
Hay que tener en cuenta que esta técnica no respeta el orden de inclusión de varios ficheros JavaScript (en algunos navegadores). No se garantiza que el fichero que se incluye primero sea el primero en ejecutarse.

Atributo ‘defer’ en <script>

Incluyendo el atributo defer la descarga comienza inmediatamente pero de forma no-bloqueante. La ejecución se retrasa hasta que la página se ha parseado completamente.


Atributo ‘async’ en <script> ( HTML5 )

En HTML5 se ha creado un atributo nuevo precisamente para este propósito:
de esta forma la etiqueta <script> se comporta igual que si la hubiéramos generado dinámicamente. El script de descarga inmediatamente sin bloquear la presentación de la página y se ejecuta en cuanto está descargado (esta es la principal diferencia respecto a defer).

Es importante señalar que todas estas técnicas retrasan el evento onload hasta que los scripts se han ejecutado. Existen otras técnicas que utilizan XHR (AJAX) o iframes, pero no aportan ventajas con respecto a las anteriores y prácticamente han sido desplazadas por estas.


Referencias:
Best way to load external javascript
Cargar JavaScript. Blocking vs non-blocking
Loading Scripts Without Blocking
What is a non-blocking script?


viernes, 24 de agosto de 2012

CSS: elementos de bloque y elementos en línea

Un elemento HTML se puede mostrar como elemento de bloque ( display: block ) o como elemento en línea ( display: inline ). Comprender exactamente la diferencia entre estos dos tipos de presentación es fundamental para un desarrollador.

Elementos de bloque ( block )

Elementos de bloque son, por ejemplo: <p>, <div>, <ul>, <li>, <form>, etc (siempre que no cambiemos su display por defecto).
Se caracterizan por:
  • Se colocan siempre en su propia línea, debajo de los elementos anteriores
  • Se expanden hasta ocupar toda la anchura disponible ( la del elemento padre )
  • La altura se ajusta al contenido
  • Pueden contener otros elementos inline o block
  • Se les puede fijar altura y anchura con CSS ( width y height )
  • Se les puede asignar margin y padding con CSS
  • Ignoran la propiedad CSS vertical-align


Elementos en línea ( inline )

Elementos en línea son, por ejemplo: <a>, <span>, <b>, <em>, etc (siempre que no cambiemos su display por defecto).
Se caracterizan por:
  • No crean una nueva línea. Se colocan ‘en línea’ con otros elementos
  • Su anchura y altura se ajusta al contenido y no podemos cambiarlas con CSS ( ignora widht y height )
  • Sólo podemos fijar margin-left y margin-right. Ignoran margin-top y margin-bottom 
  • Sólo pueden contener otros elementos inline
  • Debe respetar la propiedad white-space de CSS
  • Respeta vertical-align


Particularidades de margin y padding para elementos inline

El padding y el margin para elementos inline puede aplicarse en los cuatro lados, pero el que se define arriba y abajo no va a afectar a otros elementos, no los desplaza. Es como si ignorara estos valores, pero podemos apreciar el padding aplicado si definimos un borde o un color de fondo:


Imágenes y elementos inline-block

El elemento <img>(imagen) es un poco especial porque se comporta como una mezcla de elemento en línea y elemento de bloque:


Realmente es un elemento inline, pero de un tipo especial que admite altura y anchura. En el estándar se define como ”elemento en línea reemplazado” ( replaced inline element ) y para estos elementos width y height sí aplica.

Se define como un elemento reemplazado porque no tiene contenido por si mismo, sino que será despues reemplazado por el archivo que se obtiene de su URL.

Existe un tipo de display para hacer que cualquier elemento se comporte como lo hacen las imágenes, como un elemento de bloque que se coloca en línea:

display: inline-block

Para elementos reemplazados ( como <img> ) display: inline-block es exactamente igual al display: inline que tienen por defecto.

Referencias:
Inline elements and padding
W3C CSS2 Visual formatting model