Change the style of :before and :after pseudo-elements? [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.
This is what my code looks like:
$('.mainSpan:before').css('background','url(_gfx/cmn/main_bg.png)');
This does not seem to work so I'm asking if it's even possible to add
background images to shadow elements with jQuery.

It's not possible to directly access pseudo-elements with Javascript as they're not part of the DOM. You can read their style using the optional second argument - which most, although not all, browsers in current use support - in .getComputedStyle() but you can't directly change their style.
However, you could change their style indirectly by adding in a new style element containing new rules. For example:
http://jsfiddle.net/sjFML/
The initial CSS assigns the :before pseudo-element with a green background, which is turned to black by inserting a new style element.
HTML:
<div id="theDiv"></div>
CSS:
#theDiv {
height: 100px;
background: red;
}
#theDiv:before {
content:' ';
display: block;
width: 50px;
height: 50px;
background: green;
}
Javascript:
var styleElem = document.head.appendChild(document.createElement("style"));
styleElem.innerHTML = "#theDiv:before {background: black;}";

There is also solution with CSS Variables (aka custom properties):
var style = document.querySelector('.foo').style;
style.setProperty('--background', 'url(http://placekitten.com/200/300)');
.foo::before {
background: var(--background);
content: '';
display: block;
width: 200px;
height: 300px;
}
<div class="foo"></div>
For browser support see Can I use and here is link to Ponyfill (same as Polyfill, but you need to call a function)
Ponyfill work with CSS in link and style CSS, but if you use code below, you can set the variable like with setProperty (it will run only in browsers that don't support CSS Variables like IE11)
var style = document.querySelector('.foo').style;
style.setProperty('--background', 'url(http://placekitten.com/200/300)');
cssVars({
variables: {'--background': 'url(http://placekitten.com/200/300)'}
});
.foo::before {
background: var(--background);
content: '';
display: block;
width: 200px;
height: 300px;
}
<div class="foo"></div>
<script src="https://unpkg.com/css-vars-ponyfill#2/dist/css-vars-ponyfill.min.js"></script>
Unfortunately the cssVar ponyfill is global like setting var on :root. If you need to support IE11 or other old browser you can try to search for better polyfill or library.

It is possible to change the value of the ::after element but not directly. Gotta be sneaky. Works on all browsers.
Let's say you have an element:
<div class="thing1">hi here</class>
And you got an ::after css style for it:
.thing1::after {
content:"I am what comes ::after a thing :)";
display: inline-block;
background-color: #4455ff;
padding:3px;
border: 1px solid #000000; }
And you want to change the content and the background color of the ::after pseudo-element using javascript. To do this, make a second CSS rule with the changes you want applied and have both the current class name and add a totally new class name to it. So let's say I want to change the content and the background color a bit and leave the rest of the stuff, the same:
.thing1.extra_stuff::after {
content:"Some parts of me, changed!";
background-color: #8888cc; }
Now, you can just fire off an onclick javascript event that will apply those two new rules to the element, by adding the second class name, to the element :) yay
function change_the_after_attribute(thing_button) {
thing_button.className="thing1 extra_stuff"; }
https://jsfiddle.net/bt8n26a5/
fun side notes:
You can use thing_button.classList.add("extra_stuff"); and thing_button.classList.remove("extra_stuff"); to make the function applicable to many different elements with many different class names, and to be able to remove your changes, as well!
Use a variable instead of the "extra_stuff" string to change what you're adding more dynamically.

Related

Can I make an element inherit the properties of other elements?

We're providing a pre-populated WordPress site for multiple members to use on their servers. The theme has a selector where they can customize their heading colours and fonts. Each member will have different colours based on their branding.
The site also includes a knowledgebase plugin and it uses its own colours which can be customized within its interface. Instead, we'd like to be able to set the knowedgebase colours/properties based on the theme's colour palette. (Ultimately, we'd like the member to only have to change the colors for the theme in one place rather than customize every single plugin.)
So, if H1 is globally set to blue, we'd like to be able to tell the knowledgebase's element (.kb-header) to be the same colour as H1.
Is this at all doable via CSS or Javascript or something?
Many thanks!
You can make an element to inherit the properties of a parent element. For example:
p { color: red; }
a { color: inherit; }
<p>Paragraph with link</p>
But definitely this won't work for what you're asking if your .kb-header is not a child of your h1.
Instead you could use different approaches to get the desired result. For example with custom properties (a.k.a CSS variables)
:root {
--user-color: red;
}
h1 {
color: var(--user-color);
}
.kb-header {
color: var(--user-color);
}
<h1>Title</h1>
<header class="kb-header">This is the header</header>
This way you could, for example, output your :root selector defining all your custom properties in your <head> tag using PHP. And your CSS would be totally independent from it.
If you want to inherit (Object Oriented Programing like) if the html tags doesn't have any relationship, you can use SCSS, for example SASS, it's a text pre processor that generates the CSS with a CSS-like coding with the addition that you can use variables and much more.
For more details visit SASS lang webpage i think this can help you a lot for mostly all your projects.
If you don't want to use SASS, you can even use javascript (with or without libraries) to reach this job, as plain CSS is not capable to conditionally apply styles between non-related tags.
I've written a miniature version of what you're looking for. Hope this helps :P
<html>
<style>
h1 {
background-color: blue;
}
</style>
<body>
<h1>Hey!</h1>
<div class="kb-header">I'm a div :)</div>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var bgColor = $("h1").css("background-color");
$(".kb-header").css({"background-color": bgColor});
});
</script>
<body>
</html>
In CSS you can combine selectors with a comma and have a single block of rules for both:
.a, .b { property: value; }.
And still style one or another selector with other declarations (example below).
When selectors are unrelated, it causes maintenance problems but if it's generated by a theme generator, that should be OK (you don't want to style those given components but have a clear documented list of what has to be styled with a set of colors).
h1,
.kb-header {
color: darkred;
}
h1 {
font-size: 2rem;
}
#media (min-width: 961px) {
.kb-header {
border: 1px solid tomato;
}
<h1>Title</h1>
<p>Unstyled paragraph</p>
<header class="kb-header">This is the header</header>
You can also add a utility class to all elements that are to be styled with a border, a background color and a color:
/* Theme 1
Primary color: #0055D0
Secondary color: #080;
*/
.c-primary {
color: #0055D0;
}
.bd-secondary {
border: 1px solid #080;
}
/* Common styles */
h1 {
font-size: 2rem;
}
.kb-header {
padding: 1rem;
}
<h1 class="c-primary">Title</h1>
<header class="kb-header bd-secondary c-primary">This is the header</header>
Other answers talking about a Sass environment (or other preprocessors like PostCSS and LESS) and CSS "Variables" (if you don't have to support old browsers like IE11 and Edge ~15 + Saf (iOS and OS X) 9.2 https://caniuse.com/#search=custom%20prop are also fine solutions to your problem IMHO.

Access pseudo class element attribute width from scss

I'm trying to change width and height of pseudo-class element through the attribute. I'm doing this because I cannot change pseudo element in javascript. What's wrong in my code? Mozilla says its posible:
https://developer.mozilla.org/en/docs/Web/CSS/attr#Examples
.loader::before {
height: 30px;
width: attr(data-width);
display: block;
position: absolute;
background-color: red;
content: '';}
javascript:
$('.loader').attr('data-width', '100px');});
https://jsfiddle.net/9j2pbbzd/
Be careful, at the moment you can use attr() just into content property. Look at this similar answer https://stackoverflow.com/a/27529435/1849721
What if you create a class with the width/height you want the pseudo element to have and use JS to add/remove this classes as you want to ?

Call CSS Class instead of inserting Attribute using JQuery (.css())

I am building a fixed header with using JQuery
Everything is working fine at the moment but instead of setting attributes to classes and I want to call them from css directly. I am not quite familiar with this method.
One of the example is below;
#header-main {
background-color: #ffffff;
min-height: 107px;
color: #8c8c8c;
}
#header-main .sabit{
position : fixed;
width: 100%;
z-index: 98;
padding-top: 35px;
border-bottom: 3px ridge #7BBD42;
}
How I am doing is; (Working)
var menu = $('#header-main');
if (...)
menu.css('position','fixed').css('width','100%').css('z-index','98').css('padding-top','35px').css('border-bottom','3px ridge #7BBD42');
else
menu.removeAttr('style'); //Back to normal
What I am doing to achieve what I want; (Not working)
var menu = $('#header-main');
if(...)
menu.addClass("sabit");
else
menu.removeClass("sabit"); //Back to normal
I also tried menu.addClass(".sabit"); or menu.addClass("#header-main .sabit"); but none of them worked.
What part am I doing wrong to add directly css class using JQuery?
It's not working because you have a space between #header-main and .sabit in your CSS, meaning that your CSS is trying to style the .sabit descendant of #header-main and not the #header-main element itself.
Change:
#header-main .sabit
To:
#header-main.sabit
Your logic is fine, the problem comes from your CSS.
The line #header-main .sabit{ should instead be #header-main.sabit{, as the sabit class is set on the #header-main element and not on one of its children elements.
Try changing
menu.addClass("sabit");
to
$(menu).addClass("sabit");
addClass comes from the Jquery library so you need to reference it from there.

How to find all css classes and its css attributes inside a certain div?

i would like to find all classes and ids inside a certain div ! and these css attributes!
Example :
<div class="demo">
<div class="new_class">
<p id="para">This is Demo Paragraph</p>
<a style="background:#ccc">HyperLink</a>
</div>
</div>
<style>
.demo{
height:100px; width:100px; background:#FF0;
}
.new_class{height:40px; width:40px; background:#999;}
#para{color:#E1E1E1;}
</style>
Now The question is that: i would like to find all classes and ids which are used inside demo class ! and Their css values too(which style applying now. ).
I would like to find result as below :
<style>
.demo{
height:100px; width:100px; background:#FF0;
}
.new_class{height:40px; width:40px; background:#999;}
#para{color:#E1E1E1;}
a{background:#ccc;}
</style>
OP, not sure what your purpose is, but in general, this can be useful. I had a project where I needed to embed a fancy template from one site onto a page on a different site with a very different, and conflicting stylesheet. I used some code similar to the following to grab every applied style from the original content, via document.styleSheets, then reapplied them all as inline styles, so I could put it onto the "parent" site without the stylesheets conflicting.
Fiddle
JS
var selector,rule;
var result=[];
var sheets = document.styleSheets;
for (var i in sheets) {
//rules or cssRules, depending on the browser
var rules = sheets[i].rules || sheets[i].cssRules;
//iterate over every css rule in the document
for (var r in rules)
{
selector=rules[r].selectorText;
rule=rules[r].cssText;
//select demo itself, as well as all of its children
$('.demo, .demo *').each(function () {
//console.log($(this),selector);
//for each element, see if it matches the current rule. add if it does
if ($(this).is(selector))
{
result.push(rule);
}
});
}
}
console.log(result);
//result[0] .demo { height: 100px; width: 100px; background: none repeat scroll 0% 0% rgb(255, 255, 0); }
//result[1] .new_class { height: 40px; width: 40px; background: none repeat scroll 0% 0% rgb(153, 153, 153); }
//result[2] #para { color: rgb(225, 225, 225); }
Granted, you will have to tweak this on your own to do things like, removing duplicate styles that would occur if you were to apply this to a larger block of HTML, and for dealing with inline styles (which this does not attempt to do, but you can get them from the style attribute and work from there...), and possibly the computed style, which you can get with getComputedStyle, as indicated by the #Derek's answer. but this should get you started.
To find all existing id, try:
var ids = [];
$(".demo *").each(function(){ this.id && ids.push(this.id); });
console.log(ids);
Do the same thing for class or anything else.
However, to get your expected output, you must first acquire the defined CSS style for each element. Which one should be included? p by default gets margins and paddings. Do you include those too? You will also need to dig into all the CSS declarations just to find the style that are applied, which is almost impossible to do.
For example,
<div class="yellow"></div>
<style>
div.yellow:not(.blue){
background: yellow;
}
</style>
How do you get the background of the <div> tag? .style.background? Nah, it returns "". Well now you will have to reach into the CSS declaration with document.styleSheets to see which one applied. How do you even check if the rule div.yellow:not(.blue) matches your element? Good luck doing that. (There might be libraries that does this kind of thing, or maybe you can even utilize jQuery's internal selector engine with .is, though it will not be the same as in CSS) Another thing you can do is try getComputedStyle. It gives you every single computed styles that aren't even in your declaration. So what you are trying to do is not possible to do. (I don't even know what you are doing something like this.)

Change background color via a checkbox when checked with Jquery

I'm trying to change the background color of a div with a checkbox in it. I've made this for reference. I'm trying to replace the parent <div> with the 'highlight' <div>, so I thought the toggle <div> would work. When the checkbox is deselected, I would like the background color to go back to normal (or remove the 'highlight' <div>). Any help is appreciated.
You are setting an inline background-color style for the divs. This takes precedence over any properties you set via a CSS rule.
Add !important to the background-color value of the checked class in your css file, like so: http://jsfiddle.net/KtsGs/1/
There are a few issues present in the jsFiddle.
The first one is that, despite having written jQuery code, you haven't selected jQuery as the framework on the left hand side. That's a small issue specific to the code on jsFiddle, and easily fixed, though.
The second issue is that you have inline styles on the <div> elements, including a background-color. That inline style will be used in preference to any background-color specified using a CSS class (unless it's specified as being !important), so even when your code correctly adds the checked class to the element, the background colour isn't going to change.
The simplest solution is to simply change your CSS declaration:
.checked {
background-color: #ff0000 !important;
}
Here is an updated version of your jsFiddle with the working functionality (using the suggestion above).
However, I'd suggest you instead move the inline styles and JavaScript event handlers to their own CSS declarations, so you don't have to specify !important. That would require the following changes:
#holder > div {
clear: both;
padding: 0.5%;
margin-bottom: 1px;
border-bottom: 1px solid #eee;
float: left;
width: 96%;
style: height: 16px;
cursor: pointer;
background-color: white; // added this to the existing CSS
}
#holder > div:hover { // this is new
background-color: #fafafa;
}
Then move the CSS declaration for .checked below those, so that it takes precedence for the background-color property.
Here is another updated version of your jsFiddle, using the CSS declarations instead.

Categories

Resources