Algunos efectos para botones en CSS
Categorías : CSS, HTML, Programación.

La intención de este documento es mostrar la forma de exprimir al máximo una simple etiqueta <button>
añadiendo transiciones y transformaciones para cada uno de sus estados.
Lo que mas claro nos debe quedar a la hora de trabajar con botones son sus estados. En esencia una etiqueta <button>
puede tener los siguientes estados :
:hover
(al pasar el mouse por encima):active
(al hacer click con el mouse):focus
(al obtener el foco del teclado)
Para ponernos en la situación, imaginaros que pasa al hacer click encima de un botón. Para empezar el evento :hover
ya ha saltado antes de hacer el click por haber entrado dentro del área del botón. A parte al hacer el click se manda el evento :active
, y además si el foco actual no es el botón en el que se hace el click, se recibe el evento :focus
por que ahora lo será.
Con esta breve explicación lo que os quiero hacer ver, es que hay que pensar muy bien como distribuir las transiciones para cada evento, ya que si se activan las tres a la vez se pueden acabar pisando entre ellas. (en lo personal me pasa muchisimo utilizando transformaciones)
Para evitar que las transiciones se pisen la idea es distribuir el control en 3 capas :
- La capa principal es la etiqueta
<button>
, la cual contiene el texto y el borde del botón. Se utilizará para las transiciones de los eventosactive
y:focus
. - Detrás de la capa principal utilizaremos el pseudo elemento
::before
para añadir una segunda capa destinada a mostrar las transiciones del evento:hover
. Esta capa la identificaremos en este documento como la capa animación. - Por ultimo detrás de la capa
::before
crearemos con el pseudo elemento::after
una capa la cual tiene la finalidad de mostrar el fondo del botón (aunque si es necesario se puede llegar a utilizar para otra transición). Esta capa la identificaremos por capa fondo. -
<button>::before::after
Definiendo las capas
He creado varias transiciones para el hover en este documento, por lo que me ha resultado mas fácil crearme una base para los botones con los parámetros por defecto, para luego ir adaptando-los a cada transición.
El primer paso consistirá en crear un marco con el borde negro, fondo transparente, y el texto de color blanco, al que definiremos sus tres estados por defecto (:hover, :focus, :active).
/* Clases que empiezan por 'Boton-' */[class^='Boton-'] {border : 2px solid #000; /* 2 pixeles de borde negro */text-align : center; /* Texto centrado */text-decoration : none; /* Sin decoraciones para el texto (por defecto viene con underline) */padding : 10px; /* Un poco de padding para que se vea bien el botón *//* La transición en el click (:active) tiene que ser rápida 150ms (transform y color), la transición para cambiar de foco en 150ms */transition : transform 0.15s ease-in-out, color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;font-family : Karla, sans-serif; /* Fuente de google */font-size : 1.7rem; /* Tamaño de la fuente */color : #FFF; /* Color del texto en blanco */margin : 10px; /* 10 pixeles de margen para separar los botones entre si. */position : relative; /* Posición relativa para que sus hijos partan desde él */overflow : hidden; /* Todo lo que sobresalga del botón no se verá */cursor : pointer; /* Puntero del mouse que muestre una mano */transform : perspective(600px) translateZ(0px) rotateZ(0deg) rotateX(0deg); /* Perspectiva, rotación y posición por defecto */text-shadow : 1px 1px 1px #666; /* Una ligera sombra gris para el texto */}/* Elimino el outline del botón por una transición con la sombra */[class^='Boton-']:focus {outline : 0px solid transparent; /* Elimino el outline que viene por defecto en los button */box-shadow : 0px 0px 4px 2px #800, 0px 0px 2px 1px #300; /* Creo uan sombra en gris oscuro con 2 tonalidades */}/* Alejo el objeto en la perspectiva cuando el usuario presiona sobre él */[class^='Boton-']:active {transform : perspective(600px) translateZ(-75px) rotateZ(-0.5deg) rotateX(-10deg); /* Creo el efecto de hundimiento para el botón */color : #BBB; /* Cambio el color del texto a gris */}/* Color del borde rojo al pasar el mouse por encima del botón */[class^='Boton-']:hover, [class^='Boton-']:active { border : 2px solid darkred; }
Línea 2 utilizo el selector[class^='Boton-']
para buscar los elementos en el que el principio del nombre de la clase sea 'Boton-'.La verdad es que podría haber utilizado el selectorbutton
sin más pero por una parte quería optimizar al máximo el tamaño del código, y por otra así no entra en conflicto con los botones de mi web.Línea 8 Esta transición se realiza en la capa principal para los eventos:active
y:focus
. Hay que remarcar que el evento:active
hace una transición con una transformación, con lo cual no podremos realizar otras transiciones con una transformación en esta capa.Línea 14 Eloverflow
es muy importante, ya que la capa::before
(capa animación) puede quedar fuera de los límites del botón.Líneas 20, 21, 22, 23 Cuando el botón tiene el foco creo una sombra para el botón utilizando la propiedadbox-shadow
. También elimino eloutline
por defecto que tiene.Líneas 25, 26, 27, 28 Cuando se está pulsando el botón movemos la coordenada Z utilizando la propiedadtransform
(para simular que el botón se aleja), y cambio el color del texto utilizando la propiedadcolor
.Línea 30 Modifico el color del borde en el:hover
utilizando la propiedadborder
.
Para terminar con las capas por defecto, vamos a crear las capas animación y fondo (::before, ::after)
/* Preparación para los pseudo elementos before y after */[class^='Boton-']::before, [class^='Boton-']::after {content : ''; /* Contenido (requerida para inicializar el pseudo-selector) */position : absolute; /* Posición absoluta (relativa al button) */top : 0px; /* Empezamos desde arriba del <button> */left : 0px; /* Empezamos desde la izquierda del <button> */width : 100%; /* Ancho 100% del <button> */height : 100%; /* Alto 100% del <button> */transition : 0.4s ease-in-out; /* Transición para el hover de 500ms para que se vea bien (capa animación) */}/* Para las transiciones del fondo a color rojo en el hover, se utilizara el pseudo elemento ::before (capa animación) */[class^='Boton-']::before {z-index : -1; /* MUY IMPORTANTE esta capa va por debajo de la capa principal */}/* Para mostrar el fondo negro del botón se utilizara el pseudo elemento ::after (capa fondo) */[class^='Boton-']::after {z-index : -2; /* MUY IMPORTANTE esta capa va por debajo de la capa animación */background-color : rgb(60,60,60); /* Color del fondo gris oscuro */}
Lo más importante de este fragmento de código son los z-index
para colocar cada capa en su sitio, y la propiedad transition
por defecto a 400ms para TODAS las propiedades.
A partir de aquí ya tenemos un botón básico con una transición en el :focus
, y una transición en el :active
. Mantén pulsado el mouse sobre el botón, y luego haz click fuera de él para ver las transiciones de los eventos :active
y :focus
.
Ahora viene la parte divertida donde vamos a crear varios efectos hover partiendo de esta base.
Efecto box-shadow
El efecto box-shadow
consiste en crear una sombra por dentro del botón hasta ocupar el 100% de su área. El primero empezará desde las puntas y terminara dentro, y el segundo empezara desde dentro para terminar en las puntas.
Echad un vistazo al concepto :
- La primera capa contiene el borde y el texto. Ademas sigue conservando las transiciones en los eventos
:focus
y:active
. - La segunda capa utiliza una transición con la propiedad
box-shadow
para cambiar el color del fondo a rojo. - La última capa se utiliza para mostrar el fondo gris oscuro.
-
box-shadow
/* Sombra interior que crece desde las puntas hacia el centro */.Boton-BoxShadow1::before { box-shadow : 0px 0px 0px 0px transparent inset; }.Boton-BoxShadow1:hover::before,.Boton-BoxShadow1:active::before { box-shadow : 0px 0px 30px 25px #ea504e inset; }/* Efecto invertido (crece desde el centro hacia las puntas)en este caso lo más fácil es hacer el fondo rojo, mientras que el box-shadow empezara cubriendo el fondo de color gris oscuro */.Boton-BoxShadow2::before { box-shadow : 0px 0px 30px 25px rgb(60,60,60) inset; }.Boton-BoxShadow2:hover::before,.Boton-BoxShadow2:active::before { box-shadow : 0px 0px 0px 0px transparent inset; }.Boton-BoxShadow2::after { background-color : #ea504e !important; }
La cosa es muy simple asignamos el
.Boton-BoxShadow:hover::before
.Boton-BoxShadow:active::before
:active
del mismo modo que tratamos el selector :hover
.Efecto LinealGradient
Antes de nada vamos a ver gráficamente como funciona esta transición. En el siguiente concepto podemos ver que la capa animación es mas ancha de lo normal y se desplaza de izquierda a derecha.
-
Linear-gradient
La idea es hacer un degradado un 400% mas ancho que el botón, que en una punta sea rojo yu en la otra transparente. Luego solo hay que desplazarlo lateralmente.
/* Desplazamiento lateral del fondo que contiene un degradado lineal. */.Boton-LinearGradient1::before, .Boton-LinearGradient2::before { width : 400%; }.Boton-LinearGradient1::before {background-image : linear-gradient(45deg, #ea504e 40%, transparent 60%); /* Degradado rojo-transparente */left : -300%;}.Boton-LinearGradient2::before {background-image : linear-gradient(45deg, transparent 40%, #ea504e 60%); /* Degradado transparente-rojo */left : 0%;}.Boton-LinearGradient1:hover::before, .Boton-LinearGradient1:active::before { left : 0%; }.Boton-LinearGradient2:hover::before, .Boton-LinearGradient2:active::before { left : -300%; }
En realidad el código no tiene mucha complicación, como ya he mencionado antes asignamos un ancho del 400% con la propiedad width
, creamos unos degradados con la propiedad background-image
y la función linear-gradient
, y los desplazamos desde su left
.
Efecto LinearGradient 3
Este efecto viene a ser los efectos LinearGradient1 y LinearGradient2 a la vez. Para construir este efecto, esta vez vamos a utilizar una transición tanto en la capa ::before como en la capa ::after. Echa un vistazo al concepto para este efecto :
-
Linear-gradient3
/* Desplazamiento desde el centro a los laterales con un degradado lineal utilizando el pseudo-elemento ::before (para el degradado) */.Boton-LinearGradient3::before, .Boton-LinearGradient3::after { width : 300%; }.Boton-LinearGradient3::before {background-image : linear-gradient(45deg, #ea504e 40%, transparent 60%); /* Degradado de rojo a transparente */left : -200%; /* Posición X al -200% */}.Boton-LinearGradient3::after {background-image : linear-gradient(45deg, rgb(60,60,60) 40%, #ea504e 60%); /* Degradado de gris a rojo */left : 0%; /* Posición X al 0% */}.Boton-LinearGradient3:hover::before, .Boton-LinearGradient3:active::before { left:0%; }.Boton-LinearGradient3:hover::after, .Boton-LinearGradient3:active::after { left:-200%; }
La capa ::before
tiene un degradado de rojo a transparente, y la capa ::after
tiene un degradado de gris a rojo. De esta forma aprovechamos la capa del fondo para hacer una segunda transición.
Efecto 3D
Los efectos 3d consisten en rotar la capa ::before
ajustando el origen de la transformación a un lado del botón. Veamos el concepto :
- La primera capa contiene el borde y el texto. Como siempre sigue conservando las transiciones en los eventos
:focus
y:active
que definimos al principio. - La segunda capa establece la propiedad
transform-origin
a un lado, y hace una transición con la propiedadtransform
para rotar la capa de forma que quede a la vista o oculta. - La última capa se utiliza para mostrar el fondo gris oscuro.
-
3D
.Boton-3DSuperior::before, .Boton-3DInferior::before,.Boton-3DLateralD::before, .Boton-3DLateralI::before {background-color : #ea504e;transition : 0.4s cubic-bezier(.7,.24,0.26,1.52);}/* Inicialmente el eje X rotado 90 grados */.Boton-3DSuperior::before { transform-origin : top center; transform : perspective(600px) rotateX(-90deg); }.Boton-3DInferior::before { transform-origin : bottom center; transform : perspective(600px) rotateX(90deg); }/* En el hover devolvemos la rotación del eje X a 0 grados */.Boton-3DSuperior:hover::before, .Boton-3DInferior:hover::before,.Boton-3DSuperior:active::before, .Boton-3DInferior:active::before { transform : perspective(600px) rotateX(0deg); }/* Inicialmente el eje Y rotado 90 grados */.Boton-3DLateralD::before { transform-origin : center right; transform : perspective(600px) rotateY(-90deg); }.Boton-3DLateralI::before { transform-origin : center left; transform : perspective(600px) rotateY(90deg); }/* En el hover devolvemos la rotación del eje Y a 0 grados */.Boton-3DLateralD:hover::before, .Boton-3DLateralI:hover::before,.Boton-3DLateralD:active::before, .Boton-3DLateralI:active::before { transform : perspective(600px) rotateY(0deg); }
En primer lugar hay que aplicar el transform-origin
para cada lateral, y luego hay que utilizar la propiedad transform
para rotar el eje X (para los laterales superior e inferior), y para rotar el eje Y (para los laterales derecho e izquierdo).
Por último en el :hover
devolvemos la rotación del eje X/Y a 0.
Efecto circular
Por ultimo el efecto circular consiste en centrar la capa animación con un tamaño inicial de 0 de altura por 0 de ancho para agrandarla en el :hover
.
Clase Boton-Circular 1 2 3 4 5 6 7 8 9 10 11
|
|
Lo mas importante de este fragmento de código son las top
y left
al 50%, para luego utilizar la propiedad transform
con un -50% a las coordenadas X e Y.
Finalmente en el evento :hover
establecemos las propiedades width
y height
a 300 pixeles.
width
y el height
al mismo tamaño si queremos que el efecto sea circular, y no elíptico. Esto puede ser un problema a partir de ciertos tamaños, ya que contra mas grande sea el circulo final, mas rápida será la transición hasta el punto de que llegue a ser imperceptible.Ejemplo completo
Y esto es todo por hoy, como siempre tenéis el ejemplo completo a vuestra disposición para que podáis hacer las pruebas que queráis.