Here are two ways to directly manipulate a pseudo-element:
First way, is by using some sort of style manager.
This "manager" is an object with methods which allows easier manipulation of CSS rules on-the-fly, so here is a very basic example which you can study and implement for your specific needs:
var elm = document.querySelector('main');
// Reference: https://stackoverflow.com/a/28930990/104380
var styleManager = (function() {
// Create the <style> tag
var style = document.createElement("style")
// WebKit hack
style.appendChild(document.createTextNode(""));
// Add the <style> element to the page
document.head.appendChild(style);
function getStyleRuleIndexBySelector(selector, prop){
var result = [], i,
value = (prop ? selector + "{" + prop + "}" : selector).replace(/\s/g, ''), // remove whitespaces
s = prop ? "cssText" : "selectorText";
for( i=0; i < style.sheet.cssRules.length; i++ )
if( style.sheet.cssRules[i][s].replace(/\s/g, '') == value)
result.push(i);
return result;
};
return {
style : style,
getStyleRuleIndexBySelector : getStyleRuleIndexBySelector,
add(prop, value){
return style.sheet.insertRule(`${prop}{${value}}`, style.sheet.cssRules.length);
},
remove(selector, prop){
var indexes = getStyleRuleIndexBySelector(selector, prop), i = indexes.length;
// reversed iteration so indexes won't change after deletion for each iteration
for( ; i-- ; )
style.sheet.deleteRule( indexes[i] );
}
}
})();
elm.addEventListener('mouseenter', function(){
// each new rule should be added the END of the sheet
styleManager.add('main::before','left:90%; top:60%;');
styleManager.add('main::before','left:70%;');
});
elm.addEventListener('mouseleave', function(){
styleManager.remove('main::before', 'left:70%;'); // you can also try without the "left:70%;" part
});
main{
position:relative;
width: 200px;
height: 200px;
border: 1px dashed silver;
}
main::before{
content: 'pseudo';
width: 100px;
height: 100px;
background: lightgreen;
position: absolute;
left: 10px;
top: 40px;
transition:.3s ease-out;
}
<main>Hover & out</main>
Another way - with CSS variables:
var elm = document.querySelector('main');
elm.addEventListener('mouseenter', function(){
elm.style.setProperty('--before-left', '90%');
});
elm.addEventListener('mouseleave', function(){
elm.style.setProperty('--before-left', '10px');
});
main{
--before-left : 10px; /* <-- Your CSS should use variables for this to work */
position:relative;
width: 200px;
height: 200px;
border: 1px dashed silver;
}
main::before{
content: 'pseudo';
width: 100px;
height: 100px;
background: lightgreen;
position: absolute;
left: var(--before-left); /* <-- using the variable */
top: 40px;
transition:.3s ease-out;
}
<main>Hover & out</main>