Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieving or changing css rules for pseudo elements

EDIT 2015-10-07 1624 CST

This question has been tagged as a possible duplicate - the reason I posted it is that none of the answers to the other question provided all the information I wanted and I want a simple and direct way to do it. I can take care of controlling the order of stylesheets and rules so that I am referencing the correct rule. I also wanted feedback as to the feasibility of this method as regards it breaking in the future.

Look at the comments I posted below for additional reasons why I didn't accept the answers to the possible duplicate questions.

** original question follows **

I searched for a question like this and found some that address part of the question but not both retrieving and changing CSS values for pseudo elements like ::before and ::after.

I have searched the web with Google before coming here and basically what I found is that there is no ideal way to do this.

I found a way that works in FF 40, IE 9, and Chrome 45.0.2454.101 m but I'm wondering if I'm overlooking something that may cause my method to break in some instances.

The answers I've seen, here and other places on the web, about accessing or changing CSS values for pseudo elements, say that you can't directly access these items because they are not "part of the DOM" and "outside the DOM"

They say about the only way to change them is to create a new rule and appending it to the existing rules to override the coded value.

Here is a snippet that demonstrates the method:

function changeColor () { // Flip psedo element's background color
	var newColor,
		currentColor;
	
    // Get the current color
	currentColor= document.styleSheets[0].cssRules[0].style.backgroundColor;  
	
    // flip the color
	newColor = (currentColor== "red") ? "aqua" : "red";  					  
	
     // Change the color
    document.styleSheets[0].cssRules[0].style.backgroundColor = newColor;  	  
    
    // put color in top message
    document.getElementById("colorIs").innerHTML = newColor;
  
    // display colors  
	document.getElementById("displayColors").innerHTML = 
			"Pevious color was " + currentColor + 
            ", changed to " + newColor + ".";  
            
    // Change background of button (not needed but thought I'd throw it in)
    document.getElementById("changeButton").style.backgroundColor = newColor;                      
}
#testDiv::before {
      background-color: aqua;
	  content: "psedo element ";
  }

#changeButton {
	background-color: aqua;
}
<div id="testDiv">
  This divsion has an pseudo ::before element whose background color is
  <span id="colorIs">
		aqua
	</span>
  <br>
  <br> Click "Display and Flip Color" to display the colors
  <br> and flip the color from aqua and red and vice versa.
</div>
<br>
<form method="post">
  <input id="changeButton" name="change" type="button" value="Display and Flip Color" onclick="changeColor();">
</form>
<br>
<div id="displayColors">
</div>

I realize that this depends upon my knowing the order of style sheets and rules within them, but I can control that.

These seems to go against the answers I've seen which say the CSS items for pseudo elements are not part of, and therefore not accessible, through the DOM.

Is this method possible because of browser or DOM changes that occurred after the answers I read were posted?

What is the likelihood that this method might break in the future?

And would those with different version of the various browsers please try the snippet and let me know if it works or not?

Bob


EDIT 2015-10-08 1352 CST

I have modified my method of accessing styles of pseudo elements to be able to directly reference the style sheet in question, regardless of the order in which it is defined.

I would change the snippet but I don't see a way to give the css "stylesheet" an id.

Instead I'll tell how I would modify it.

1) Separate the CSS that defines the elements being used and put it in a separate file.

2) Code id= on the <link tag referencing the CSS file. In this case I would use id="colorFlipFlop"

3) Change the JavaScript to reference or change a style from this:

currentColor = document.styleSheets[0].cssRules[0].style.backgroundColor;

document.styleSheets[0].cssRules[0].style.backgroundColor = newColor;

To:

var beforeIndex = 0; // give a name to the index, in cssRules, of the rule we want to get and change.

var styleSheetObject = document.getElementById("colorFlipFlop"); // get a reference to the stylesheet object

currentColor = styleSheetObject.sheet.cssRules[beforeIndex].style.backgroundColor;   // get current pseudo element background color

styleSheetObject.sheet.cssRules[beforeIndex].style.backgroundColor = newColor; // set new background color

I would fully document all of this, in the CSS and Javascript, and in the HTML if I deemed it necessary, with as many comments as I thought was necessary to explain what I am doing, how I am doing it, and why I am doing it the way I am doing it - I call that the WHW of commenting.

I feel this makes the functionality more manageable and more bullet proof.

You no longer have to now the index of the stylesheet object, everything is neatly separated from everything else on the page, and it still provides a direct way to access and change styles of pseudo elements without creating and appending new rules.

Before I post this edit I will make up a file containing the CSS, JavaScript, and HTML to achieve what the snippet does to show the new method. I will put everything in one file just to make it easier to create and FTP to the site. In real world code, I'd use separate CSS, JavaScript, and HTML files.

It will be at http://thetesting.site/flipFlopColor.html

So - What do you think?

like image 694
SimonT Avatar asked Oct 06 '15 23:10

SimonT


1 Answers

Manipulating the CSSRule instead of the DOM element is an obscure but perfectly valid (and standardized) way of changing an element's style. It's obscure because it is difficult, requiring a nested loop going through all the rules in all the stylesheets to find the rule you want to change. And it's obscure also because it's not super valuable - you can usually accomplish the same thing by just accessing the DOM element's style property.

But, with pseudo-elements, there is no DOM element. The pseudo-element is a product of the style rule, so the only way to manipulate the pseudo-element is through the style rule. People recommend adding style rules because that is easier than finding the style rule and editing it. But finding and editing it is perfectly valid.

You can have the best of both worlds by adding a style rule once, and then keeping a reference to the rule and making subsequent edits to that same rule.

like image 131
gilly3 Avatar answered Sep 29 '22 12:09

gilly3