Selezione e manipolazione di pseudo-elementi CSS come :: before e :: after using jQuery

C’è un modo per selezionare / manipolare pseudo-elementi CSS come ::before e ::after (e la vecchia versione con un punto e virgola) usando jQuery?

Ad esempio, il mio foglio di stile ha la seguente regola:

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

Come posso cambiare ‘pippo’ in ‘bar’ usando jQuery?

È anche ansible passare il contenuto allo pseudo elemento con un attributo dati e quindi utilizzare jQuery per manipolarlo:

In HTML:

 foo 

In jQuery:

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

In CSS:

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

Se vuoi impedire che venga visualizzato “l’altro testo”, puoi combinarlo con la soluzione di seucolega in questo modo:

In HTML:

 foo 

In jQuery:

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

In CSS:

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

Penseresti che sarebbe una semplice domanda a cui rispondere, con tutto il resto che jQuery può fare. Sfortunatamente, il problema si riduce a un problema tecnico: css: after e: before le regole non fanno parte del DOM, e quindi non possono essere alterate usando i metodi DOM di jQuery.

Ci sono modi per manipolare questi elementi usando JavaScript e / o soluzioni alternative CSS; quale si utilizza dipende dalle vostre esatte esigenze.


Inizierò con quello che è ampiamente considerato l’approccio “migliore”:

1) Aggiungi / rimuovi una class predeterminata

Con questo approccio hai già creato una class nel tuo CSS con una diversa :after o :before style. Inserisci questa “nuova” class più avanti nel tuo foglio di stile per assicurarti che sostituisca:

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

Quindi puoi facilmente aggiungere o rimuovere questa class usando jQuery (o vanilla JavaScript):

 $('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"; } 
  

This is a paragraph.

This is another paragraph.

Sebbene siano resi dai browser tramite CSS come se fossero come altri veri elementi DOM, gli pseudo-elementi stessi non fanno parte del DOM, perché gli pseudo-elementi, come suggerisce il nome, non sono elementi reali, e quindi non è ansible selezionali e manipoli direttamente con jQuery (o con qualsiasi API JavaScript per quella materia, nemmeno con l’ API dei selettori ). Questo vale per tutti gli pseudo-elementi di cui stai cercando di modificare gli stili con uno script e non solo ::before e ::after .

È ansible accedere solo agli stili di pseudo-elementi direttamente in fase di esecuzione tramite CSSOM (si pensi a window.getComputedStyle() ), che non è esposto da jQuery oltre .css() , un metodo che non supporta nemmeno gli pseudo-elementi.

Puoi sempre trovare altri modi per aggirarlo, ad esempio:

  • Applicare gli stili agli pseudo-elementi di una o più classi arbitrarie, quindi passare da una class all’altra (vedere la risposta di seucolega per un rapido esempio) – questo è il modo idiomatico in quanto utilizza i selettori semplici (che non sono pseudo-elementi) per distinguere tra elementi e stati degli elementi, il modo in cui sono destinati ad essere utilizzati

  • Manipolare gli stili applicati a detti pseudo-elementi, alterando il foglio di stile del documento, che è molto più di un hack

Non puoi selezionare gli pseudo elementi in jQuery perché non fanno parte del DOM. Ma puoi aggiungere una class specifica all’elemento padre e controllare i suoi pseudo elementi in CSS.

ESEMPIO

In jQuery:

  

In CSS:

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

Nella linea di ciò che Christian suggerisce, potresti anche fare:

 $('head').append(""); 

Ecco come accedere: after e: before style properties, definite in 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'); 

Ho già risposto a questa domanda, ma per essere super-cool mi ripeterò per te.

La risposta dovrebbe essere Sì e No. Non è ansible selezionare un elemento tramite lo pseudo-selettore, ma è ansible aggiungere una nuova regola al foglio di stile con javascript.

Ho fatto qualcosa che dovrebbe funzionare per te:

 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/

Se vuoi manipolare gli elementi sudo :: before o :: after interamente tramite CSS, potresti farlo JS. Vedi sotto;

 jQuery('head').append(''); 

Nota come l’elemento

abbia un ID, che puoi usare per rimuoverlo e aggiungerlo nuovamente se il tuo stile cambia dynamicmente.

In questo modo, il tuo elemento è lo stile esattamente come lo vuoi attraverso i CSS, con l'aiuto di JS.

Ecco l’HTML:

 
::before

Lo stile calcolato su “prima” era content: "VERIFY TO WATCH";

Ecco le mie due linee di jQuery, che usano l’idea di aggiungere una class extra per fare riferimento specifico a questo elemento e quindi aggiungere un tag di stile (con un tag! Important) per modificare il CSS del valore del contenuto di sudo-elemento:

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

$('body').append("

");

Possiamo anche fare affidamento sulle proprietà personalizzate CSS (variabili) per manipolare lo pseudo-elemento. Possiamo leggere nella specifica che:

Le proprietà personalizzate sono proprietà ordinarie, quindi possono essere dichiarate su qualsiasi elemento, sono risolte con le normali regole di ereditarietà e in cascata , possono essere rese condizionali con @media e altre regole condizionali, possono essere utilizzate nell’attributo di stile HTML , possono essere lette o impostate usando il CSSOM , ecc.

Considerando questo, l’idea è di definire la proprietà personalizzata all’interno dell’elemento e lo pseudo-elemento lo erediterà semplicemente; quindi possiamo facilmente modificarlo:

1) Uso dello stile in linea :

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

un modo di lavorare ma non molto efficace è aggiungere una regola al documento con il nuovo contenuto e farne riferimento con una class. a seconda di ciò che è necessario, la class potrebbe richiedere un ID univoco per ogni valore nel contenuto.

 $("").appendTo($("head")); $('span').addClass('id-after'); 

Grazie a tutti! sono riuscito a fare quello che volevo: D http://jsfiddle.net/Tfc9j/42/ qui dare un’occhiata

volevo che l’opacità di un div esterno fosse diversa dall’opacità del div interno e che cambiasse con un clic da qualche parte;) Grazie!

  $('#ena').on('click', function () { $('head').append(""); }); $('#duop').on('click', function (e) { $('head').append(""); 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%; } 

ena p

duoyyyyyyyyyyyyyy p

Questo non è pratico in quanto non l’ho scritto per gli usi del mondo reale, solo per darti un esempio di ciò che può essere raggiunto.

 css = { before: function(elem,attr){ if($("#cust_style") !== undefined){ $("body").append(""); } else { $("#cust_style").remove(); $("body").append(""); } }, after: function(elem,attr){ if($("#cust_style") !== undefined){ $("body").append(""); } else { $("#cust_style").remove(); $("body").append(""); } } } 

questo attualmente aggiunge un / o aggiunge un elemento Stile che contiene gli attributi necessari che avranno effetto sullo elemento Pseudo dopo l’elemento di destinazione.

questo può essere usato come

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

e

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

come dopo: e prima: gli elementi pseudo non sono direttamente accessibili tramite DOM, non è attualmente ansible modificare liberamente i valori specifici del css.

il mio modo era solo un esempio e non è buono per la pratica, puoi modificarlo provare alcuni dei tuoi trucchi e renderlo corretto per l’utilizzo del mondo reale.

così fai la tua stessa sperimentazione con questo e altri!

saluti – Adarsh ​​Hegde.

Puoi creare una proprietà falsa o usarne una esistente e ereditarla nel foglio di stile dello 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%; } 
  

Perché aggiungere classi o attributi quando puoi semplicemente aggiungere uno style alla testa

 $('head').append('') 

Ci sono molte risposte qui ma nessuna risposta aiuta a manipolare il css di :before o :after , nemmeno quello accettato.

Ecco come propongo di farlo. Supponiamo che il tuo HTML sia così:

 
Test

E poi lo stai impostando: prima in CSS e progettandolo come:

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

Si prega di notare che ho anche impostato l’attributo content nell’elemento stesso in modo da poterlo estrarre facilmente in seguito. Ora c’è un button clic sul quale, vuoi cambiare il colore di: before to green e la sua font-size a 30px. Puoi ottenerlo come segue:

Definisci un css con lo stile richiesto su alcune classi .activeS :

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

Ora puoi cambiare: prima dello stile aggiungendo la class al tuo: before element come segue:

   

Se vuoi solo ottenere il contenuto di :before , può essere fatto come:

   

In definitiva se vuoi cambiare dynamicmente :before contenuto di jQuery, puoi ottenerlo come segue:

   

Cliccando sopra il pulsante “cambia :before di” cambierà :before contenuto di #something in “22” che è un valore dinamico.

spero possa essere d’aiuto

  $('.span').attr('data-txt', 'foo'); $('.span').click(function () { $(this).attr('data-txt',"any other text"); }) 
 .span{ } .span:after{ content: attr(data-txt); } 
  

Puoi usare il mio plugin per questo scopo.

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

Someone else commented on appending to the head element with a full style element and that’s not bad if you’re only doing it once but if you need to reset it more than once you’ll end up with a ton of style elements. So to prevent that I created a blank style element in the head with an id and replace the innerHTML of it like this:

  

Then the JavaScript would look like this:

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

Now in my case I needed this to set the height of a before element based on the height of another and it will change on resize so using this I can run setHeight() every time the window is resized and it will replace the

properly.

Hope that helps someone who was stuck trying to do the same thing.