Get the :before value of an element with JQuery [duplicate] - javascript

This question already has answers here:
Selecting and manipulating CSS pseudo-elements such as ::before and ::after using javascript (or jQuery)
(26 answers)
Closed 3 years ago.
For context, this is a followup to an earlier question. Rather than digging through cssRules, I'd like to base the logic on jQuery selectors that search for the effects of those rules.
Given default properties of
.commentarea .author:before {
background-image: url(http://...);
background-position: -9999px -9999px;
/* ... */
}
that are selectively modified as in
.author[href$="gbacon"]:before /* ... */ {
content: "";
background-position: 0 -140px
}
how can I select pseudo-elements whose respective background positions have default values? Copying the selector as in
GM_log("size = " + $(".commentarea .author:before").size());
matches nothing. Trying .siblings() with
$(".commentarea .author")
.map(function(i) {
GM_log($(this)
.siblings()
.map(function (i) { return $(this).css("background-image") })
.get()
.join(", "))
});
produces only none values.
For full details, see the live page. Is this possible?

You can't use the :before and :after pseudo-elements like this. The purpose of them is to insert content before and after (respectively) the selector you have specified.
Example usage:
HTML:
<span class='a'>
Outer
<span class='b'>
Inner
</span>
</span>
CSS:
.a .b:before {
content: "|Inserted using :before|";
}
.a {
color: blue;
}
.b {
color: red;
}
Result:
http://jsfiddle.net/mzcp6/
What happened was that the text |Inserted using :before| was inserted before (well, really, prepended into) the inner span because it was class b and a descendant of an element of class a. Basically, :before and :after don't select; they modify.
Example:
This doesn't work as expected:
HTML:
<span class='a'>
<p>More text</p>
<span class='b'>
<p>More text</p>
Inner
</span>
</span>
CSS:
.a .b:before {
text-size: 100px;
}
Nothing happens:
http://jsfiddle.net/bQ2ty/
EDIT:
:before is not a valid jQuery selector: http://api.jquery.com/category/selectors/
I think you will need to use something other than :before or attempt to extract the original rule using the jQuery plugin: http://flesler.blogspot.com/2007/11/jqueryrule.html

Related

What is the difference between a space and a comma in a jQuery selector? [duplicate]

Here is an example that I do not understand:
.container_12 .grid_6,
.container_16 .grid_8 {
width: 460px;
}
It seems to me that width: 460px is applied to all above mentioned classes. But why some classes are separated by a comma (,), and some just by a space?
I assume that width: 460px will be applied only to those elements which combine classes in the way mentioned in the CSS file. For example, it will be applied to <div class='container_12 grid_6'> but it will not be applied to the <div class='container_12'>. Is this assumption correct?
.container_12 .grid_6,
.container_16 .grid_8 {
width: 460px;
}
That says "make all .grid_6's within .container_12's and all .grid_8's within .container_16's 460 pixels wide." So both of the following will render the same:
<div class="container_12">
<div class="grid_6">460px Wide</div>
</div>
<div class="container_16">
<div class="grid_8">460px Wide</div>
</div>
As for the commas, it's applying one rule to multiple classes, like this.
.blueCheese, .blueBike {
color:blue;
}
It's functionally equivalent to:
.blueCheese { color:blue }
.blueBike { color:blue }
But cuts down on verbosity.
.container_12 .grid_6 { ... }
This rule matches a DOM node with class container_12 that has a descendant (not necessarily a child) with class grid_6, and applies the CSS rules to the DOM element with class grid_6.
.container_12 > .grid_6 { ... }
Putting > between them says that the grid_6 node must be a direct child of the node with class container_12.
.container_12, .grid_6 { ... }
A comma, as others have stated, is a way to apply rules to many different nodes at one time. In this case, the rules apply to any node with either a class of container_12 or grid_6.
Not exactly what was asked, but maybe this will help.
To apply a style to an element only if it has both classes your selector should use no space between the class names.
For Example:
.class1.class2 { color: #f00; }
.class1 .class2 { color: #0f0; }
.class1, .class2 { font-weight: bold; }
<div class='class1 class2'>Bold Red Text</div>
<div class='class1'>Bold Text (not red)</div>
<div class='class1'><div class='class2'>Bold Green Text</div></div>
Comma groups the classes (applies the same style to them all), an empty space tells that the following selector must be within the first selector.
Therefore
.container_12 .grid_6,
.container_16 .grid_8 {
width: 460px;
}
applies that style to only class .grid_6 which is within .container_12 class and to .grid_8 class which is within .container_16.
The width: 460px; will be applied to the element with the .grid_8 class, contained inside the elements with .container_16 class, and elements with the .grid_6 class, contained inside the elements with .container_12.
The space means heritage, and the comma means 'and'. If you put properties with a selector like
.class-a, .class-b, you will have the properties applied to the elements with anyone of the two classes.
Hope I have helped.
You have four classes and two selectors in your example:
.container_12 .grid_6,
.container_16 .grid_8 {
width: 460px;
}
So .container_12 and .grid_6 are both classes, but the rule width: 460px will only be applied to elements that have the .grid_6 class which are descendants of an element that have the .container_16 class.
For example:
<div class="container_16">
<p class=".grid_6">This has a width of 480px.</p>
<p>This has an unknown width.&lt/p>
</div>
The above means that you are applying styles to two classes, indicated by the comma.
When you see two elements side by side not separated you can assume that it is referring to an area within an area. So in the above, this style only applies to grid_6 classes inside of container_12 classes and grid_8 classes inside of container_16 classes.
in the example:
<div class="grid_6">This is not effected</div>
<div class="container_12">
<div class="grid_6">
This is effected.
</div>
</div>
The first grid_6 will not be effected while the second grid_6 class will because it is contained inside a container_12.
A statement like
#admin .description p { font-weight:bold; }
Would only apply the bold to tags within areas that have class "description" that are inside of an area with id "admin", such as:
<div id="admin">
<div class="description">
<p>This is bold</p>
</div>
</div>
Selectors combinations get different meanings - attached image explains easily
a) Multiple selectors separated by a comma(,) - Same styles are applied to all selected elements.
div,.elmnt-color {
border: 1px solid red;
}
Here border style is applied to DIV elements and CSS class .elmnt-color applied elements.
<!-- comma example -->
<div>
Red border applied
</div>
<p class="elmnt-color">
Red border applied
</p>
b) Multiple selectors separated by space – Those are called descendant selectors.
div .elmnt-color {
background-color: red;
}
Here border style is applied to CSS class .elmnt-color applied elements which are child elements of a DIV element.
<!-- space example -->
<div>
Red border NOT applied
</div>
<p class="elmnt-color">
Red border NOT applied
</p>
<div>
Red border NOT applied
<p class="elmnt-color">
Red border applied
</p>
</div>
c) Multiple selectors specified without space - Here styles are applied to elements which meet all the combinations.
div.elmnt-color {
border: 1px solid red;
}
Here border style is applied only to DIV elements with a CSS class of .elmnt-color.
<!-- no space example -->
<div>
Red border NOT applied
</div>
<p class="elmnt-color">
Red border NOT applied
</p>
<div>
Red border NOT applied
<p class="elmnt-color">
Red border NOT applied
</p>
</div>
<div class="elmnt-color">
Red border applied
</div>
Details are attached at https://www.csssolid.com/css-tips.html
Note: CSS Class is just one of the CSS Selectors. These rules applies to all CSS Selectors (ex: Class, Element, ID etc.,).
.container_12 .grid_6,
.container_16 .grid_8 {
width: 460px;
}
width:460px will be only applied to .grid_6 and .grid_8
Edit: Here is a very good article for you
http://css-tricks.com/multiple-class-id-selectors/

How do I connect html transforms in multiple classes? [duplicate]

This question already has answers here:
How can I apply multiple transform declarations to one element?
(5 answers)
How to have multiple CSS transitions on an element?
(9 answers)
Closed 2 years ago.
I'm trying to use multiple transforms in a single element so that the end product is a combination of all of the transformations applied together.
However, the only one transform property will be ignored when there are multiple of them.
Say, if I want a div transformed by rotate(20deg) and skewY(20deg), this wouldn't work:
.foo {
transform: rotate(20deg);
}
.bar {
transform: skewY(20deg);
}
<div class="foo bar"></div>
Only one will be applied. Although compounding the transformations could work, it would be impractical as there can be potentially many combinations to the transformations. Rather than doing this:
.one-one {transform: rotate(10deg) skewY(1deg);}
.one-two {transform: rotate(10deg) skewY(2deg);}
.one-three {transform: rotate(10deg) skewY(3deg);}
.one-four {transform: rotate(10deg) skewY(4deg);}
.two-one etc.
I want to do this, so that i can apply the transformations on button clicks, rather than to exhaust all possible combinations of the transformations:
.one {transform: rotate(10deg);}
.two {transform: rotate(20deg);}
.three {transform: rotate(30deg);}
.four {transform: rotate(40deg);}
.uno {transform: skewY(10deg);}
.dos {transform: skewY(20deg);}
.tres {transform: skewY(30deg);}
Current solutions I think are possible:
There is a way to add to the transform property of a <div>
Somehow modify classes in some way
Changing the CSS using jQuery, but it seems like this will also overwrite the property with css() rather than adding to the transform style
I'd prefer css/js solutions, but jQuery answers are welcome too, I'm just not familiar with it.
You may look at CSS var(--X) (see links below snippet's demo) and , set all transformation you intend to 0 by default and update them via the className :(mind support before use : https://caniuse.com/#feat=mdn-css_properties_custom-property_var and eventually a polyfill https://github.com/nuxodin/ie11CustomProperties )
possible exemple without JavaScript https://codepen.io/gc-nomade/pen/RwWLOWr :
.foo {
--rotate: 20deg;
}
.bar {
--skewY: 20deg;
}
div[class] {
transform: rotate( var(--rotate, 0)) skewY( var(--skewY, 0));/* fallback value is here 0 */
}
/* demo purpose */
div[class] {
float: left;
border: solid;
}
html {
display: flex;
height: 100%;
}
body {
margin: auto;
}
<div class="foo bar">foo bar</div>
<div class="foo ">foo</div>
<div class="bar">bar</div>
<div class="nop">no transform</div>
https://developer.mozilla.org/en-US/docs/Web/CSS/--*
Property names that are prefixed with --, like --example-name, represent custom properties that contain a value that can be used in other declarations using the var() function.
Custom properties are scoped to the element(s) they are declared on, and participate in the cascade: the value of such a custom property is that from the declaration decided by the cascading algorithm.
Fallback : https://drafts.csswg.org/css-variables/#example-abd63bac
Note: The syntax of the fallback, like that of custom properties, allows commas. For example, var(--foo, red, blue) defines a fallback of red, blue; that is, anything between the first comma and the end of the function is considered a fallback value.
if supports comes a question, you may look at : IE11 - does a polyfill / script exist for CSS variables?
There's many ways you can approach that. How about this below?
I have created two ` to read the values for skew and rotation and them apply the effects.
Remember it doesn't matter where the values come from. They can be hard-coded in your buttons as data-* attributes(if you want them fixed). This is just to show you how you can approach it with javascript( Ihave added some commends to make it simpler to understand):
var object = document.querySelector(".shape");
// this function takes care of Rotational effect
function rotate(event)
{
var rotation_val = document.getElementById("rotationVal").value;
// this get's the css transform expression for rotation which is
// stored as data-attribute on every button, because it tells you what button is resposible for what transformation. But you can store this anywhere you want.
var css_transform = event.currentTarget.getAttribute("data-rotation");
// this here just replaces say rotate(_r_) to rotate(15deg) if val was 15
var effect = css_transform.replace("_r_",rotation_val + "deg");
// Take not of this. ere I am not overriding the transform property. Instead
// I am adding a transformation to it. more like compounding but dynamically.
object.style.transform += effect;
}
// this function takes care of Skewing effect
function skewY(event)
{
var skew_val = document.getElementById("skewVal").value;
var css_transform = event.currentTarget.getAttribute("data-skew");
var effect = css_transform.replace("_s_",skew_val + "deg");
object.style.transform += effect;
}
function apply_all(){
var buttons = document.querySelectorAll(".effect_button");
buttons.forEach( function(button){
button.click();
});
}
.container{
padding: 60px;
border: thin solid #dbdbdb;
}
.shape{
width: 60px;
height: 60px;
background-color: green;
}
<div class="container">
<div class="shape">
</div>
</div>
<input id="rotationVal" />
<button class="effect_button" data-rotation="rotate(_r_)" onClick="rotate(event)">rotate</button>
<br />
<input id="skewVal" />
<button class="effect_button" data-skew="skewY(_s_)" onClick="skewY(event)">Skew</button>
<br />
Or Rotate and Skew at the same time:
<button onClick="apply_all(event)">Transform</button>

How do you remove CSS style inside a style element?

Example:
<style>
.className {
left: 0;
color: blue;
}
</style>
I want to remove the left: 0; aspect using javascript/jquery or whatever method I have to use to do this. I don't have the option of opening the document to edit or delete. Any Ideas? Note that this class has other styles within it and I just want to remove the left:0; aspect ONLY leaving the rest intact.
An element's style attribute can override its CSS class properties. left: auto will also reset the left property of an element to the default value.
An element's style can be set like this in Javascript:
Element.style.[CSS property] = [value]
<span id="someId">Span</span>
<script>
document.getElementById("someId").style.color = "#aeb";
</script>
Its jQuery equivalent is (for one CSS property):
$([selector]).css([CSS property], [value]);
$('#someId').css("color", "#aeb");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span id="someId">Span</span>
For many CSS properties:
$([selector]).css({[CSS property]: [value], [CSS property]: [value]});
$('#someId').css({"color":"red", "font-size":"1.5em", "position":"absolute", "top": "25%", "left": "25%"});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span id="someId">Span</span>
<style>
.className {
left: 0;
position: absolute;
}
</style>
<span class="className">Span.className</span><br/>
<span class="className">Span.className</span><br/>
<span class="className">Span.className</span><br/>
<span class="className">Span.className</span><br/>
<span class="className">Span.className</span><br/>
<span style="left: 0; position: absolute;">Span with left:0 and position:absolute</span>
<script>
var elems = document.getElementsByClassName("className");
for(let i = 0; i < elems.length; i++){
elems[i].style.left = "50px";
}
</script>
To overwrite all previous set CSS properties of an element, you can use all: initial, setting all CSS properties to its initial value.
<style>
.someClass{
position: fixed;
color: red;
background-color: dodgerblue;
font-size: 3em;
margin: 20px;
}
</style>
<span class="someClass">Span.someClass</span>
<span class="someClass" style="all: initial;">Span.someClass all:initial</span>
left:auto;
Auto will reset the left attribute to the browser's default for the page :)
possible / similar duplicate:
How to remove Left property when position: absolute?
Using jquery you should be able to simply do this:
$('.className').css({'left': 'auto'});
Or, if the class isn't really all that important anyways, you could just remove it like this:
$('.className').removeClass('className');
You could override it with another value either in CSS, or using the same jQuery thing mentioned in the first part of my answer.
Here are two different approaches.
1. Replace/Remove the class
If that is the only style attribute in that class, you could remove the class from all elements that use it.
Example with jQuery:
$(".className").removeClass("className").addClass("anotherClass");
2. Override the attribute
The default value for left in CSS is auto, so you could override the CSS for all of those elements.
Example with jQuery:
$(".className").css("left", "auto");
Try like this:
$('.className').remove();
Since it has a value, making the value blank will make it so it doesn't count as any value and the css attribute will be skipped/ignored.
Solution:
$('.className').css('left',' ');
If the attribute still gets read as 0 then you will have to apply the !important to the .css(); to override it.

getComputedStyle() Unexpected Behaviour [duplicate]

This question already has answers here:
text-decoration: apparent discrepancy between appearance and computed values
(3 answers)
Closed 7 years ago.
In the following code example, I'd expect to see underline in the console log. Instead, I see none.
How do I extract the underline value from the text-decoration property in #one .yo?
setTimeout(function() {
var $el = document.querySelectorAll('#one .yo')[0];
var css = getComputedStyle($el).cssText;
console.log("text-decoration is set to:");
console.log(/text\-decoration\: ([^\;]+)/g.exec(css)?.[1] + '!');
console.dir($el);
console.log(window.getComputedStyle($el));
var $el2 = document.querySelectorAll('#two .yo')[0];
$el2.style.cssText = css;
}, 750);
* {
margin: 0;
padding: 0;
}
#one {
color: blue;
text-decoration: underline;
}
<div id="one">
<div class="yo">what's up</div>
</div>
<div id="two">
<div class="yo">what's up</div>
</div>
Although it affects its childs, the text-decoration style property [of the parent] is not inherited (bold is mine):
The text decorations are not technically inherited, but the effect is similar to inheritance. If they’re set on an inline element, they apply to all boxes generated by that element. (...)
It seems strange because other similar properties, like font-size, do inherit, but that's just the way it is (see "Inherited: no" at the table here and/or here).

How change content value of pseudo :before element by Javascript [duplicate]

This question already has answers here:
Selecting and manipulating CSS pseudo-elements such as ::before and ::after using javascript (or jQuery)
(26 answers)
Closed 2 years ago.
I have the grap constructured by CSS, which is dynamically changes by JS. I show graph max value by pseudo element as:
.graph:before {
content:""; //value that want set by JS
position:absolute;
top:0;
left:0;
}
That's why I need to set this value by JS. I tried $(".graph:before").css("content", hh); but it didn't help. How to get that value?
I hope the below snippet might help, you can specify the content value you want via JS using the CSS attr() function.
Below you have two options: to use JavaScript or jQuery:
jQuery:
$('.graph').on('click', function () {
//do something with the callback
$(this).attr('data-before','anything'); //anything is the 'content' value
});
JavaScript:
var graphElem = document.querySelector('.graph');
graphElem.addEventListener('click', function (event) {
event.target.setAttribute('data-before', 'anything');
});
CSS:
.graph:before {
content: attr(data-before); /* value that that refers to CSS 'content' */
position:absolute;
top: 0;
left: 0;
}
Update (2018): as has been noted in the comments, you now can do this.
You can't modify pseudo elements through JavaScript since they are not part of the DOM. Your best bet is to define another class in your CSS with the styles you require and then add that to the element. Since that doesn't seem to be possible from your question, perhaps you need to look at using a real DOM element instead of a pseudo one.
You can use CSS variable
:root {
--h: 100px;
}
.elem:after {
top: var(--h);
}
let y = 10;
document.documentElement.style.setProperty('--h', y + 'px')
https://codepen.io/Gorbulin/pen/odVQVL
I believe there is a simple solution using the attr() function to specify the content of the pseudo element. Here is a working example using the 'title' attribute, but it should work also with custom attributes.:
document.getElementById('btn_change1').addEventListener("click", function(){
document.getElementById('test_div').title='Status 1';
});
document.getElementById('btn_change2').addEventListener("click", function(){
document.getElementById('test_div').title='Status 2';
});
#test_div {
margin: 4em;
padding:2em;
background: blue;
color: yellow;
}
#test_div:after {
content:attr(title);
background: red;
padding:1em;
}
<button id='btn_change1'>Change div:after to [Status 1]</button>
<button id='btn_change2'>Change div:after to [Status 2]</button>
<div id='test_div' title='Initial Status'>The element to modify</div>
People who are still looking some solution of same problem, it is doable as follows using jQuery:
<button id="changeBefore">Change</button>
<script>
var newValue = '22';//coming from somewhere
var add = '<style>.graph:before{content:"'+newValue+'"!important;}</style>';
$('#changeBefore').click(function(){
$('body').append(add);
});
</script>
This example illustrate that on clicking button: changeBefore , the value for .graph:before will change as per new dynamic coming value for it.
For more description about changing of :before or :after element style or getting its content:
Lets suppose your HTML is like this:
<div id="something">Test</div>
And then you are setting its :before in CSS and designing it like:
#something:before{
content:"1st";
font-size:20px;
color:red;
}
#something{
content:'1st';
}
Please notice I also set content attribute in element itself so that you can take it out easily later.
Now there is a button clicking on which, you want to change the color of :before to green and its font-size to 30px. You can achieve that as follows:
Define a css with your required style on some class .activeS :
.activeS:before{
color:green !important;
font-size:30px !important;
}
Now you can change :before style by adding the class to your :before element as follows:
<button id="changeBefore">Change</button>
<script>
$('#changeBefore').click(function(){
$('#something').addClass('activeS');
});
</script>
If you just want to get content of :before, it can be done as:
<button id="getContent">Get Content</button>
<script>
$('#getContent').click(function(){
console.log($('#something').css('content'));//will print '1st'
});
</script>
I hope it helps
I had a similar problem, but with icons. I needed to switch the play and pause icons for an audio player in html5.
The problem here was that HTML, CSS and jQuery all interpret differently the "content" values to show icons, due to the use of \ symbol.
So the best workaround is to delete and re-create the node. Here's my code:
<ul class="list list--buttons">
<li><i class="fa fa-step-backward"></i></li>
<li><i class="fa fa-play"></i></li>
<li><i class="fa fa-step-forward"></i></li>
</ul>
And the script
<script type="text/javascript">
$(
function(){
var aud = $('audio')[0];
$('.playpause').on('click', function(e){
e.preventDefault();
if (aud.paused) {
aud.play();
/* from play icon to pause icon */
$('.playpause .fa-play').remove();
$('.playpause').append('<i class="fa fa-pause"></i>');
}
else {
aud.pause();
/* from play icon to pause icon */
$('.playpause .fa-pause').remove();
$('.playpause').append('<i class="fa fa-play"></i>');
}
})
$('.next').on('click', function(e){
e.preventDefault();
aud.src = '{$content:audio-file}';
})
$('.previuos').on('click', function(e){
e.preventDefault();
aud.src = '{$content:audio-file}';
})
aud.ontimeupdate = function(){
$('.progress').css('width', aud.currentTime / aud.duration * 100 + '%')
}
})
</script>
Hope it helps!
You can use document.styleSheets to modify pseudo selector cssRules
document.styleSheets[0].cssRules[0].style.content = '"111"';
If you use something like an onoffswitch and want to translate the css content attribute with i18next then you can use one of the i18next Framework example from github (i18next Jquery Framework) and then you extended the function with this code:
var before = i18next.t('onoffswitch.before');
var after = i18next.t('onoffswitch.after');
$('.onoffswitch-inner')
.attr('data-before', before )
.attr('data-after', after );
and the css code must be this:
.onoffswitch-inner:before {
content: attr(data-before);
padding-left: 10px;
background-color: #65AFF5; color: #FFFFFF;
}
.onoffswitch-inner:after {
content: attr(data-after);
padding-right: 10px;
background-color: #EEEEEE; color: #999999;
text-align: right;
}

Categories

Resources