it-swarm.com.ru

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

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

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

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

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

832
JBradwell

Вы также можете передать содержимое в псевдоэлемент с атрибутом данных, а затем использовать 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';
}
642
Nick Kline

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

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


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

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

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

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

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

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

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

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

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

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

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

152
BoltClock

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

ПРИМЕР

В jQuery:

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

В CSS:

span.change:after { content: 'bar' }
75
Gustavo Sousa

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

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

Вот способ доступа к свойствам стиля: 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');
23
Nedudi

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

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

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

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

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>

20
Temani Afif

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

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

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

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

11
user595349

Вот HTML-код:

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

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

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

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

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

5
Coyote

Спасибо всем! Мне удалось сделать то, что я хотел: 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>
4
aimiliano

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

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

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

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.

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

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

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

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

3
Adarsh Hegde

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

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

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

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" :(

2
Alexander Shutov

Здесь много ответов, но ни один из них не помогает манипулировать 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 с помощью 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», которое является динамическим значением.

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

1
Learner

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

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!');
1
Orlandster

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

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

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

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

0
BananaAcid

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

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/

0
Yuri

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

0
Tariq Javed

Кто-то еще прокомментировал добавление к элементу 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>.

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

0
zfb

Я использовал переменные, определенные в :root внутри CSS, чтобы изменить :after (то же самое относится и к :before) псевдоэлемент, в частности, чтобы изменить значение background-color для стилизованной anchor, определенной .sliding-middle-out:hover:after, и значение content для другого anchor (#reference) в следующем demo , который генерирует случайные цвета с помощью 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://stackoverflow.com/a/52360188/2149425" id="reference" class="sliding-middle-out" target="_blank" title="Stack Overflow topic">Reference</a>
</h6>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.rawgit.com/davidmerfield/randomColor/master/randomColor.js"></script>

CSS

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

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

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

JS/jQuery

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

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