Shortest way to add CSS rules with vanilla JS - javascript

I'm working on a library that I'm trying to keep it below 1KB. Which I'm already very close to my limits. I need to add a css rule to control show hide behaviour.
[hidden]{ display:none !important }
HTML page does not have any style tags. This will be only rule I need. I can only add it with pure JS. I do not want to change the style of an element with el.style.display = 'none'. I want to do it with an attribute.
So how can I add this, I found solutions that create a style element and set it's innerHTML and append it to head element. I'm hoping I can get an answer / a hack to maybe do it with less characters.

This is the shortest I got, please make it shorter if you can.
const addCSS = s => document.head.appendChild(document.createElement("style")).innerHTML = s;
// Usage:
addCSS("[hidden]{ display:none !important }");

If you want to hide an element with an attribute, simply use the attribute hidden.
Example:
<div hidden class="container"></div>
If you do not want to use el.style.display = 'none', you could also use cssText to use your whole style in only 1 string.
Example:
document.querySelector('.container').style.cssText = 'width: 100vw; height: 100vh; background: rebeccapurple;';
<div class="container"></div>
Another option would be using the method CSSStyleSheet.insertRule().
The CSSStyleSheet.insertRule() method inserts a new CSS rule into the
current style sheet, with some restrictions.
Example:
const css = window.document.styleSheets[0];
css.insertRule(`
.container {
width: 100vw;
height: 100vh;
background: rebeccapurple;
}
`, css.cssRules.length);
<div class="container"></div>

Related

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 ?

document.body.style.marginTop returning blank string in JS

It was my understanding that [some elem].style.maginTop would return a string with the element's top margin.
Instead, I'm always getting a blank string. I want to use this with the body, but I also tried on a div, and that didn't work either.
console.log(document.body.style.marginTop); // logs ""
console.log(typeof(document.body.style.marginTop)); // logs "String"
var elem = document.getElementById("testDiv");
console.log(elem.style.marginTop); // logs ""
body {
margin-top:100px;
}
#testDiv {
margin-top:50px;
}
hi!
<div id="testDiv">test</div>
I'm not sure what I'm doing wrong... Does anybody have a non-jQuery solution to this?
The HTMLElement.style only returns inline styles:
The HTMLElement.style property returns a CSSStyleDeclaration object that represents the element's style attribute.
To access the styles from stylesheets use Window.getComputedStyle(element):
The Window.getComputedStyle() method gives the values of all the CSS properties of an element after applying the active stylesheets and resolving any basic computation those values may contain.
var elem = document.getElementById("testDiv");
var style = window.getComputedStyle(elem);
//output
document.body.innerHTML = style.marginTop;
body {
margin-top:100px;
}
#testDiv {
margin-top:50px;
}
hi!
<div id="testDiv">test</div>
You can use getComputedStyle and getPropertyValue to get top margin.
console.log(document.body.style.marginTop); // logs ""
console.log(typeof(document.body.style.marginTop)); // logs "String"
var elem = document.getElementById("testDiv");
//console.log(elem.style.marginTop); // logs ""
console.log(getComputedStyle(elem).getPropertyValue("margin-top"));
alert(getComputedStyle(elem).getPropertyValue("margin-top"));
body {
margin-top:100px;
}
#testDiv {
margin-top:50px;
}
hi!
<div id="testDiv">test</div>
Tested and working.
I don't know why, but I got it working by implicitly assigning the margin-top by JS first. I know why my answer works (it's been over 2 years so I better know why). By setting the values of div#test and body to 50px and
100px like this:
document.getElementById("testDiv").style.marginTop = '50px';
document.body.style.marginTop = '100px';
I'm actually setting the CSS property/value of the elements inline:
<body style='margin-top: 100px'>
<div id='testDiv' style='margin-top: 50px'>test</div>
</body>
Whenever the .style property is used, the CSS property/value that follows it is always inline. One important thing to remember about inline CSS styles is that they have a higher priority than the other 2 means of CSS Declaration: external stylesheets (ex. <link href="file.css"...) and inline stylesheet (ex. <style>...</style>). The only way to override an inline style is to use !important (unless of course the inline style has !important as well.)
So if the.style property is used to read a property/value of an element, it'll only return the inline style value if it actually exists which in OP's case it never did and in my case it did because I used .style to assign the property/values. While my solution is correct, the answers by Nicolo and Mr. Karlsson are better since you'll get the values from all CSS stylesheets.
document.getElementById("testDiv").style.marginTop = '50px';
document.body.style.marginTop = '100px';
console.log(document.getElementById("testDiv").style.marginTop);
console.log(document.body.style.marginTop);
body {
margin-top: 100px;
}
#testDiv {
margin-top: 50px;
}
hi!
<div id="testDiv">test</div>
Hm, I tried it as well with the same result as you did. A quick google search turned up Using JavaScript to read html / body tag margin-top which uses style.getPropertyValue() to return the information you're looking for.
instead of using core javascript, let you use js library jQuery. Then use this syntaxt to get its value.:
console.log($('body').css('margin-top'));
for pure javascript use this
var element = document.body,
style = window.getComputedStyle(element),
margin_top = style.getPropertyValue('margin-top');
console.log(margin_top);
http://jsfiddle.net/hAw53/726/

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 the style of :before and :after pseudo-elements? [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 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.

Is there a way to write a css to any div that contain specific string in its id?

I have jQuery that sets style by div name:
$("[id*='_container']").css({"width":"100%"});
That name of the div can be XXXXX_container (its randomly generated).
Is there a way to write this in a css and not as jQuery code ?
jQuery's selector syntax is based off of CSS.
[id*="_container"] {
width: 100%;
}
Really though you should be adding classes rather than selecting IDs like this:
.container {
width: 100%;
}
Try:
[id$="_container"] {
width: 100%;
}
jsFiddle example
See http://www.w3.org/TR/css3-selectors/#attribute-substrings
In css...
[id$="_container"] {
/* your css */
}
'id$=' means an element whose id ends with.

Categories

Resources