Efecto flip card CSS en paginación JavaScript

En este post veremos cómo aplicar un efecto CSS flip card a un div y a continuación aprovecharemos este efecto para paginar elementos de un array JavaScript

Aleix Martí
Blog de Interactius UX
5 min readSep 27, 2016

--

En este post explicaré cómo aplicar un efecto CSS de flip card para paginar los elementos de un array en JavaScript

Flip card

Primero hay que entender la estructura de un contenedor con el efecto flip. Se necesita un div contenedor (flip-container) y dentro otro div que será el que tendrá el efecto (card). Este último lo representaremos como si fuera una tarjeta con sus 2 caras, delantera y trasera. Cada una de estas caras se representarán con su respectivo div (front y back).

<div id="flip-container">
<div id="card1" class="card">
<div class="front"></div>
<div class="back"></div>
</div>
</div>

Ahora hay que aplicar un poco de CSS a estos elementos para conseguir el efecto flip. Este efecto consiste en simular que el div es un tarjeta a la que se le da la vuelta para ver la otra cara.

Primero se aplica la propiedad perspective al contenedor principal, para indicar a cuantos píxels de distancia está situado el elemento en una vista 3D. También se definen las medidas del contenedor y su posición.

#flip-container{
-webkit-perspective: 1000px;
perspective: 1000px;
padding: 50px
position: relative;
margin: 10px auto;
width: 500px;
}

A continuación se aplican los estilos al div que girará sobre sí mismo (efecto flip card) en cuanto se pase el puntero por encima (hover). Se define un tiempo de transición que mantenga el estilo 3D y se definen las coordenadas dónde se aplicará el efecto. También se define la rotación sobre sí mismo rotateX(180deg) cuando se le aplique la clase flip.

.card {
position: relative;
width: 500px;
height: 50px;
transition: 0.6s;
transform-style: preserve-3d;
transform-origin: 100% 25px;
margin: 5px;
}
.card:hover, .card.flip{
transform: rotateX(180deg);
}

Finalmente se aplican los estilos a los div que representan ambos lados de la tarjeta (front y back). En este ejemplo mostraremos información por la parte delantera y le aplicaremos un fondo rallado a la parte posterior, pero podría tener perfectamente contenido en ambas caras. En este punto es importante destacar las propiedades backface-visibility para ocultar la parte trasera de la tarjeta e inicializar la cara frontal con rotateX(0deg) y la trasera con rotate(180deg) para que nunca se vean las 2 a la vez.

.front, .back{
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
text-align: center;
}
.front{
transform: rotateX(0deg);
z-index: 2;
background-color: #e93e29;
color: #FFF;
font: 1em/1.8em Arial;
display: flex;
align-items: center;
justify-content: center;
}
.back{
transform: rotateX(180deg);
background: repeating-linear-gradient(
-45deg,
#ececec,
#ececec 10px,
#dedede 10px,
#dedede 20px
);
}

Este es el código básico para conseguir el efecto flip card sobre un div.

Paginación

Ahora veremos cómo hacer la paginación utilizando este efecto para hacer el cambio de página.

Primero añadiremos dos div más para ver 3 elementos en cada página (el número puede variar a gusto del consumidor) y un panel con 2 botones para avanzar y retroceder página. El de retroceder inicialmente lo dejaremos desactivado, ya que de entrada nos encontramos en la primera página y no tiene sentido retroceder.

<div id="flip-container">
<div id="card1" class="card">
<div class="front"></div>
<div class="back"></div>
</div>
<div id="card2" class="card">
<div class="front"></div>
<div class="back"></div>
</div>
<div id="card3" class="card">
<div class="front"></div>
<div class="back"></div>
</div>
</div>
<div id="controls">
<button id="prev" class="disabled" disabled>&lt;</button>
<button id="next">&gt;</button>
<div class="pag">Pág.<span id="pag"></span></div>
</div>

Y aquí el estilo de los botones, de manera muy básica (se puede cambiar el estilo tanto como se quiera).

#controls{
position: relative;
margin: 10px auto;
text-align: center;
}
.disabled {
color: #ccc;
}
button{
width: 25px;
height: 25px;
}
.pag{
font: 0.8em/1.2em Arial;
padding-top: 10px;
}

También quitaremos la propiedad hover y haremos girar el div asignándole una clase por JavaScript, de forma que

.card:hover, .card.flip{
transform: rotateX(180deg);
}

quedará:

.card.flip{
transform: rotateX(180deg);
}

A continuación vamos a ver la parte de la paginación. Utilizaremos algunas funciones de jQuery para buscar elementos y añadir y quitar clases.
Definimos un array con la información que se irá mostrando y unas variables para controlar qué información hay que mostrar en cada página.

var names=['Stan','Francine','Hayley','Steve','Roger','Klaus','Jeff','Avery'];
var pointer = 0; // indica el puntero sobre el index del array que debe mostrarse
var current = 1; // página actual que se muestra
var pages = (Math.ceil(names.length/$('.card').length)); // cálculo del número de páginas según el número de div que se muestren por página
var itemsPage = $('.card').length; // número total de items

La función flip es la encargada de hacer el efecto flip y devolver el div a su estado original al cabo de medio segundo (500ms). Mientras la carta está girada se hace la paginación llamando a la función “update”. Necesita 2 parámetros: el puntero dónde leer el array y la dirección de la paginación (siguiente/anterior).

function flip(ptr,dir){
setTimeout(function(){
$('.card').addClass('flip');
setTimeout(function(){
update(ptr, dir);
$('.card').removeClass('flip');
},500);
}, 100)
}

La función update es la encargada de actualizar el contenido HTML de los div en función de los 2 parámetros que recibe: el puntero para leer el array y la dirección de la paginación. En caso de llegar al final del array, si en la última página quedan menos elementos por mostrar que div hay creados, para no mostrar un div vacío se le aplica una propiedad display: none, para ocultarlo con la función hide() de jQuery.

Después hay que tener en cuenta volver a mostarlo con la función show().

function update(index, direction){
var id = 1;
var lim = index+$('.card').length;
if(direction == 'next'){
for (var i=index;i if(typeof names[i] !== 'undefined') {
$('#card'+(id)+'> .front').html(names[i]);
}else{
$('#card'+(id)+'> .front').hide();
}
id++;
}
}else if(direction == 'prev'){
for (var i=index;i if($('#card'+(id)+'> .front').css('display') == 'none'){
$('#card'+(id)+'> .front').show();
}
$('#card'+(id)+'> .front').html(names[i]);
id++;
}
}else{
alert('Error on pagination');
}
}

Ahora hay que asignar las funciones asociadas a los botones de página anterior y página siguiente. Estas funciones controlan que los botones estén activados o desactivados según toque, actualizan el número de página actual y llaman a la función flip con los punteros actualizados.

$('#next').on('click', function(){
pointer += itemsPage;
flip(pointer,'next');
if ((current+1) >= pages){
$('#next').addClass('disabled').prop('disabled', true);
}
current++;
$('#pag').html(current+'/'+pages);
$('#prev').removeClass('disabled').prop('disabled', false);
});
$('#prev').on('click', function(){
pointer -= itemsPage;
flip(pointer,'prev');
if ((current-1) == 1){
$('#prev').addClass('disabled').prop('disabled', true);
}
current--;
$('#pag').html(current+'/'+pages);
$('#next').removeClass('disabled').prop('disabled', false);
});

Finalmente sólo queda iniciar los div con el contenido inicial al cargar la página.

$('document').ready(function(){
update(pointer, 'next');
$('#pag').html(current+'/'+pages);
});

Y aquí podemos ver el resultado final:

--

--