Seleccionar y manipular pseudoelementos CSS como :: before y :: after usando jQuery


943

¿Hay alguna manera de seleccionar / manipular pseudo-elementos CSS como ::beforey ::after(y la versión anterior con un punto y coma) usando jQuery?

Por ejemplo, mi hoja de estilo tiene la siguiente regla:

.span::after{ content:'foo' }

¿Cómo puedo cambiar 'foo' a 'bar' usando jQuery?


44
Hice algo que debería funcionar para usted: gist.github.com/yckart/5563717
yckart

1
Odio tales comentarios sobre stackoverflow que voy a escribir (donde el comentarista pregunta por qué no lo haces de forma completamente opuesta ), pero: en algún momento uno debería darse cuenta del problema de diseño de código y reemplazar ese pseudo elemento con un lapso o algo Supongo que sabes a lo que estoy apuntando.
zsitro

1
La respuesta aceptada es excelente. Aunque si está tratando de lograr cualquiera de los siguientes puntos, la respuesta no funcionará: 1. cambie el estilo de: before por JS. 2. cambiar el contenido de: antes por JS Por favor, vea mi respuesta si lo necesita.
Estudiante


@Learner Ahora hay una respuesta para todos estos: stackoverflow.com/a/49618941/8620333
Temani Afif

Respuestas:


695

También puede pasar el contenido al pseudo elemento con un atributo de datos y luego usar jQuery para manipular eso:

En HTML:

<span>foo</span>

En jQuery:

$('span').hover(function(){
    $(this).attr('data-content','bar');
});

En CSS:

span:after {
    content: attr(data-content) ' any other text you may want';
}

Si desea evitar que aparezca el 'otro texto', puede combinar esto con la solución de seucolega como esta:

En HTML:

<span>foo</span>

En jQuery:

$('span').hover(function(){
    $(this).addClass('change').attr('data-content','bar');
});

En CSS:

span.change:after {
    content: attr(data-content) ' any other text you may want';
}

2
¿Tiene un enlace en la especificación para usar esa attrfunción contra la contentpropiedad? Me sorprende que nunca haya oído hablar de esto ...
Kevin Peno

95
+1 por attr(), lástima que no pude usarlo con otras propiedades que no sean content. Demostración
Maksim Vi.

28
Esto se debe a que attr()todavía no se ha implementado ningún navegador más allá de CSS2, mientras que en CSS2 attr()solo se ha definido para la contentpropiedad.
BoltClock

10
Enlace actualizado para referencias de atributos: w3.org/TR/css3-values/#attr-notation


477

Pensarías que esta sería una pregunta simple de responder, con todo lo demás que jQuery puede hacer. Desafortunadamente, el problema se reduce a un problema técnico: css: after y: before las reglas no son parte del DOM y , por lo tanto, no pueden modificarse utilizando los métodos DOM de jQuery.

No son formas de manipular estos elementos utilizando JavaScript y / o CSS soluciones; cuál usa depende de sus requisitos exactos.


Voy a comenzar con lo que se considera ampliamente el "mejor" enfoque:

1) Agregar / eliminar una clase predeterminada

En este enfoque, ya ha creado una clase en su CSS con un estilo :aftero :beforeestilo diferente . Coloque esta clase "nueva" más adelante en su hoja de estilo para asegurarse de que anula:

p:before {
    content: "foo";
}
p.special:before {
    content: "bar";
}

Luego, puede agregar o eliminar fácilmente esta clase utilizando jQuery (o JavaScript de vainilla):

$('p').on('click', function() {
    $(this).toggleClass('special');
});

  • Pros: Fácil de implementar con jQuery; altera rápidamente varios estilos a la vez; impone la separación de preocupaciones (aislando su CSS y JS de su HTML)
  • Contras: CSS debe estar preescrito, por lo que el contenido de :beforeo :afterno es completamente dinámico

2) Agregue nuevos estilos directamente a la hoja de estilo del documento

Es posible usar JavaScript para agregar estilos directamente a la hoja de estilo del documento, incluidos los estilos :aftery :before. jQuery no proporciona un atajo conveniente, pero afortunadamente el JS no es tan complicado:

var str = "bar";
document.styleSheets[0].addRule('p.special:before','content: "'+str+'";');

.addRule()y los .insertRule()métodos relacionados están bastante bien soportados hoy.

Como variación, también puede usar jQuery para agregar una hoja de estilo completamente nueva al documento, pero el código necesario no es más limpio:

var str = "bar";
$('<style>p.special:before{content:"'+str+'"}</style>').appendTo('head');

Si estamos hablando de "manipular" los valores, no solo agregarlos, también podemos leer los estilos existentes :aftero:before usar un enfoque diferente:

var str = window.getComputedStyle(document.querySelector('p'), ':before') 
           .getPropertyValue('content');

Podemos reemplazar document.querySelector('p')con $('p')[0]cuando usamos jQuery, para un código ligeramente más corto.

  • Pros: cualquier cadena se puede insertar dinámicamente en el estilo
  • Contras: los estilos originales no se modifican, solo se anulan; el uso repetido (ab) puede hacer que el DOM crezca arbitrariamente grande

3) Alterar un atributo DOM diferente

También puede usar attr()en su CSS para leer un atributo DOM particular. ( Si un navegador es compatible :before, también lo esattr() ) . Al combinar esto con content:un CSS cuidadosamente preparado, podemos cambiar el contenido (pero no otras propiedades, como el margen o el color) :beforey :afterdinámicamente:

p:before {
    content: attr(data-before);
    color: red;
    cursor: pointer;
}

JS:

$('p').on('click', function () {
    $(this).attr('data-before','bar');
});

Esto se puede combinar con la segunda técnica si el CSS no se puede preparar con anticipación:

var str = "bar";

document.styleSheets[0].addRule('p:before', 'content: attr(data-before);');

$('p').on('click', function () {
    $(this).attr('data-before', str);
});

  • Pros: no crea infinitos estilos adicionales
  • Contras: attr en CSS solo se puede aplicar a cadenas de contenido, no a URL o colores RGB

2
Estoy tratando de establecer dinámicamente los valores de glifos (es decir, a través de sus valores hexadecimales) en :: after psedo. contenido: elemento (por ejemplo, contenido: "\ e043";). no parece funcionar para mí, así que supongo que tampoco funciona para valores hexadecimales para glifos.
user2101068

@ user2101068 Debería publicar eso como una nueva pregunta. Tendría que ver todo el código que está usando.
Blazemonger

Blazemonger, gracias por la respuesta rápida ... desafortunadamente, hay un código bastante grande y tomaría un poco de esfuerzo recortar el código relevante. Ya he pasado más de 12 horas tratando de conseguir este trabajo y este fue mi último esfuerzo para lograrlo. Necesito reducir mis pérdidas. Esperaba que pudiera verificar mi suposición de re: valores hexadecimales al usar la técnica que describió en el n. ° 3 anterior (antes del fragmento de código). Puedo insertar una cadena hexadecimal en el elemento de contenido, pero muestra el texto para el valor hexadecimal de glifos en lugar del valor real de glifos. ¿Impresión sin ver todo el código?
user2101068

1
@ user2101068 No use la cadena hexadecimal; en su lugar, copie y pegue el carácter Unicode real en el atributo HTML. jsfiddle.net/mblase75/Lcsjkc5y
Blazemonger

con respecto a la solución 2. y 3. en realidad, puede evitar que la hoja de estilo (sobre) crezca si usa: document.styleSheets [0] .insertRule (regla, índice), luego, usando este índice, puede eliminar las reglas cuando no sea necesario: documento. styleSheets [0] .deleteRule (index)
Picard

158

Aunque los navegadores los representan a través de CSS como si fueran como otros elementos DOM reales, los pseudoelementos en sí no son parte del DOM, porque los pseudoelementos, como su nombre lo indica, no son elementos reales, y por lo tanto no puede selecciónelos y manipúlelos directamente con jQuery (o cualquier API de JavaScript para el caso, ni siquiera la API de Selectores ). Esto se aplica a todos los pseudoelementos cuyos estilos está intentando modificar con un script, y no solo ::beforey ::after.

Solo puede acceder a los estilos de pseudoelementos directamente en tiempo de ejecución a través de CSSOM (think window.getComputedStyle()), que no está expuesto por jQuery más allá .css(), un método que tampoco admite pseudoelementos.

Sin embargo, siempre puede encontrar otras formas de evitarlo, por ejemplo:

  • Aplicando los estilos a los pseudoelementos de una o más clases arbitrarias, luego alternando entre clases (vea la respuesta de seucolega para un ejemplo rápido): esta es la forma idiomática ya que utiliza selectores simples (que no son pseudoelementos) distinguir entre elementos y estados de elementos, la forma en que están destinados a ser utilizados

  • Manipular los estilos que se aplican a dichos pseudoelementos, alterando la hoja de estilo del documento, que es mucho más que un truco


78

No puede seleccionar pseudo elementos en jQuery porque no son parte de DOM. Pero puede agregar una clase específica al elemento padre y controlar sus pseudo elementos en CSS.

EJEMPLO

En jQuery:

<script type="text/javascript">
    $('span').addClass('change');
</script>

En CSS:

span.change:after { content: 'bar' }

48

También podemos confiar en propiedades personalizadas (también conocidas como variables CSS) para manipular el pseudo-elemento. Podemos leer en la especificación que:

Las propiedades personalizadas son propiedades ordinarias, por lo que se pueden declarar en cualquier elemento, se resuelven con la herencia normal y las reglas en cascada , se pueden condicionar con @media y otras reglas condicionales, se pueden usar en el atributo de estilo HTML , se pueden leer o establecer usando el CSSOM , etc.

Considerando esto, la idea es definir la propiedad personalizada dentro del elemento y el pseudo-elemento simplemente la heredará; así podemos modificarlo fácilmente.

1) Usando estilo en línea :

.box:before {
  content:var(--content,"I am a before element");
  color:var(--color, red);
  font-size:25px;
}
<div class="box"></div>
<div class="box" style="--color:blue;--content:'I am a blue element'"></div>
<div class="box" style="--color:black"></div>
<div class="box" style="--color:#f0f;--content:'another element'"></div>

2) Usar CSS y clases

.box:before {
  content:var(--content,"I am a before element");
  color:var(--color, red);
  font-size:25px;
}

.blue {
  --color:blue;
  --content:'I am a blue element';
}
.black {
  --color:black;
}
<div class="box"></div>
<div class="box black" ></div>
<div class="box blue"></div>

3) Usar javascript

document.querySelectorAll('.box')[0].style.setProperty("--color", "blue");
document.querySelectorAll('.box')[1].style.setProperty("--content", "'I am another element'");
.box:before {
  content:var(--content,"I am a before element");
  color:var(--color, red);
  font-size:25px;
}
<div class="box"></div>
<div class="box"></div>

4) Usando jQuery

$('.box').eq(0).css("--color", "blue");
/* the css() function with custom properties works only with a jQuery vesion >= 3.x
   with older version we can use style attribute to set the value. Simply pay
   attention if you already have inline style defined! 
*/
$('.box').eq(1).attr("style","--color:#f0f");
.box:before {
  content:"I am a before element";
  color:var(--color, red);
  font-size:25px;
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>


También se puede usar con valores complejos:

.box {
  --c:"content";
  --b:linear-gradient(red,blue);
  --s:20px;
  --p:0 15px;
}

.box:before {
  content: var(--c);
  background:var(--b);
  color:#fff;
  font-size: calc(2 * var(--s) + 5px);
  padding:var(--p);
}
<div class="box"></div>

Puede notar que estoy considerando la sintaxis var(--c,value)donde valueestá el valor predeterminado y también llamado el valor de reserva.

De la misma especificación podemos leer:

El valor de una propiedad personalizada se puede sustituir por el valor de otra propiedad con la función var (). La sintaxis de var () es:

var() = var( <custom-property-name> [, <declaration-value> ]? )

El primer argumento de la función es el nombre de la propiedad personalizada que se va a sustituir. El segundo argumento de la función, si se proporciona, es un valor de reserva, que se utiliza como valor de sustitución cuando la propiedad personalizada a la que se hace referencia no es válida.

Y después:

Para sustituir un var () en el valor de una propiedad:

  1. Si la propiedad personalizada nombrada por el primer argumento de la var()función está contaminada por la animación, y la var()función se está utilizando en la propiedad de animación o en una de sus manos largas, trate la propiedad personalizada como si tuviera su valor inicial para el resto de este algoritmo.
  2. Si el valor de la propiedad personalizada nombrada por el primer argumento de la var()función es cualquier cosa menos el valor inicial, reemplace la var()función por el valor de la propiedad personalizada correspondiente.
  3. De lo contrario, si la var()función tiene un valor de reserva como segundo argumento, reemplace la var()función por el valor de reserva. Si hay var()referencias en la reserva, sustitúyalas también.
  4. De lo contrario, la propiedad que contiene la var()función no es válida en el momento del valor calculado.

Si no establecemos la propiedad personalizada O la establecemos en initialO si contiene un valor no válido, se utilizará el valor de reserva. El uso de initialpuede ser útil en caso de que queramos restablecer una propiedad personalizada a su valor predeterminado.

Relacionado

¿Cómo almacenar el valor de herencia dentro de una propiedad personalizada CSS (también conocida como variables CSS)?

Propiedades personalizadas de CSS (variables) para el modelo de caja


Tenga en cuenta que las variables CSS pueden no estar disponibles en todos los navegadores que considere relevantes (por ejemplo, IE 11): https://caniuse.com/#feat=css-variables


@akalata sí, el código requiere una versión 3.x de jQuery. Agregué más detalles y otra alternativa con jQuery;)
Temani Afif

¿Cómo funcionaría esto en IE 11?
connexo

1
@connexo tiene gusto de cualquier característica buena y moderna ... no es compatible y no funcionará caniuse.com/#feat=css-variables
Afif

Ofc lo sabía y dado que IE 11 sigue siendo muy relevante, me perdí esa información en la parte introductoria de su respuesta.
connexo

1
Esta respuesta es un tutorial en profundidad sobre cómo relacionar y modificar pseudoelementos con JavaScript usando CSS Variables. Muchas gracias por su tiempo y por compartir esta (s) técnica (s) extremadamente valiosas.
LebCit

37

En la línea de lo que sugiere Christian, también podrías hacer:

$('head').append("<style>.span::after{ content:'bar' }</style>");

2
Aquí se debe agregar un atributo id, para que el elemento se pueda seleccionar y eliminar antes de agregar uno nuevo. Si no, pueden aparecer muchos nodos de estilo innecesarios.
KS

24

Aquí está la forma de acceder: después y: antes de las propiedades de estilo, definidas en css:

// Get the color value of .element:before
var color = window.getComputedStyle(
    document.querySelector('.element'), ':before'
).getPropertyValue('color');

// Get the content value of .element:before
var content = window.getComputedStyle(
    document.querySelector('.element'), ':before'
).getPropertyValue('content');

11

SI desea manipular los elementos :: before o :: after sudo completamente a través de CSS, puede hacerlo JS. Vea abajo;

jQuery('head').append('<style id="mystyle" type="text/css"> /* your styles here */ </style>');

Observe cómo el <style>elemento tiene una ID, que puede usar para eliminarlo y agregarlo nuevamente si su estilo cambia dinámicamente.

De esta manera, su elemento es el estilo exactamente como lo desea a través de CSS, con la ayuda de JS.


6

Una manera funcional pero no muy eficiente es agregar una regla al documento con el nuevo contenido y hacer referencia a ella con una clase. dependiendo de lo que se necesite, la clase podría necesitar una identificación única para cada valor en el contenido.

$("<style type='text/css'>span.id-after:after{content:bar;}</style>").appendTo($("head"));
$('span').addClass('id-after');

5

Aquí está el HTML:

<div class="icon">
  <span class="play">
    ::before
  </span>
</div>

El estilo calculado en 'antes' era content: "VERIFY TO WATCH";

Aquí están mis dos líneas de jQuery, que utilizan la idea de agregar una clase adicional para hacer referencia específica a este elemento y luego agregar una etiqueta de estilo (con una etiqueta! Important) para cambiar el CSS del valor de contenido del elemento sudo:

$("span.play:eq(0)").addClass('G');

$('body').append("<style>.G:before{content:'NewText' !important}</style>");


5

¡Gracias a todos! logré hacer lo que quería: D http://jsfiddle.net/Tfc9j/42/ aquí eche un vistazo

Quería que la opacidad de un div externo fuera diferente de la opacidad del div interno y que cambiara con un clic en alguna parte;) ¡Gracias!

   $('#ena').on('click', function () {
        $('head').append("<style>#ena:before { opacity:0.3; }</style>");
    });

$('#duop').on('click', function (e) {

        $('head').append("<style>#ena:before { opacity:0.8; }</style>");

     e.stopPropagation(); 
    });

#ena{
    width:300px;
    height:300px;
    border:1px black solid;
    position:relative;
}
#duo{
    opacity:1;
    position:absolute;
    top:50px;
  width:300px;
    height:100px;
      background-color:white;
}
#ena:before {
    content: attr(data-before);
    color: white;
    cursor: pointer;
    position: absolute;
    background-color:red;
    opacity:0.9;
    width:100%;
    height:100%;
}


<div id="ena">
    <div id="duo">
        <p>ena p</p>
        <p id="duop">duoyyyyyyyyyyyyyy p</p>

    </div>   


</div>

No intente append, el uso htmles mejor prevenir
KingRider

1
Cuidado: aquí está agregando una etiqueta de estilo a la cabeza cada vez que se maneja uno de esos clics. Codificaría una forma de eliminar la anterior antes de agregar una nueva.
pupitetris

3

Puede crear una propiedad falsa o usar una existente y heredarla en la hoja de estilo del pseudo-elemento.

var switched = false;

// Enable color switching
setInterval(function () {
    var color = switched ? 'red' : 'darkred';
    var element = document.getElementById('arrow');
    element.style.backgroundColor = color;
    
    // Managing pseudo-element's css
    // using inheritance.
    element.style.borderLeftColor = color;
    
    switched = !switched;
}, 1000);
.arrow {
    /* SET FICTIONAL PROPERTY */
    border-left-color:red;
    
    background-color:red;
    width:1em;
    height:1em;
    display:inline-block;
    position:relative;
}
.arrow:after {
    border-top:1em solid transparent;
    border-right:1em solid transparent;
    border-bottom:1em solid transparent;
    border-left:1em solid transparent;
    
    /* INHERIT PROPERTY */
    border-left-color:inherit;
    
    content:"";
    width:0;
    height:0;
    position:absolute;
    left:100%;
    top:-50%;
}
<span id="arrow" class="arrow"></span>

Parece que no funciona para la propiedad "contenido" :(


3

Esto no es práctico ya que no escribí esto para usos del mundo real, solo para darle un ejemplo de lo que se puede lograr.

css = {
before: function(elem,attr){ 

if($("#cust_style") !== undefined){ 
$("body").append("<style> " + elem + ":before {"  + attr +  "} </style>"); 
} else {
 $("#cust_style").remove();
$("body").append("<style> " + elem + ":before {"  + attr +  "} </style>"); 
}

}, after: function(elem,attr){
if($("#cust_style") !== undefined){ 
$("body").append("<style> " + elem + ":after {"  + attr +  "} </style>"); 

} else { $("#cust_style").remove();
$("body").append("<style> " + elem + ":after {"  + attr +  "} </style>"); 
}
}
}

esto actualmente agrega a / o agrega un elemento Style que contiene los atributos necesarios que tendrán efecto en el elemento objetivo después del Pseudo elemento.

esto se puede usar como

css.after("someElement"," content: 'Test'; position: 'absolute'; ") // editing / adding styles to :after

y

css.before( ... ); // to affect the before pseudo element.

como after: y before: los pseudo elementos no son accesibles directamente a través de DOM, actualmente no es posible editar los valores específicos de css libremente.

mi manera fue solo un ejemplo y no es bueno para la práctica, puedes modificarlo para probar algunos de tus propios trucos y corregirlo para el uso en el mundo real.

¡así que haz tu propia experimentación con esto y otros!

saludos - Adarsh ​​Hegde.


3

Siempre estoy agregando mi propia función de utilidades, que se ve así.

function setPseudoElContent(selector, value) {    
    document.styleSheets[0].addRule(selector, 'content: "' + value + '";');
}

setPseudoElContent('.class::after', 'Hello World!');

o haga uso de las características de ES6:

const setPseudoElContent = (selector, value) => {    
    document.styleSheets[0].addRule(selector, `content: "${value}";`);
}

setPseudoElContent('.class::after', 'Hello World!');

2

¿Por qué agregar clases o atributos cuando solo puede agregar un styleencabezado?

$('head').append('<style>.span:after{ content:'changed content' }</style>')

2

Aquí hay muchas respuestas, pero ninguna respuesta ayuda a manipular el CSS de :beforeo :after, ni siquiera el aceptado.

Así es como me propongo hacerlo. Supongamos que su HTML es así:

<div id="something">Test</div>

Y luego está configurando su: antes en CSS y diseñándolo como:

#something:before{
   content:"1st";
   font-size:20px;
   color:red;
}
#something{
  content:'1st';
}

Tenga en cuenta que también configuro el contentatributo en el elemento mismo para que pueda eliminarlo fácilmente más adelante. Ahora hay un buttonclic en el que desea cambiar el color de: antes a verde y su tamaño de fuente a 30px. Puede lograr eso de la siguiente manera:

Defina un CSS con su estilo requerido en alguna clase .activeS:

.activeS:before{
   color:green !important;
   font-size:30px !important;
 }

Ahora puede cambiar el estilo: before agregando la clase a su elemento: before de la siguiente manera:

<button id="changeBefore">Change</button>
<script>
    $('#changeBefore').click(function(){
        $('#something').addClass('activeS');
    });
</script>

Si solo desea obtener contenido :before, puede hacerlo como:

<button id="getContent">Get Content</button>
<script>
    $('#getContent').click(function(){
        console.log($('#something').css('content'));//will print '1st'
    });
</script>

En última instancia, si desea cambiar dinámicamente el :beforecontenido mediante jQuery, puede lograrlo de la siguiente manera:

<button id="changeBefore">Change</button>
<script>
    var newValue = '22';//coming from somewhere
    var add = '<style>#something:before{content:"'+newValue+'"!important;}</style>';
    $('#changeBefore').click(function(){
        $('body').append(add);
    });
</script>

Al hacer clic en el botón "cambiar antes" cambiará el :beforecontenido #somethinga '22', que es un valor dinámico.

Espero que ayude


1

Hice uso de variables definidas en el :rootinterior CSSpara modificar el pseudo-elemento:after (lo mismo se aplica a :before) , en particular para cambiar el valor de un estilo definido por y el valor de otro ( ) en la siguiente demostración que genera colores aleatorios mediante JavaScript / jQuery:background-coloranchor.sliding-middle-out:hover:aftercontentanchor#reference

HTML

<a href="#" id="changeColor" class="sliding-middle-out" title="Generate a random color">Change link color</a>
<span id="log"></span>
<h6>
  <a href="https://stackoverflow.com/a/52360188/2149425" id="reference" class="sliding-middle-out" target="_blank" title="Stack Overflow topic">Reference</a>
</h6>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.rawgit.com/davidmerfield/randomColor/master/randomColor.js"></script>

CSS

:root {
    --anchorsFg: #0DAFA4;
}
a, a:visited, a:focus, a:active {
    text-decoration: none;
    color: var(--anchorsFg);
    outline: 0;
    font-style: italic;

    -webkit-transition: color 250ms ease-in-out;
    -moz-transition: color 250ms ease-in-out;
    -ms-transition: color 250ms ease-in-out;
    -o-transition: color 250ms ease-in-out;
    transition: color 250ms ease-in-out;
}
.sliding-middle-out {
    display: inline-block;
    position: relative;
    padding-bottom: 1px;
}
.sliding-middle-out:after {
    content: '';
    display: block;
    margin: auto;
    height: 1px;
    width: 0px;
    background-color: transparent;

    -webkit-transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
    -moz-transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
    -ms-transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
    -o-transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
    transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
}
.sliding-middle-out:hover:after {
    width: 100%;
    background-color: var(--anchorsFg);
    outline: 0;
}
#reference {
  margin-top: 20px;
}
.sliding-middle-out:before {
  content: attr(data-content);
  display: attr(data-display);
}

JS / jQuery

var anchorsFg = randomColor();
$( ".sliding-middle-out" ).hover(function(){
    $( ":root" ).css({"--anchorsFg" : anchorsFg});
});

$( "#reference" ).hover(
 function(){
    $(this).attr("data-content", "Hello World!").attr("data-display", "block").html("");
 },
 function(){
    $(this).attr("data-content", "Reference").attr("data-display", "inline").html("");
 }
);

El soporte para attr()excepto en content, es realmente escaso. Puede consultar caniuse.com para ello. :rooty el soporte de css-variables es mejor, pero aún no está tan extendido ya que el soporte es bastante nuevo. (también verifique el soporte en caniuse.com)
BananaAcid

1

He creado un complemento jQuery para agregar css-pseudo reglas como usar .css()elementos específicos.

  • el código del complemento y el caso de prueba está aquí
  • use el caso como una simple ventana emergente de imagen CSS aquí

uso:

$('body')
  .css({
    backgroundColor: 'white'
  })
  .cssPseudo('after', {
    content: 'attr(title) ", you should try to hover the picture, then click it."',
    position: 'absolute',
    top: 20, left: 20  
  })
  .cssPseudo('hover:after', {
    content: '"Now hover the picture, then click it!"'
  });

0

 $('.span').attr('data-txt', 'foo');
        $('.span').click(function () {
         $(this).attr('data-txt',"any other text");
        })
.span{
}
.span:after{ 
  content: attr(data-txt);
 }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class='span'></div>


0

Puedes usar mi plugin para este propósito.

JQuery:

(function() {
  $.pseudoElements = {
    length: 0
  };

  var setPseudoElement = function(parameters) {
    if (typeof parameters.argument === 'object' || (parameters.argument !== undefined && parameters.property !== undefined)) {
      for (var element of parameters.elements.get()) {
        if (!element.pseudoElements) element.pseudoElements = {
          styleSheet: null,
          before: {
            index: null,
            properties: null
          },
          after: {
            index: null,
            properties: null
          },
          id: null
        };

        var selector = (function() {
          if (element.pseudoElements.id !== null) {
            if (Number(element.getAttribute('data-pe--id')) !== element.pseudoElements.id) element.setAttribute('data-pe--id', element.pseudoElements.id);
            return '[data-pe--id="' + element.pseudoElements.id + '"]::' + parameters.pseudoElement;
          } else {
            var id = $.pseudoElements.length;
            $.pseudoElements.length++

              element.pseudoElements.id = id;
            element.setAttribute('data-pe--id', id);

            return '[data-pe--id="' + id + '"]::' + parameters.pseudoElement;
          };
        })();

        if (!element.pseudoElements.styleSheet) {
          if (document.styleSheets[0]) {
            element.pseudoElements.styleSheet = document.styleSheets[0];
          } else {
            var styleSheet = document.createElement('style');

            document.head.appendChild(styleSheet);
            element.pseudoElements.styleSheet = styleSheet.sheet;
          };
        };

        if (element.pseudoElements[parameters.pseudoElement].properties && element.pseudoElements[parameters.pseudoElement].index) {
          element.pseudoElements.styleSheet.deleteRule(element.pseudoElements[parameters.pseudoElement].index);
        };

        if (typeof parameters.argument === 'object') {
          parameters.argument = $.extend({}, parameters.argument);

          if (!element.pseudoElements[parameters.pseudoElement].properties && !element.pseudoElements[parameters.pseudoElement].index) {
            var newIndex = element.pseudoElements.styleSheet.rules.length || element.pseudoElements.styleSheet.cssRules.length || element.pseudoElements.styleSheet.length;

            element.pseudoElements[parameters.pseudoElement].index = newIndex;
            element.pseudoElements[parameters.pseudoElement].properties = parameters.argument;
          };

          var properties = '';

          for (var property in parameters.argument) {
            if (typeof parameters.argument[property] === 'function')
              element.pseudoElements[parameters.pseudoElement].properties[property] = parameters.argument[property]();
            else
              element.pseudoElements[parameters.pseudoElement].properties[property] = parameters.argument[property];
          };

          for (var property in element.pseudoElements[parameters.pseudoElement].properties) {
            properties += property + ': ' + element.pseudoElements[parameters.pseudoElement].properties[property] + ' !important; ';
          };

          element.pseudoElements.styleSheet.addRule(selector, properties, element.pseudoElements[parameters.pseudoElement].index);
        } else if (parameters.argument !== undefined && parameters.property !== undefined) {
          if (!element.pseudoElements[parameters.pseudoElement].properties && !element.pseudoElements[parameters.pseudoElement].index) {
            var newIndex = element.pseudoElements.styleSheet.rules.length || element.pseudoElements.styleSheet.cssRules.length || element.pseudoElements.styleSheet.length;

            element.pseudoElements[parameters.pseudoElement].index = newIndex;
            element.pseudoElements[parameters.pseudoElement].properties = {};
          };

          if (typeof parameters.property === 'function')
            element.pseudoElements[parameters.pseudoElement].properties[parameters.argument] = parameters.property();
          else
            element.pseudoElements[parameters.pseudoElement].properties[parameters.argument] = parameters.property;

          var properties = '';

          for (var property in element.pseudoElements[parameters.pseudoElement].properties) {
            properties += property + ': ' + element.pseudoElements[parameters.pseudoElement].properties[property] + ' !important; ';
          };

          element.pseudoElements.styleSheet.addRule(selector, properties, element.pseudoElements[parameters.pseudoElement].index);
        };
      };

      return $(parameters.elements);
    } else if (parameters.argument !== undefined && parameters.property === undefined) {
      var element = $(parameters.elements).get(0);

      var windowStyle = window.getComputedStyle(
        element, '::' + parameters.pseudoElement
      ).getPropertyValue(parameters.argument);

      if (element.pseudoElements) {
        return $(parameters.elements).get(0).pseudoElements[parameters.pseudoElement].properties[parameters.argument] || windowStyle;
      } else {
        return windowStyle || null;
      };
    } else {
      console.error('Invalid values!');
      return false;
    };
  };

  $.fn.cssBefore = function(argument, property) {
    return setPseudoElement({
      elements: this,
      pseudoElement: 'before',
      argument: argument,
      property: property
    });
  };
  $.fn.cssAfter = function(argument, property) {
    return setPseudoElement({
      elements: this,
      pseudoElement: 'after',
      argument: argument,
      property: property
    });
  };
})();

$(function() {
  $('.element').cssBefore('content', '"New before!"');
});
.element {
  width: 480px;
  margin: 0 auto;
  border: 2px solid red;
}

.element::before {
  content: 'Old before!';
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

<div class="element"></div>

Los valores deben especificarse, como en la función normal de jQuery.css

Además, también puede obtener el valor del parámetro pseudoelemento, como en la función normal de jQuery.css:

console.log( $(element).cssBefore(parameter) );

JS:


GitHub: https://github.com/yuri-spivak/managing-the-properties-of-pseudo-elements/


0

Alguien más comentó sobre agregar al elemento head con un elemento de estilo completo y eso no está mal si solo lo está haciendo una vez, pero si necesita restablecerlo más de una vez, terminará con una tonelada de elementos de estilo. Entonces, para evitar eso, creé un elemento de estilo en blanco en la cabeza con una identificación y reemplacé el innerHTML de esta manera:

<style id="pseudo"></style>

Entonces el JavaScript se vería así:

var pseudo = document.getElementById("pseudo");

function setHeight() {
    let height = document.getElementById("container").clientHeight;
    pseudo.innerHTML = `.class:before { height: ${height}px; }`
}

setHeight()

Ahora, en mi caso, necesitaba esto para establecer la altura de un elemento anterior en función de la altura de otro y cambiará al cambiar el tamaño, así que usando esto puedo ejecutar setHeight() cada vez la ventana y reemplazará <style>correctamente.

Espero que ayude a alguien que estaba atrapado tratando de hacer lo mismo.


-1

Tengo algo diferente para ti que es fácil y efectivo.

    <style> 
    .case-after:after { // set your properties here like eg: 
        color:#3fd309 !important; 
     } 
     .case-before:before { // set your properties here like eg: 
        color:#151715 !important; 
     }
 </style>
  // case for after
    $('#button-id').on('click', function() {
        $(".target-div").toggleClass('case-after');
    });

     // case for before
    $('#button-id').on('click', function() {
        $(".target-div").toggleClass('case-before');
    });
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.