¿Por qué los pseudo-elementos: before y: after requieren una propiedad ‘content’?

Dado el siguiente escenario, ¿por qué el selector: after requiere una propiedad de contenido para funcionar?

.test { width: 20px; height: 20px; background: blue; position:relative; } .test:after { width: 20px; height: 20px; background: red; display: block; position: absolute; top: 0px; left: 20px; } 
 

Observe cómo no ve el pseudo elemento hasta que especifique la propiedad de contenido:

 .test { width: 20px; height: 20px; background: blue; position:relative; } .test:after { width: 20px; height: 20px; background: red; display: block; position: absolute; top: 0px; left: 20px; content:"hi"; } 
 

¿Por qué es esta la funcionalidad prevista? Se podría pensar que el bloque de visualización obligaría al elemento a aparecer. Curiosamente, puedes ver los estilos dentro de depuradores web; sin embargo, no se muestran en la página.

Aquí hay algunas referencias a varias especificaciones y borradores del W3C:

Selectores Nivel 3

Los pseudo-elementos ‘: before’ y ‘: after’ se pueden usar para insertar contenido generado antes o después del contenido de un elemento.

Los pseudo-elementos: antes y después

Los autores especifican el estilo y la ubicación del contenido generado con los pseudo-elementos: before y: after. Como indican sus nombres, los pseudo-elementos: before y: after especifican la ubicación del contenido antes y después del contenido del árbol de documentos de un elemento. La propiedad ‘contenido’, junto con estos pseudo-elementos, especifica qué se inserta.

El atributo de contenido

Inicial: ninguno

Esta propiedad se usa con los pseudo-elementos: before y: after para generar contenido en un documento. Los valores tienen los siguientes significados:

none : el pseudo-elemento no se genera.


El estilo aplicado a los pseudoelementos :: before y :: after afecta la visualización del contenido generado. El atributo de content es este contenido generado, y sin él presente, se asume el valor predeterminado de content: none , lo que significa que no hay nada para que se aplique el estilo.

Si no quieres repetir el content:''; varias veces, puede anular esto simplemente mediante el diseño global de todos los pseudo-elementos :: before y :: after dentro de su CSS ( ejemplo de JSFiddle ):

 ::before, ::after { content:''; } 

En base a sus comentarios sobre las respuestas de los demás, creo que su pregunta es en realidad:

¿Por qué debe establecerse la propiedad de contenido para las pseudoclases en el CSS, en oposición al contenido de las no pseudoclases, que pueden configurarse en HTML o CSS?

La razón es que:

  • por definición, las pseudo-clases se crean dinámicamente para cada elemento especificado por el marcado HTML de una página
  • todos los elementos de página, incluidas las pseudoclases, deben tener una propiedad de contenido para mostrarse.
  • Los elementos HTML como

    hacen, pero puede establecer su propiedad de contenido rápidamente mediante el marcado ( o con declaraciones CSS).

  • Sin embargo, a diferencia de los elementos que no son pseudoclases, las pseudoclases no pueden recibir valores en el marcado.
    Por lo tanto, todas las pseudo-clases son invisibles (sus propiedades de ‘contenido’ no tienen ningún valor) a menos que les digas que no lo sean (dándoles valor con declaraciones CSS).

Toma esta simple página:

  

Sabemos que esta página no mostrará nada, porque el elemento

no tiene texto. Una forma más precisa de reformular esto es que la propiedad de contenido del elemento

no tiene ningún valor .

Podemos cambiar esto fácilmente, configurando la propiedad de contenido del elemento h1 en el marcado HTML :

  

This sentence is the content of the p element.

Esto ahora se mostrará cuando se cargue, porque la propiedad de contenido del elemento

tiene un valor; ese valor es una cadena:

 "This sentence is the content of the p element." 

Alternativamente, podemos hacer que el elemento

se muestre estableciendo la propiedad de contenido del elemento

en el CSS :

 p { content: "This sentence is the content of the p element set in the CSS."; } 

Estas dos formas de inyectar la cadena en el elemento

son idénticas.

Ahora, considere hacer lo mismo con las pseudo-clases:

 HTML:  

P

CSS: p:before { content: "BEFORE... " ; } p:after { content: " ...and AFTER"; }

El resultado:

 BEFORE... P ...and AFTER 

Finalmente, imagina cómo lograrías este ejemplo sin usar CSS. Es imposible, porque no hay forma de establecer el contenido de la pseudoclase en el marcado HTML.

Puede ser creativo e imaginar algo como esto podría funcionar:

 BEFORE...  

P

...and AFTER

Pero no, porque y no son elementos HTML .

En conclusión:

  • Las pseudo clases existen para cada elemento de marcado.
  • Son invisibles por defecto, porque se inicializan sin propiedad de contenido.
  • NO PUEDE establecer la propiedad de contenido para pseudo clases con marcado HTML.
    Por lo tanto, la propiedad de contenido de los pseudo-elementos debe declararse con declaraciones CSS, para poder mostrarse.

La razón por la que necesita un content: '' statement para cada pseudo-elemento ::before y / or ::after se debe a que el valor inicial del content es normal , que no computa a none en los pseudo-elementos ::after ::before y ::after . Ver la especificación

La razón por la cual el valor inicial del content no es una cadena vacía, sino un valor que no se computa para none para los pseudo-elementos ::before y ::after , es doble:

  1. Tener contenido en línea vacío al principio y al final de cada elemento es bastante tonto. Recuerde que el propósito original de los pseudo-elementos ::before y ::after es insertar el contenido generado antes y después del contenido principal de un elemento de origen. Cuando no hay contenido para insertar, crear un cuadro adicional solo para insertar nada no tiene sentido. Entonces el valor none está allí para decirle al navegador que no se moleste en crear una caja adicional.

    La práctica de usar pseudo-elementos vacíos ::before y ::after para crear cajas adicionales con el único propósito de la estética del diseño es relativamente nueva, y algunos puristas incluso pueden llegar a decir que es un truco por esta razón.

  2. Tener contenido en línea vacío al principio y al final de cada elemento significa que cada elemento (no reemplazado), incluidos html y body , generaría de forma predeterminada no un cuadro, sino hasta tres cuadros (y más en el caso de los elementos que ya generar más que solo el cuadro principal, como elementos con estilos de lista). ¿Cuántas de las dos cajas adicionales por elemento usará realmente? Eso potencialmente puede triplicar el costo del diseño con muy poca ganancia.

    De forma realista, incluso en esta década, menos del 10% de los elementos en una página necesitarán ::before y ::after pseudo-elementos para el diseño.

Por lo tanto, estos pseudoelementos se convierten en opt-in, porque hacer que se excluyan no solo es un desperdicio de recursos del sistema, sino simplemente ilógico dado su propósito original. La razón de rendimiento también es la razón por la que no recomiendo generar pseudo-elementos para cada elemento usando ::before, ::after .

Pero luego puede preguntar: ¿por qué no hacer que la propiedad de display no tenga valor predeterminado en none en ::before, ::after ? Simple: porque el valor inicial de la display no es none ; está en inline Tener un cómputo en inline de none en ::before, ::after no es una opción porque entonces nunca podría mostrarlos en línea. Tener el valor inicial de display none on on ::before, ::after no es una opción porque una propiedad solo puede tener un valor inicial. (Esta es la razón por la que el valor inicial del content siempre es normal y simplemente se define para calcular none en ::before, ::after ).

Hasta que agregue content: ... , el elemento psuedo no existe en realidad.

Establecer otras propiedades de estilo no es suficiente para obligar al navegador a crear el elemento.