Manipulating CSS Pseudo-Elements ::before and ::after Using JavaScript/jQuery

Introduction

In this article we'll be showing how to select and manipulate CSS pseudo-elements, specifically ::before and ::after, using JavaScript and jQuery. As a web developer, you've likely at least seen these pseudo-elements in a CSS file, but may not have had the chance to interact with them programmatically. This article will show you how and why you might want to do so.

What are CSS pseudo-elements?

CSS pseudo-elements are keywords added to selectors that let you style certain parts of a document. For instance, the ::before and ::after pseudo-elements are used to insert content before or after the content of an element.

p::before {
  content: "Read this - ";
}

p::after {
  content: " - thank you!";
}

In the above code, the ::before pseudo-element adds "Read this - " before the content of every <p> element, and the ::after pseudo-element adds " - thank you!" after the content of every <p> element.

This is what it would actually look like:

The quick brown fox jumps over the lazy dog. Waltz, bad nymph, for quick jigs vex. Sphinx of black quartz, judge my vow. How vexingly quick daft zebras jump! Pack my box with five dozen liquor jugs.

If you were to check the source of this page, you'd see that the "Read this - " and " - thank you!" are not actually in the <p> tag, they're inserted by the CSS.

Note: The ::before and ::after pseudo-elements are often used with the content property, which is used to insert generated content.

Since these pseudo-elements are not actually part of the DOM, they can't be directly selected or manipulated using JavaScript or jQuery. This might seem like a limitation, but there are workarounds, which we'll explore in the following sections.

Why would you need to manipulate pseudo-elements?

CSS pseudo-elements are a powerful tool that can be used to style specific parts of your HTML elements. They can be used to add special effects or extra content before or after the content of an element. However, there are times when you might need to manipulate these pseudo-elements dynamically, based on user interactions or changes in your application state. That's where JavaScript comes in.

Let's say you have a CSS ::before pseudo-element that adds a decorative icon to your buttons. Now, suppose you want to change this icon when the user clicks the button. This change cannot be achieved with CSS alone. You would need to use JavaScript to select the pseudo-element and then change it.

Selecting Pseudo-Elements using JavaScript

As mentioned before, pseudo-elements are not part of the DOM and cannot be directly selected using JavaScript. However, we can still manipulate them by changing their associated CSS rules. To do so, we need to first select the CSS rule that defines the pseudo-element.

Let's say we have a CSS rule for a ::before pseudo-element on a button:

button::before {
  content: "Click me";
  color: blue;
}

We can select this rule using JavaScript's document.styleSheets and cssRules properties. Here's how:

let styleSheet = document.styleSheets[0]; // Select the first stylesheet
let cssRule;

for (let rule of styleSheet.cssRules) {
  if (rule.selectorText === 'button::before') {
    cssRule = rule;
    break;
  }
}

console.log(cssRule.style.content); // Outputs: "Click me"

In the above code, we first select the first stylesheet of the document. Then, we iterate over its cssRules to find the rule with the selector 'button::before'. Once we find the rule, we can access its styles using the style property.

While this method works, it's not very efficient since it requires us to loop through all the cssRules. In a large app with many stylesheets/rules, this likely wouldn't perform well. Therefore, it's recommended to use this method sparingly and only when necessary.

Manipulating Pseudo-Elements using JavaScript

In JavaScript, manipulating pseudo-elements is a bit tricky since they are not directly part of the Document Object Model (DOM). However, we can still modify them with a bit of creativity. We can't directly select pseudo-elements in JavaScript, but we can manipulate their styles via the CSSStyleSheet.insertRule() method.

Let's say we have a paragraph with the id "example" and a ::before pseudo-element:

<p id="example">Hello, StackAbuse readers!</p>
#example::before {
    content: "Greetings! ";
}

Now, suppose we want to change the content of the ::before pseudo-element to "Welcome! " using JavaScript. Here's how we can do it:

document.styleSheets[0].insertRule("#example::before { content: 'Welcome! '; }", 0);

Here, styleSheets[0] refers to the first stylesheet linked/embedded in the HTML document. The insertRule() method takes two parameters: the CSS rule to be inserted, and the index at which to insert the rule. In this case, we're inserting our rule at the beginning of the stylesheet (index 0).

Free eBook: Git Essentials

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

If you need to eventually remove this new rule, you can do so with document.styleSheets[0].removeRule().

Selecting/Manipulating Pseudo-Elements using jQuery

When it comes to jQuery, the situation is similar. We can't directly select pseudo-elements. But we can still get around this by manipulating the CSS rules that apply to them. jQuery doesn't have a built-in method like insertRule(), but we can use the $('style') selector to append a new rule to our stylesheet.

Let's use the same HTML and CSS as before:

<p id="example">Hello, StackAbuse readers!</p>
#example::before {
    content: "Greetings! ";
}

Now, let's change the content of the ::before pseudo-element to "Welcome! " using jQuery:

$('style').append("#example::before { content: 'Welcome! '; }");

With the append() method, we're adding a new rule to the end of our stylesheet. This rule will override the previous rule for #example::before, which results in the content being changed.

Alternatives to Manipulating CSS Psuedo-Elements

Using Attributes

Another solution that has been proposed, and possibly a better one than what we have shown above, is to use the element's attribute to specify before/after content. For example:

#example::before {
    content: attr(data-before);
}
<p id="example" data-before="Greetings! ">Hello, StackAbuse readers!</p>

The attr() method selects whatever text is given in the data-before attribute of the element. Using this, you can change the text in the data-before attribute, which will then alter what the psuedo-elements show.

$('#example').click(function() {
    $(this).attr('data-content', 'Welcome! ');
});

Using Classes

Another reasonable method is to just use CSS classes, which may be something you're already doing throughout your app. You can add/remove classes that have the ::before or ::after selectors, thus helping you manipulate the behavior of the psuedo-elements. It doesn't give as much flexibility as the last option, but it's a familiar and simple solution to a difficult problem.

Conclusion

In this article, we took a look at CSS pseudo-elements and how we can interact with them using JavaScript and jQuery. We've learned that while pseudo-elements are not actually part of the DOM and can't be selected directly, we can still manipulate them by dynamically changing the CSS rules they're associated with.

While pseudo-elements can be useful, you may want to avoid using them if possible, at least when you need to manipulat their values. They’re not a replacement for semantic HTML elements and should not be used to add content that is important to your page.

Last Updated: September 11th, 2023
Was this article helpful?

Improve your dev skills!

Get tutorials, guides, and dev jobs in your inbox.

No spam ever. Unsubscribe at any time. Read our Privacy Policy.

Project

React State Management with Redux and Redux-Toolkit

# javascript# React

Coordinating state and keeping components in sync can be tricky. If components rely on the same data but do not communicate with each other when...

David Landup
Uchechukwu Azubuko
Details

Getting Started with AWS in Node.js

Build the foundation you'll need to provision, deploy, and run Node.js applications in the AWS cloud. Learn Lambda, EC2, S3, SQS, and more!

© 2013-2024 Stack Abuse. All rights reserved.

AboutDisclosurePrivacyTerms