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

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

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

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

Как я могу изменить "foo" на "bar" с помощью jQuery?

Ответ 1

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

Ответ 2

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

Есть способы манипулировать этими элементами с помощью обходных решений 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>

Ответ 3

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

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

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

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

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

Ответ 4

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

ПРИМЕР

В jQuery:

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

В CSS:

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

Ответ 5

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

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

Ответ 6

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

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

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

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

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

Ответ 7

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

Ответ 8

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

Ответ должен быть "Да" и "Нет". Вы не можете выбрать элемент с помощью псевдоселектора, но вы можете добавить новое правило в таблицу стилей с помощью 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/

Ответ 9

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

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

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

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

Ответ 10

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

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

Ответ 11

Вот HTML:

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

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

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

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

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

Ответ 12

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

Ответ 13

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

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, который содержит ваш необходимый атрибут, который будет влиять на целевой элемент после элемента Pseudo.

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

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

и

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

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

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

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

привет - Адарш Хедде.

Ответ 14

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

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

Ответ 15

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

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

Ответ 16

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

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

Ответ 17

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

Вот как я предлагаю это сделать. Предположим, что ваш HTML выглядит следующим образом:

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

И затем вы устанавливаете его: раньше в CSS и проектируете его так:

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

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

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

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

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

<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", что является динамическим значением.

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

Ответ 18

Я создал плагин jQuery для добавления псевдо-правил css, таких как использование .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!"'
  });

Ответ 19

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

Ответ 20

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

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>

Ответ 21

Кто-то еще прокомментировал добавление элемента head с полным элементом стиля, и это неплохо, если вы делаете это только один раз, но если вам нужно reset, это не один раз, вы получите тонну стиль элементов. Поэтому, чтобы я не создал пустой элемент стиля в голове с идентификатором и заменил его 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> правильно.

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

Ответ 22

Я использовал переменные, определенные в :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="#" onclick="location.href='https://stackoverflow.com/a/52360188/2149425'; return false;" 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("");
 }
);