Pregunta Seleccionar y manipular pseudo-elementos CSS como :: before y :: after usando jQuery


¿Hay alguna forma de seleccionar / manipular pseudo-elementos CSS como ::before y ::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?


782
2018-02-18 12:53


origen


Respuestas:


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 se muestre el "otro texto", puede combinar esto con la solución de seucolega de esta manera:

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';
}

606
2018-04-20 17:59



Podrías pensar que esta sería una pregunta simple de responder, con todo lo demás que jQuery puede hacer. Lamentablemente, el problema se reduce a un problema técnico: css: after y: before rules no son parte del DOM, y por lo tanto no puede ser alterado usando los métodos DOM de jQuery.

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


Comenzaré con lo que se considera ampliamente el "mejor" enfoque:

1) Agregar / eliminar una clase predeterminada

En este enfoque, ya has creado una clase en tu CSS con una diferente :after o :before estilo. 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 usando jQuery (o JavaScript simple):

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

    $('p').on('click', function() {
      $(this).toggleClass('special');
    });
p:before {
  content: "foo";
  color: red;
  cursor: pointer;
}
p.special:before {
  content: "bar";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<p>This is a paragraph.</p>
<p>This is another paragraph.</p>

  • Pros: Fácil de implementar con jQuery; altera rápidamente varios estilos a la vez; impone la separación de las preocupaciones (aislando su CSS y JS de su HTML)
  • Contras: CSS debe estar escrito previamente, por lo que el contenido de :before o :after no 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 :after y :before estilos. 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+'";');

var str = "bar";
document.styleSheets[0].addRule('p.special:before', 'content: "' + str + '";');
p:before {
  content: "foo";
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<p class="special">This is a paragraph</p>
<p>This is another paragraph</p>

.addRule() y lo relacionado .insertRule() métodos están bastante bien apoyados hoy.

Como una 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');

var str = "bar";
$('<style>p.special:before{content:"' + str + '"}</style>').appendTo('head');
p:before {
  content: "foo";
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<p class="special">This is a paragraph</p>
<p>This is another paragraph</p>

Si estamos hablando de "manipular" los valores, no solo de aumentarlos, también podemos leer la existencia :after o :before estilos usando un enfoque diferente:

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

var str = window.getComputedStyle($('p')[0], ':before').getPropertyValue('content');
console.log(str);

document.styleSheets[0].addRule('p.special:before', 'content: "' + str+str + '";');
p:before {
    content:"foo";
    color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<p class="special">This is a paragraph</p>
<p>This is another paragraph</p>

Podemos reemplazar document.querySelector('p') con $('p')[0] cuando se usa 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 DOM crezca arbitrariamente grande

3) Alterar un atributo DOM diferente

También puedes utilizar attr() en tu CSS para leer un atributo de DOM particular. (Si un navegador es compatible :before, es compatible attr() también.) Al combinar esto con content:en algunos CSS cuidadosamente preparados, podemos cambiar el contenido (pero no otras propiedades, como margen o color) de :before y :after dinamicamente:

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

JS:

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

$('p').on('click', function () {
    $(this).attr('data-before','bar');
});
p:before {
    content: attr(data-before);
    color: red;
    cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<p>This is a paragraph.</p>
<p>This is another paragraph.</p>

Esto se puede combinar con la segunda técnica si el CSS no se puede preparar antes de tiempo:

var str = "bar";

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

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

var str = "bar";
document.styleSheets[0].addRule('p:before', 'content: attr(data-before) !important;');

$('p').on('click', function() {
  $(this).attr('data-before', str);
});
p:before {
  content: "foo";
  color: red;
  cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<p>This is a paragraph.</p>
<p>This is another paragraph.</p>

  • Pros: No crea estilos adicionales sin fin
  • Contras:  attr en CSS solo se puede aplicar a las cadenas de contenido, no a las URL ni a los colores RGB

391
2018-02-11 18:14



A pesar de que son renderizados por navegadores a través de CSS como si fueran como otros elementos DOM reales, los pseudo-elementos no son parte del DOM, porque los pseudo-elementos, como su nombre lo indica, no son elementos reales, y por lo tanto no se puede seleccionar y manipularlos directamente con jQuery (o alguna API de JavaScript para el caso, ni siquiera el API de selectores) Esto se aplica a cualquier pseudoelemento cuyos estilos intente modificar con un script, y no solo ::before y ::after.

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

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

  • Aplicar los estilos a los pseudo-elementos de una o más clases arbitrarias, luego alternar entre clases (ver la respuesta de seucolega para un ejemplo rápido): esta es la forma idiomática, ya que utiliza selectores simples (que los pseudo-elementos no) para 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 pseudo-elementos, alterando la hoja de estilo del documento, que es mucho más un hack


144
2018-02-18 12:56



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' }

72
2018-03-17 06:46



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

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

34
2017-10-18 10:20



Aquí está la forma de acceder: after y: before properties, 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');

20
2017-07-15 21:55



He respondido esta pregunta aquí ya, pero para ser súper genial, me repetiré por ti.

La respuesta debería ser Si no. No puede seleccionar un elemento a través de pseudo-selector, pero puede agregar una nueva regla a su hoja de estilo con javascript.

Hice algo que debería funcionar para ti:

var addRule = function(sheet, selector, styles) {
    if (sheet.insertRule) return sheet.insertRule(selector + " {" + styles + "}", sheet.cssRules.length);
    if (sheet.addRule) return sheet.addRule(selector, styles);
};

addRule(document.styleSheets[0], "body:after", "content: 'foo'");

http://fiddle.jshell.net/MDyxg/1/


12
2018-05-12 12:18



SI quiere manipular los elementos sudo :: before o :: after 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> element tiene una ID, que puede usar para eliminarla y anexarla de nuevo si su estilo cambia dinámicamente.

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


11
2018-06-14 20:13



Una forma de trabajo pero no muy eficiente es agregar una regla al documento con el nuevo contenido y referenciarlo con una clase. dependiendo de lo que necesite la clase puede 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
2017-09-12 13:27