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




js css before (14)

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 possibile passare il contenuto allo pseudo elemento con un attributo dati e quindi utilizzare jQuery per manipolarlo:

In HTML:

<span>foo</span>

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:

<span>foo</span>

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

Aggiungo sempre la mia funzione di utilità, che assomiglia a questo.

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

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

o utilizzare le funzionalità di ES6:

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

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

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

Ecco l'HTML:

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

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

Ecco le mie due linee di jQuery, che usano l'idea di aggiungere una classe 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("<style>.G:before{content:'NewText' !important}</style>");


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

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

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

EXAMPLE

In jQuery:

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

In CSS:

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

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

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

Possiamo anche fare affidamento sulle proprietà personalizzate CSS (variabili) per manipolare lo pseudo-elemento. Possiamo leggere nella specification 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.

Tieni presente che le variabili CSS potrebbero non essere disponibili in tutti i browser che consideri pertinenti (ad esempio, IE 11): https://caniuse.com/#feat=css-variables

1) Uso dello stile in linea :

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

2) Uso di CSS e classi

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

.blue {
  --color:blue;
}
.black {
  --color:black;
}
<div class="box"></div>
<div class="box black" ></div>
<div class="box blue"></div>

3) Utilizzo di javascript

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

4) Utilizzo di 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>

Può anche essere utilizzato con valori complessi:

.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>


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!';
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

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

I valori dovrebbero essere specificati, come nella normale funzione di jQuery.css

Inoltre, puoi anche ottenere il valore del parametro pseudo-elemento, come nella normale funzione di jQuery.css:

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

JS:

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

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

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

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

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

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

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

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

      if (typeof parameters.argument === 'object') {
        parameters.argument = (function() {
          var cloneObject = typeof parameters.argument.pop === 'function' ? [] : {};

          for (var property in parameters.argument) {
            cloneObject[property] = parameters.argument[property];
          };

          return cloneObject;
        })();

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

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

        var properties = '';

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

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

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

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

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

        var properties = '';

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

        parameters.element.pseudoElements.styleSheet.addRule(selector, properties, parameters.element.pseudoElements[parameters.pseudoElement].index);
      };
    } else if (parameters.argument !== undefined && parameters.property === undefined) {
      var windowStyle = window.getComputedStyle(
        parameters.element, '::' + parameters.pseudoElement
      ).getPropertyValue(parameters.argument);

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

  Object.defineProperty(Element.prototype, 'styleBefore', {
    enumerable: false,
    value: function(argument, property) {
      return setPseudoElement({
        element: this,
        pseudoElement: 'before',
        argument: argument,
        property: property
      });
    }
  });
  Object.defineProperty(Element.prototype, 'styleAfter', {
    enumerable: false,
    value: function(argument, property) {
      return setPseudoElement({
        element: this,
        pseudoElement: 'after',
        argument: argument,
        property: property
      });
    }
  });
})();

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

.element::before {
  content: 'Old before!';
}
<div class="element"></div>

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


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

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 possibile 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.


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 è possibile 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 .

È possibile 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 classe 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


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

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

Ho fatto uso di variabili definite :rootall'interno CSSper modificare lo pseudo-elemento:after (lo stesso vale per :before) , in particolare per modificare il valore di uno stile definito da e il valore di un altro ( ) nella seguente demo che genera colori casuali utilizzando JavaScript / jQuery:background-coloranchor.sliding-middle-out:hover:aftercontentanchor#referencedemo

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://.com/a/52360188/2149425" id="reference" class="sliding-middle-out" target="_blank" title=" 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("");
 }
);

Qualcun altro ha commentato l'aggiunta all'elemento head con un elemento stile completo e questo non è male se lo fai solo una volta, ma se hai bisogno di resettarlo più di una volta ti ritroverai con un sacco di elementi di stile. Quindi per evitare di aver creato un elemento di stile vuoto nella testa con un id e di sostituirlo con innerHTML come questo:

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

Quindi il JavaScript dovrebbe assomigliare a questo:

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

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

setHeight()

Ora nel mio caso ho avuto bisogno di questo per impostare l'altezza di un elemento precedente in base all'altezza di un altro e cambierà in ridimensionamento in modo da poterlo utilizzare setHeight()ogni volta che la finestra viene ridimensionata e sostituirà <style>correttamente.

Spero che aiuti qualcuno che è stato bloccato a cercare di fare la stessa cosa.







pseudo-element