CSS ::before
y ::after
Los pseudoelementos le permiten insertar “contenido” antes y después de cualquier elemento no reemplazado (por ejemplo, funcionan en un <div>
pero no un <input>
). Esto le permite mostrar algo en una página web que puede no estar presente en el contenido HTML. No debe usarlo para contenido real porque no es muy accesible, ya que ni siquiera puede seleccionar y copiar el texto insertado en la página de esta manera; es solo contenido decorativo.
En este artículo, lo guiaré a través de siete ejemplos diferentes que muestran cómo ::before
y ::after
se puede utilizar para crear efectos interesantes.
Tabla de contenido
- Estilismo de imágenes rotas
- Blockquote personalizado
- Lista de viñetas de iconos
- Interruptor de palanca animado
- Borde degradado
- Superposiciones de degradado
- Botones de radio personalizados
- Terminando
Tenga en cuenta que para la mayoría de los ejemplos, solo estoy explicando las partes del código que tratan específicamente con los pseudoelementos CSS. Dicho esto, todo el CSS está disponible en las demostraciones integradas si desea ver el código para un estilo adicional.
Estilismo de imágenes rotas
Cuando un usuario visita su sitio web, su conexión a Internet (o un factor fuera de su control) puede evitar que sus imágenes se descarguen y, como resultado, el navegador muestra un icono de imagen rota y la imagen alt
texto (si realmente está allí).
¿Qué tal mostrar un marcador de posición personalizado en su lugar? Puedes lograr esto usando ::before
y ::after
con un poco de posicionamiento CSS.
Primero, necesitamos usar el posicionamiento relativo en el elemento de imagen. Vamos a usar el posicionamiento absoluto en uno de los pseudo-elementos en un momento, así que esto relative
position se asegura de que el pseudo-elemento esté ubicado dentro del contenido del elemento de imagen, en lugar de caer completamente fuera del flujo del documento.
img {
display: block; /* Avoid the space under the image caused by line height */
position: relative;
width: 100%
}
A continuación, creemos la región del efecto de imagen rota usando la imagen ::before
pseudo-elemento. Vamos a diseñar esto con un fondo gris claro y un borde un poco más oscuro para comenzar.
img::before {
background-color: hsl(0, 0%, 93.3%);
border: 1px dashed hsl(0, 0%, 66.7%);
/* ... */
}
<img>
es un elemento reemplazado. ¿Por qué estás usando :: before pseudo-elemento en él? ¡No funcionará !. Correcto. En este escenario, el pseudo-elemento se mostrará en Chrome y Firefox cuando la imagen no se cargue, que es exactamente lo que desea. Mientras tanto, Safari solo muestra el estilo aplicado al texto alternativo.
El estilo se aplica a la esquina superior izquierda de la imagen rota.
Hasta ahora tan bueno. Ahora podemos convertirlo en un elemento a nivel de bloque (display: block
) y darle una altura que ocupe todo el espacio disponible.
img::before {
/* ... */
display: block;
height: 100%;
}
¡Las cosas ya empiezan a verse mejor!
Podemos afinar un poco más el estilo. Por ejemplo, redondeemos las esquinas. También deberíamos dar la alt
texto un poco de espacio para respirar dando al pseudo-elemento ancho completo y posicionamiento absoluto para un mejor control de colocar las cosas donde queremos.
img::before {
/* ... */
border-radius: 4px;
content: "";
position: absolute;
width: 100%;
}
Si se detuvo aquí y revisó su trabajo, es posible que se esté rascando la cabeza porque el alt
el texto desaparece de repente.
Eso es porque establecemos content
a una cadena vacía (que necesitamos para mostrar nuestro contenido y estilos generados) y cubrir todo el espacio, incluido el texto alternativo real. Está ahí, simplemente no podemos verlo.
Podemos verlo si mostramos el alt
texto de una manera alternativa (¿entiendes?), esta vez con ayuda de la forma ::after
pseudo-elemento. El content
propiedad es realmente capaz de mostrar la imagen alt
texto de atributo usando el attr()
función:
img::after {
content: attr(alt);
/* Some light styling */
font-weight: bold;
position: absolute;
height: 100%;
left: 0px;
text-align: center;
top: 1px;
width: 100%;
}
¡Esto es asombroso! En Chrome, al menos.
Pero, en Firefox, no tanto.
El contenido generado choca con el contenido real alt
texto en Firefox.
Una solución rápida es apuntar al alt
atributo directamente usando un selector de atributo (en este caso, img[alt]
) y apunte a estilos similares allí para que coincida con Chrome.
img[alt] {
text-align: center;
font-weight: bold;
color: hsl(0, 0%, 60%);
}
Ahora tenemos un gran marcador de posición que es consistente en Chrome y Firefox.
Blockquote personalizado
Blockquotes son citas o extractos de un trabajo citado. También brindan una gran oportunidad para romper una pared de texto con algo visualmente interesante.
Hay todo tipo de formas de aplicar estilo a las citas en bloque. Chris tiene un conjunto de cinco estilos que se remontan a 2007.
Quiero ver otra técnica, una que incorpore ::before
y ::after
. Como vimos con el último ejemplo, podemos usar el content
para mostrar el contenido generado y aplicar otras propiedades para disfrazarlo. Pongamos comillas grandes al principio y al final de una cita en bloque.
Firefox 91
El HTML es sencillo:
<blockquote>
<!-- Your text here -->
</blockquote>
Algunos cosméticos en el CSS:
blockquote {
font-style: italic;
line-height: 1.618;
font-size: 1.2em;
width: 30em;
position: relative;
padding: 40px 80px;
}
Nota la position: relative
allí porque, como aprenderá, es esencial para colocar las comillas en bloque.
Como probablemente habrá adivinado, usaremos ::before
para la primera comilla, y ::after
para el cierre. Ahora, simplemente podríamos llamar al content
propiedad en ambos y generar las marcas allí. Pero, CSS nos tiene cubiertos con open-quote
y close-quote
valores.
blockquote::before {
content: open-quote;
/* Place it at the top-left */
top: 0;
left: 0;
}
blockquote::after {
content: close-quote;
/* Place it at thee bottom-right */
bottom: 0;
right: 0;
}
Esto nos da las comillas que queremos, pero permítanme abotonar un poco los estilos:
blockquote::before,
blockquote::after {
background-color: #cccccc;
display: block;
width: 60px;
height: 60px;
line-height: 1.618;
font-size: 3em;
border-radius: 100%;
text-align: center;
position: absolute;
}
Lista de viñetas de iconos
Hemos ordenado<ol>
) y desordenado (<ul>
) listas en HTML. Ambos tienen un estilo predeterminado dictado por la hoja de estilo del agente de usuario del navegador. Pero con ::before
pseudo-elemento, podemos anular esos estilos “predeterminados” con algo propio. ¿Y adivina qué? Podemos usar emojis (😊) en el content
¡propiedad!
.name-list li::before {
content: "😊";
margin-right: 15px;
font-size: 20px;
}
Si bien esto es genial y todo, vale la pena señalar que en realidad podríamos alcanzar el ::marker
pseudoelemento, que está diseñado específicamente para aplicar estilos a marcadores de lista. Eric Meyer nos muestra cómo funciona y probablemente sea una mejor manera de hacerlo a largo plazo.
Interruptor de palanca animado
Uno de los mejores trucos para diseñar formularios es crear un interruptor de palanca a partir de una casilla de verificación HTML estándar. De hecho, Preethi Sam compartió recientemente un enfoque al mostrar un puñado de otros trucos de estilo de casillas de verificación utilizando máscaras CSS.
Fiel a su nombre, se usa un interruptor de palanca para alternar o cambiar entre los estados marcado y no marcado de un elemento de casilla de verificación.
<form class="container">
<label class="switch">
<input type="checkbox" />
</label>
</form>
La personalización es todo gracias a las modificaciones agregadas al <input>
elemento a través del ::before
y ::after
pseudo-elementos. Pero primero, aquí hay algunos CSS de referencia para el <form>
elemento:
.container {
background: #212221;
background: linear-gradient(to right, #1560bd, #e90);
border-radius: 50px;
height: 40px;
position: relative;
width: 75px;
}
No estamos del todo ahí, pero vea cómo se muestra el elemento de casilla de verificación.
Vamos a “ocultar” la apariencia predeterminada de la casilla de verificación mientras hacemos que ocupe todo el espacio. Extraño, ¿verdad? Es invisible, pero técnicamente sigue ahí. Hacemos eso por:
- cambiando su posición a
absolute
, - configurando la apariencia para
none
, y - estableciendo su
width
yheight
a100%
.
input {
-webkit-appearance: none; /* Safari */
cursor: pointer; /* Show it's an interactive element */
height: 100%;
position: absolute;
width: 100%;
}
Ahora, diseñemos el <input>
elemento con su ::before
pseudo-elemento. Este estilismo cambiará la apariencia de la entrada, acercándonos al resultado final.
input::before {
background: #fff;
border-radius: 50px;
content: "";
height: 70%;
position: absolute;
top: 50%;
transform: translate(7px, -50%); /* Move styling to the center of the element */
width: 85%;
}
¿Que? Espera? Pensarías que ::before
no funcionaría con un elemento reemplazado, como <input>
. Y eso es cierto, pero solo cuando el tipo de entrada es image
que es equivalente a un <img>
elemento. Otros controles de formulario, como una casilla de verificación, se definen como elementos no reemplazados en la especificación HTML.
A continuación, tenemos que crear el botón “alternar” y da la casualidad de que todavía tenemos el ::after
pseudo-elemento disponible para hacerlo. Pero, hay dos cosas que vale la pena mencionar:
- El
background
es unlinear-gradient
. - El botón “alternar” se mueve al centro de la
<input>
con eltransform
propiedad.
input::after {
background: linear-gradient(to right, orange, #8e2de2);
border-radius: 50px;
content: "";
height: 25px;
opacity: 0.6;
position: absolute;
top: 50%;
transform: translate(7px, -50%);
transition: all .4s;
width: 25px;
}
Intente hacer clic en el botón de alternar. No pasa nada. Eso es porque en realidad no estamos cambiando el estado verificado de la <input>
. E incluso si lo estuviéramos, el resultado es … desagradable.
La solución es aplicar el :checked
atribuir a la ::after
pseudo-elemento del <input>
. Al apuntar específicamente al estado marcado de la casilla de verificación y encadenarlo al ::after
pseudo-elemento, podemos mover la palanca a su lugar.
input:checked::after {
opacity: 1;
transform: translate(170%, -50%);
}
Borde degradado
Podemos decorar imágenes con bordes para que se destaquen o encajen de manera más fluida dentro de un diseño. ¿Sabías que podemos usar un degradado en un borde? Bueno, podemos con ::before
(también hay otras formas, por supuesto).
La idea central es crear un degradado sobre la imagen y usar CSS z-index
propiedad con un valor negativo. El valor negativo tira del degradado debajo de la imagen en el orden de apilamiento. Esto significa que la imagen siempre aparece en la parte superior siempre que el degradado tenga un negativo. z-index
.
.gradient-border::before {
/* Renders the styles */
content: "";
/* Fills the entire space */
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
/* Creates the gradient */
background-image: linear-gradient(#1a1a1a, #1560bd);
/* Stacks the gradient behind the image */
z-index: -1;
}
figure {
/* Removes the default margin */
margin: 0;
/* Squeezes the image, revealing the gradient behind it */
padding: 10px;
}
Superposiciones de degradado
Esto es similar a lo que hicimos en el ejemplo anterior, pero aquí aplicamos el degradado en la parte superior de la imagen. Por que hariamos eso? Puede ser una buena forma de agregar un poco de textura y profundidad a la imagen. O tal vez se puede usar para aclarar u oscurecer una imagen si hay texto encima que necesita un contraste adicional para su legibilidad.
Si bien esto es similar a lo que acabamos de hacer, notará algunas diferencias evidentes:
figure::before {
background-image: linear-gradient(to top right, #1a1a1a, transparent);
content: "";
height: 100%;
position: absolute;
width: 100%;
}
¿Mira eso? No hay z-index
porque está bien que el degradado se apile sobre la imagen. También estamos introduciendo transparencia en el degradado de fondo, lo que permite que la imagen se filtre a través del degradado. Ya sabes, como una superposición.
Botones de radio personalizados
La mayoría de nosotros, si no todos, intentamos personalizar los estilos predeterminados de los botones de opción HTML, y eso suele lograrse con ::before
y ::after
, como hicimos con la casilla de verificación anteriormente.
Firefox 91
Primero estableceremos algunos estilos básicos, solo para preparar el escenario:
/* Centers everything */
.flex-center {
align-items: center;
display: flex;
justify-content: center;
}
/* Styles the form element */
.form {
background: #ccc;
height: 100vh;
width: 100%;
}
/* Styles the inputs */
.form-row {
background: #fff;
border-radius: 50px;
height: 40px;
margin: 10px;
overflow: hidden;
position: relative;
width: 150px;
}
Ahora eliminemos el estilo predeterminado de los botones de opción, nuevamente, con appearance: none;
.form-input {
-webkit-appearance: none; /* Safari */
appearance: none;
}
::before
debe colocarse en la esquina superior izquierda del botón de opción, y cuando está marcado, cambiamos su color de fondo.
.form-input::before {
/* Renders the styles */
content: '';
/* Shows that it's interactive */
cursor: pointer;
/* Positions it to the top-left corner of the input */
position: absolute;
top: 0;
left: 0;
/* Takes up the entire space */
height: 100%;
width: 100%;
}
/* When the input is in a checked state... */
.form-input:checked::before {
/* Change the background color */
background: #21209c;
}
Todavía tenemos que arreglar algunas cosas usando ::after
. Específicamente, cuando el botón de radio está marcado, queremos cambiar el color del anillo circular a blanco porque, en su estado actual, los anillos son azules.
.form-input::after {
/* Renders the styles */
content: '';
/* Shows that it's interactive */
cursor: pointer;
/* A little border styling */
border-radius: 50px;
border: 4px solid #21209c;
/* Positions the ring */
position: absolute;
left: 10%;
top: 50%;
transform: translate(0, -50%);
/* Sets the dimensions */
height: 15px;
width: 15px;
}
/* When the input is in a checked state... */
.form-input:checked::after {
/* Change ::after's border to white */
border: 4px solid #ffffff;
}
La etiqueta del formulario todavía no se puede utilizar aquí. Necesitamos apuntar a la etiqueta del formulario directamente para agregar color, y cuando la entrada del formulario está marcada, cambiamos ese color a algo que sea visible.
.form-label {
color: #21209c;
font-size: 1.1rem;
margin-left: 10px;
}
Haga clic en los botones y aún no pasa nada. Aquí lo que está pasando. El position: absolute
sobre ::before
y ::after
está encubriendo cosas cuando los botones de radio están marcados, ya que todo lo que ocurre en la jerarquía del documento HTML está encubierto a menos que se muevan a una nueva ubicación en el documento HTML, o su posición se modifique con CSS. Por lo tanto, cada vez que se marca el botón de opción, se cubre su etiqueta.
Probablemente ya sepa cómo solucionar este problema, ya que resolvimos el mismo tipo de cosas anteriormente en otro ejemplo. Aplicamos z-index: 1
(o position: absolute
) a la etiqueta del formulario.
.form-label {
color: #21209c;
font-size: 1.1rem;
margin-left: 10px;
z-index: 1; /* Makes sure the label is stacked on top */
/* position: absolute; This is an alternative option */
}
Terminando
Cubrimos siete formas diferentes en las que podemos usar el ::before
y ::after
pseudoelementos para crear efectos interesantes, personalizar estilos predeterminados, crear marcadores de posición útiles y agregar bordes a las imágenes.
De ninguna manera cubrimos todas las posibilidades que podemos desbloquear cuando aprovechamos estos elementos adicionales que se pueden seleccionar con CSS. Lynn Fisher, sin embargo, lo ha convertido en un pasatiempo, haciendo diseños asombrosos con un solo elemento. Y no olvidemos el arte CSS de Diana Smith que usa pseudoelementos en varios lugares para obtener efectos realistas, similares a los de una pintura.