Orden del contenido en Mobile First


Recientemente en un diseño sobre una página de producto tuve la necesidad de alterar el orden habitual de los contenidos para que el contenido principal apareciese antes que el contenido secundario.

Si unimos las filosofías de “Content First” y “Mobile First“, el usuario de pantalla pequeña debería acceder primero al contenido más importante, relegando a otras posiciones inferiores el contenido secundario, pero a medida que aumente el tamaño de pantalla del dispositivo seguramente surgirá la necesidad de cambiar el orden en el que aparecen esos elementos.

Esa coreografía de cambio en el orden de los contenidos puede realizarse con Javascript, pero existen dos técnicas vía CSS, que solucionan el problema con idéntico resultado.

1) display:table

La propiedad display permite especificar un rango de valores relacionados con tablas con el objetivo de que los elementos se muestren como si fueran elementos de una tabla. En nuestro caso solo nos interesan aquellos que puedan alterar el orden.

display:table – Hace que un elemento se comporte como si fuese una tabla.

display:table-caption – Hace que un elemento se comporte como si fuese el “caption” de una tabla. Se coloca de forma predeterminada en la parte superior de la tabla, pero también puede hacerlo en la parte inferior.

display: table-header-group – Grupo de filas que se coloca por encima de cualquier otra fila pero por debajo de un “caption superior” de la tabla, si es que lo hubiese.

display:table-footer-group – Grupo de filas que se coloca por debajo de cualquier otra fila pero por encima de un “caption inferior” de la tabla, si es que lo hubiese.

Según esto, tan solo tendríamos que aplicar el valor display:table a un contenedor padre y el resto de los valores a los elementos hijos que queramos que ocupen posiciones distintas a las que tienen en la estructura HTML.

De esta forma, el elemento con el valor display:table-caption ocupará la 1ª posición, seguido del que lleve el valor display:table-header-group y al final se situaría el que lleve el valor display:table-footer-group.

#container{
    display:table;
    width:100%;
}
 
.box:nth-child(1){
    display:table-footer-group;
}
 
.box:nth-child(2){  
    display:table-caption;
}
 
.box:nth-child(4){
    display:table-header-group;
}

El problema principal de este método es que solo se pueden modificar las posiciones de 3 elementos, pero tiene como ventaja que es compatible con navegadores Internet Explorer 8 y versiones superiores.

Ver ejemplo en Codepen

2) flexbox

Usando flexbox podemos alterar el orden de los elementos de una forma aún más sencilla ya que dispone de una propiedad que sirve justo para eso : order.

El problema al usar flexbox es que ha tenido a lo largo del tiempo hasta 3 sintaxis distintas. Una antigua de 2009, otra intermedia llamada “tweener” por estar creada en 2011 solo utilizada actualmente por Internet Explorer 10 y la más moderna de 2012 que es la recomendada. Ver compatibilidad de flexbox.

Primero deberemos indicar al elemento padre que se comporte como contenedor flex mediante la propiedad display:flex (la sintaxis antigua es la propiedad display:box, con sus respectivos prefijos propietarios). De forma predeterminada los elementos hijos se dispondrán en fila, por lo que tendremos que indicarles que lo hagan en columna a través de la propiedad flex-direction:column (la sintaxis antigua es la propiedad box-orient: vertical, también con sus respectivos prefijos propietarios).

#container{
    display: -webkit-box;      /* iOS 6-, Safari 3.1-6 */
    display: -moz-box;         /* Firefox 19- */
    display: -ms-flexbox;      /* IE 10 */
    display: -webkit-flex;     /* Chrome */
    display: flex;             /* Opera 12.1, Firefox 20+ */
    
    -webkit-box-orient: vertical;  /* iOS 6-, Safari 3.1-6 */
    -moz-box-orient: vertical;     /* Firefox 19- */
    -ms-flex-direction:column;     /* IE 10 */
    -webkit-flex-direction:column; /* Chrome */
    flex-direction:column;         /* Opera 12.1, Firefox 20+ */
}

A continuación, hay que utilizar en cada uno de los elementos a los que queramos cambiar, la propiedad order con el valor numérico de la posición que queramos que ocupen, en este caso sin límite de valores. Para compatibilidad con versiones de Firefox 19-, iOS hasta la 6 y Safari 3.1-6 hay que usar la sintaxis antigua que es box-ordinal-group con los prefijos propietarios.

.box:nth-child(1){
  -webkit-box-ordinal-group: 4;   /* iOS 6-, Safari 3.1-6 */
  -moz-box-ordinal-group: 4;      /* Firefox 19- */
  -ms-flex-order: 4;              /* IE 10 */
  -webkit-order: 4;               /* Chrome */
  order: 4;                       /* Opera 12.1, Firefox 20+ */
}
 
.box:nth-child(2){  
  -webkit-box-ordinal-group: 1;
  -moz-box-ordinal-group: 1;
  -ms-flex-order: 1;
  -webkit-order: 1;
  order: 1;
}
 
.box:nth-child(3){  
  -webkit-box-ordinal-group: 3;
  -moz-box-ordinal-group: 3;
  -ms-flex-order: 3;
  -webkit-order: 3;
  order: 3;
}
 
.box:nth-child(4){
  -webkit-box-ordinal-group: 2;
  -moz-box-ordinal-group: 2;
  -ms-flex-order: 2;
  -webkit-order: 2;
  order: 2;
}

Ver ejemplo en Codepen

Lo ideal es empezar a experimentar con flexbox cuanto antes, pero está claro que si queremos ser compatibles con IE8 y superiores, la opción más indicada es usar display:table.

He creado una demo con flexbox pero que usa display:table para IE8 y superiores.

Ver demo