Выбор и управление псевдоэлементами CSS, такими как::before и:: после использования jQuery

Есть ли способ выбрать / манипулировать псевдоэлементами CSS, такими как ::before а также ::after (и старая версия с одной точкой с запятой), используя jQuery?

Например, моя таблица стилей имеет следующее правило:

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

Как я могу изменить 'foo' на 'bar', используя jQuery?

29 ответов

Решение

Вы также можете передать содержимое в псевдоэлемент с атрибутом данных, а затем использовать jQuery для управления этим:

В HTML:

<span>foo</span>

В jQuery:

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

В CSS:

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

Если вы хотите предотвратить отображение "другого текста", вы можете объединить это с решением seucolega, например:

В HTML:

<span>foo</span>

В jQuery:

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

В CSS:

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

Вы могли бы подумать, что это будет простой вопрос, со всем остальным, что может сделать jQuery. К сожалению, проблема сводится к технической проблеме: css: after и:before правила не являются частью DOM и поэтому не могут быть изменены с использованием методов DOM jQuery.

Есть способы манипулировать этими элементами, используя обходные пути JavaScript и / или CSS; какой из них вы используете, зависит от ваших конкретных требований.


Я собираюсь начать с того, что широко считается "лучшим" подходом:

1) Добавить / удалить заранее определенный класс

При таком подходе вы уже создали класс в своем CSS с другим :after или же :before стиль. Поместите этот "новый" класс позже в таблицу стилей, чтобы убедиться, что он переопределяет:

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

Затем вы можете легко добавить или удалить этот класс, используя jQuery (или ванильный 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";
}
<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>

  • Плюсы: легко реализовать с помощью jQuery; быстро меняет несколько стилей одновременно; обеспечивает разделение интересов (изоляция вашего CSS и JS от вашего HTML)
  • Минусы: CSS должен быть написан заранее, поэтому содержание :before или же :after не полностью динамический

2) Добавить новые стили непосредственно в таблицу стилей документа

Можно использовать JavaScript для добавления стилей непосредственно в таблицу стилей документа, в том числе :after а также :before стили. JQuery не предоставляет удобного ярлыка, но, к счастью, JS не так уж и сложен:

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() и связанные .insertRule() методы довольно хорошо поддерживаются сегодня.

В качестве варианта вы также можете использовать jQuery для добавления в документ совершенно новой таблицы стилей, но необходимый код не так уж чист:

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>

Если мы говорим о "манипулировании" значениями, а не просто о добавлении к ним, мы также можем прочитать существующие :after или же :before стили, использующие другой подход:

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>

Мы можем заменить document.querySelector('p') с $('p')[0] при использовании jQuery, для немного более короткого кода.

  • Плюсы: любая строка может быть динамически вставлена ​​в стиль
  • Минусы: оригинальные стили не изменены, просто переопределены; повторное (ab) использование может сделать DOM произвольно большим

3) Изменить другой атрибут DOM

Вы также можете использовать attr() в вашем CSS, чтобы прочитать определенный атрибут DOM. ( Если браузер поддерживает :before поддерживает attr() также.) Объединив это с content: в некоторых тщательно подготовленных CSS мы можем изменить содержимое (но не другие свойства, такие как поле или цвет) :before а также :after динамически:

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>

Это может быть объединено со вторым методом, если CSS не может быть подготовлен заранее:

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>

  • Плюсы: не создает бесконечных дополнительных стилей
  • Минусы: attr в CSS можно применять только к строкам контента, а не к URL или цветам RGB

Хотя они отображаются браузерами через CSS, как если бы они были похожи на другие настоящие элементы DOM, сами псевдоэлементы не являются частью DOM, поскольку псевдоэлементы, как следует из названия, не являются реальными элементами, и поэтому вы не можете выбирайте и манипулируйте ими напрямую с помощью jQuery (или любых других API-интерфейсов JavaScript, даже API-интерфейсов Selectors). Это относится ко всем псевдоэлементам, стили которых вы пытаетесь изменить с помощью скрипта, а не только к ::before а также ::after,

Вы можете получить доступ только к стилям псевдоэлементов непосредственно во время выполнения через CSSOM (подумайте window.getComputedStyle()), который не доступен через jQuery .css(), метод, который также не поддерживает псевдоэлементы.

Вы всегда можете найти другие способы обойти это, например, например:

  • Применение стилей к псевдоэлементам одного или нескольких произвольных классов, а затем переключение между классами (см . Ответ seucolega для быстрого примера) - это идиоматический способ, так как он использует простые селекторы (которые псевдоэлементы не являются) для различать элементы и состояния элементов по способу их использования

  • Манипулирование стилями, применяемыми к указанным псевдоэлементам, путем изменения таблицы стилей документа, что гораздо больше

Мы также можем положиться на пользовательские свойства (переменные) CSS для манипулирования псевдоэлементом. Мы можем прочитать в спецификации, что:

Пользовательские свойства - это обычные свойства, поэтому они могут быть объявлены для любого элемента, разрешены с помощью нормальных правил наследования и каскада, могут быть сделаны условными с помощью @media и других условных правил, могут быть использованы в атрибуте стиля HTML, могут быть прочитаны или установлены использование CSSOM и т. д.

Учитывая это, идея состоит в том, чтобы определить пользовательское свойство внутри элемента, и псевдоэлемент просто наследует его; таким образом, мы можем легко изменить его.

Обратите внимание, что переменные CSS могут быть доступны не во всех браузерах, которые вы считаете актуальными (например, IE 11): https://caniuse.com/

1) Использование встроенного стиля:

.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) Использование CSS и классов

.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) Использование 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) Использование 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>


Он также может использоваться со сложными значениями:

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

Вы не можете выбрать псевдоэлементы в jQuery, потому что они не являются частью DOM. Но вы можете добавить определенный класс к элементу Father и управлять его псевдоэлементами в CSS.

ПРИМЕР

В jQuery:

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

В CSS:

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

В соответствии с тем, что предлагает Кристиан, вы также можете сделать:

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

Вот способ доступа к свойствам стиля:after и:before, определенных в 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');

Если вы хотите манипулировать элементами::before или:: after sudo полностью через CSS, вы можете сделать это с помощью JS. Увидеть ниже;

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

Обратите внимание, как <style> Элемент имеет идентификатор, который вы можете использовать для его удаления и добавления к нему снова, если ваш стиль изменяется динамически.

Таким образом, ваш элемент разрабатывается именно так, как вы хотите, используя CSS, с помощью JS.

Я уже ответил на этот вопрос здесь, но чтобы быть супер-крутым, я повторюсь для вас.

Ответ должен быть да и нет. Вы не можете выбрать элемент с помощью псевдо-селектора, но вы можете добавить новое правило в вашу таблицу стилей с помощью JavaScript.

Я сделал то, что должно работать для вас:

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/

Спасибо вам всем! мне удалось сделать то, что я хотел: D http://jsfiddle.net/Tfc9j/42/ здесь посмотрите

я хотел, чтобы непрозрачность внешнего div отличалась от непрозрачности внутреннего div, и это изменилось одним щелчком мыши;) Спасибо!

   $('#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>

Один работающий, но не очень эффективный способ - добавить правило в документ с новым содержимым и сослаться на него с помощью класса. в зависимости от того, что нужно, классу может потребоваться уникальный идентификатор для каждого значения в контенте.

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

Вот HTML-код:

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

Вычисленный стиль на "до" был content: "VERIFY TO WATCH";

Вот мои две строки jQuery, в которых используется идея добавления дополнительного класса для конкретной ссылки на этот элемент, а затем добавления тега стиля (с тегом! Важный) для изменения CSS значения содержимого элемента sudo:

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

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

Это не практично, так как я не писал это для реальных целей, просто чтобы дать вам пример того, чего можно достичь.

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

в настоящее время это добавляет / или добавляет элемент Style, который содержит необходимые атрибуты, которые будут влиять на целевой элемент после псевдоэлемента.

это можно использовать как

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

а также

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

поскольку after: и before: псевдоэлементы не доступны напрямую через DOM, в настоящее время невозможно свободно редактировать Конкретные значения css.

Мой путь был просто примером, и он не годится для практики, вы можете изменить его, попробовать свои собственные приемы и сделать его правильным для использования в реальном мире.

так что делайте свои собственные эксперименты с этим и другими!

С уважением - Адарш Хегде.

Я всегда добавляю свою собственную функцию утилит, которая выглядит следующим образом.

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

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

или используйте ES6

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

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

Вы можете создать поддельное свойство или использовать существующее и наследовать его в таблице стилей псевдоэлемента.

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>

Кажется, это не работает для свойства "content":(

Зачем добавлять классы или атрибуты, когда вы можете просто добавить style возглавить

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

Здесь много ответов, но ни один из них не помогает манипулировать CSS :before или же :after даже не принятый.

Вот как я предлагаю это сделать. Предположим, ваш HTML похож на это:

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

И тогда вы устанавливаете его: before в CSS и проектируете его так:

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

Пожалуйста, обратите внимание, я также установил content атрибут самого элемента, чтобы вы могли легко вынуть его позже. Сейчас есть button нажав на которую, вы хотите изменить цвет: before на зеленый и его размер шрифта на 30px. Вы можете достичь этого следующим образом:

Определите CSS с вашим требуемым стилем на некотором классе .activeS:

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

Теперь вы можете изменить стиль: before, добавив класс в элемент your: before следующим образом:

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

Если вы просто хотите получить содержание :before, это можно сделать как:

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

В конечном счете, если вы хотите динамически изменить :before Content by jQuery, Вы можете добиться этого следующим образом:

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

Нажатие на кнопку "changeBefore" выше изменится :before содержание #something в "22", который является динамическим значением.

Я надеюсь, что это помогает

Вы можете использовать мой плагин для этой цели.

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>

Значения должны быть указаны, как в обычной функции jQuery.css

Кроме того, вы также можете получить значение параметра псевдоэлемента, как в обычной функции 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/

В первый раз я не читаю все полученные ответы перед тем, как дать свой, так что надеюсь, что это меня не укусит ...

В моем случае это было необходимо для значков, прикрепленных к a, div и button элементы, которые работали немного иначе, чем <i class="icon-class"></i> поскольку не было icon-classкласс на них. Добавление class="icon-class" сломал стиль хотя.

Вместо этого я добавил к ним атрибут со значением того, что должно было быть в element::before { content: "HERE" } а затем этот довольно простой JavaScript позаботился обо всем остальном.

          {
        const fakeIcons = document.querySelectorAll('[data-icon]')

        for (const iconElement of fakeIcons) {

            const fakeClass = 'fake-' + Array.from(Array(20), () => Math.floor(Math.random() * 36).toString(36)).join('')
            const beforeContent = iconElement.getAttribute('data-icon')

            iconElement.classList.add(fakeClass)

            const style = document.createElement('style')
            style.type = 'text/css'
            style.innerHTML = `

                .${fakeClass}::before {
                    content: "${beforeContent}" !important;
                }

            `
            document.getElementsByTagName('head')[0].appendChild(style)
        }
    }

Объяснение кода:

  • выбрать все элементы с указанным атрибутом ()
  • пройти через них
  • произвольно сгенерировать имя класса, начинающееся с fake-, за которым следует случайная буквенно-цифровая строка
  • получать data-icon значение атрибута
  • добавить к элементу случайно сгенерированный класс
  • создать стиль для ::before псевдоэлемент устанавливает для содержимого ранее полученное значение
  • добавить стиль в конец <head> HTML-элемент

В Vanilla JS вы можете сделать что-то вроде этого: 1- вместо непосредственного редактирования ::before ::after используйте переменные CSS!

в CSS:

      :root{
   --bg: red;
}

Наша стихия:

      div::after{
   background: var(--bg) 
}

В JS измените это так:

      let r = document.querySelector(':root');
r.style.setProperty('--bg', `blue`)

В приведенном ниже решении рассказывается, как вы можете обновлять псевдоэлементы с помощью атрибута javascript attr .

добавьте атрибут в HTML, которым вы можете управлять с помощью javascript с помощью setAttribute.

      <div 
 id="inputBoxParent" 
 count="0">
      ...
</div>

обновить с помощью js

      inputBoxParent.setAttribute('count', value.length)

CSS - в псевдоэлементе добавить контент как attr (attributeName)

      .input-box-container::after{
  content: attr(count);
}

И готово !!!

Я создал плагин JQuery для добавления псевдо-правил CSS, как с помощью .css() для конкретных элементов.

  • код плагина и тестовый пример здесь
  • используйте случай как простое всплывающее окно

использование:

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

Я использовал переменные, определенные в :root внутри CSS изменить :after (то же самое относится к :before) псевдоэлемента, в частности, для изменения background-color значение для стиля anchor определяется .sliding-middle-out:hover:after и content значение для другого anchor (#reference) в следующей демонстрации, которая генерирует случайные цвета с помощью JavaScript / jQuery:

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://stackru.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("");
 }
);

Кто-то еще прокомментировал добавление к элементу head с полным элементом стиля, и это неплохо, если вы делаете это только один раз, но если вам нужно сбросить его более одного раза, вы получите массу элементов стиля. Поэтому, чтобы предотвратить это, я создал пустой элемент стиля в голове с идентификатором и заменил его на innerHTML следующим образом:

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

Тогда JavaScript будет выглядеть так:

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

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

setHeight()

Теперь в моем случае мне нужно было установить высоту элемента before, основанного на высоте другого, и он изменится при изменении размера, поэтому с помощью этого я могу запустить setHeight() каждый раз, когда окно изменяется, и оно заменит <style> должным образом.

Надеюсь, это поможет тому, кто застрял, пытаясь сделать то же самое.

 $('.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>

Просто установите псевдоним до или после, чтобы иметь стиль наследования, а затем установите родительский стиль с помощью javascript.

Итак, например, я хочу изменить цветовой стиль : before, затем я устанавливаю:

      .my-style::before{
color: inherit;
}

Тогда я просто изменить стиль цвета на .my стиль элемента с JavaScript:

      document.querySelector(".my-style").style.color = red;

работа сделана, супер просто

У меня для вас есть кое-что другое, простое и эффективное.

    <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');
    });
      function getRuleWithSelector(selector) {
  var numSheets = document.styleSheets.length,
    numRules,
    sheetIndex,
    ruleIndex;
  // Search through the style sheets.
  for (sheetIndex = 0; sheetIndex < numSheets; sheetIndex += 1) {
    numRules = document.styleSheets[sheetIndex].cssRules.length;
    for (ruleIndex = 0; ruleIndex < numRules; ruleIndex += 1) {
      if (document.styleSheets[sheetIndex].cssRules[ruleIndex].selectorText == selector) {
        return document.styleSheets[sheetIndex].cssRules[ruleIndex];
      }
    }
  }
  // If we get this far, then the rule doesn't exist.
  // So the return value is undefined.
}

Используйте эту функцию, чтобы выбрать элемент CSS, например селектор запроса, а затем просто измените его свойство стиля, например

      getRuleWithSelector('.navmenu ul li::after').style.top="15%" 

но для правильного использования этой функции ваш код должен импортировать таблицы стилей CSS в ваш DOM, например этот синтаксис

      <link rel="stylesheet" href="css/custom.css">

а также он должен прийти с вашего сервера. Если таблица стилей поступает с другого сервера, она должна выдать ошибку безопасности.

Обратитесь к этому сообщению document.styleSheets не обнаруживает все таблицы стилей , но в большинстве случаев это будет работать.

Если вы можете писать в файле innerHTML. Это то, что помогло в моем случае использования.

      #setNotValidStyle(input) {
  input.style.border = "2px solid #d50000"
  input.style.borderRadius = "3px"
  input.innerHTML = ""
  input.innerHTML = `
    <style id="after">
      .${this.className}:after {
        content: "x";
        font-family: sans-serif;
        position: absolute;
        color: #d50000;
        padding-left: 8px;
       }
     </style>
   `
   return input
}
Другие вопросы по тегам