Выбор и управление псевдоэлементами CSS, такими как :: before и :: после использования jQuery - PullRequest
876 голосов
/ 18 февраля 2011

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

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

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

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

Ответы [ 21 ]

665 голосов
/ 20 апреля 2011

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

Можно подумать, что на этот вопрос будет просто ответить, со всем остальным, что может сделать 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
156 голосов
/ 18 февраля 2011

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

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

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

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

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

77 голосов
/ 17 марта 2011

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

Пример

В jQuery:

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

В CSS:

span.change:after { content: 'bar' }
37 голосов
/ 18 октября 2012

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

$('head').append("<style>.span::after{ content:'bar' }</style>");
30 голосов
/ 03 апреля 2018

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

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

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

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

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>

2) Использование CSS и классов

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

.blue {
  --color:blue;
  --content:'I am a blue element';
}
.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("--content", "'I am another element'");
.box:before {
  content:var(--content,"I am a before element");
  color:var(--color, red);
  font-size:25px;
}
<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>

Вы можете заметить, что я рассматриваю синтаксис var(--c,value), где value является значением по умолчанию и также называется запасным значением.

Из той же спецификации мы можем прочитать:

Значение пользовательского свойства может быть заменено на значение другого свойства с помощью функции var ().Синтаксис var ():

var() = var( <custom-property-name> [, <declaration-value> ]? )

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

И позже:

Чтобы заменить var () в значении свойства:

  1. Если пользовательское свойство, указанное в первом аргументе функции var(), испорчено анимацией, а *Функция 1102 * используется в свойстве animation или в одном из его длинных строк, обрабатывает пользовательское свойство как имеющее его начальное значение для остальной части этого алгоритма.
  2. Если значение пользовательского свойства названо первым аргументомчтобы функция var() отличалась от исходного значения, замените функцию var() на значение соответствующего пользовательского свойства.
  3. В противном случае, если функция var() имеет запасное значение в качестве второго аргументазамените функцию var() на запасное значение.Если в резерве есть какие-либо ссылки var(), замените их.
  4. В противном случае свойство, содержащее функцию var(), недопустимо во время вычисления значения.

Если мы не установили пользовательское свойство ИЛИ мы не установим его на initial ИЛИ оно содержит недопустимое значение, то будет использовано запасное значение.Использование initial может быть полезно в том случае, если мы хотим сбросить пользовательское свойство к его значению по умолчанию.

Related

Как сохранить наследуемое значение внутри пользовательского свойства CSS (иначе переменные CSS)?

Пользовательские свойства CSS (переменные) для блочной модели

24 голосов
/ 16 июля 2014

Вот способ доступа: после и: до свойств стиля, определенных в 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');
11 голосов
/ 15 июня 2014

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

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

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

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

5 голосов
/ 19 марта 2014

Вот 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 голосов
/ 12 сентября 2012

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

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