I have about 100 elements in like and am trying to create an animation with jquery.
<div class="box" id="a1"></div>
I need to add special styles to each of the elements based on a function.
which of them is rendered faster in browser:
adding css property
$(this).css({'background-color':'#000'})
or adding class
$(this).addClass("style1")
Updated
Few more things i wish to add:
Right now it has 100 elements and am adding them by jquery.
To create randomness i need to create about 25 styles - am doing it by javascript
should i also add size of stylesheet to the same to get exact benchmarks.
which of them is rendered faster in browser:
Depends on the browser. you should do some tests if it's interesting you.
Anyway it's not important and very unlikely to be the bottle-neck of your website.
Avoid micro-optimization, "premature optimization is the root of all evil", you're wasting your time.
According to jsPerf, addClass is noticeably faster by about 50%.
Here's the jsPerf data for Chrome but in my tests it was about the same using Firefox:
$('#a1').css({ 'background-color': '#000' }) 82,043 ±0.21% 48%
slower
$('#a1').addClass("style1") 158,876 ±0.83% fastest
Adding a class to the parent of all these 100 elements will be faster and defining that class in the css file or page.
.style1 .box{
//define style here
}
This way you just have to manipulate the class of only one element and it is definitely faster than modifying each of the 100 element's style using css method.
How fast? It all depends on the number of lines of code executed in each of the operations which is again dependent on browser to browser.
If you go with my approach it will definitely be faster.
You can even consider using a style tag.
It could turn to be very fast.
For example if you have a lot of elements to modify, let's say 100 elements, as you write your css only once, the DOM will be changed only once.
HTML:
<style type="text/css" id="specialStyle"></style>
<div class="oneHundredElements" id="box1"/>
<div class="oneHundredElements" id="box2"/>
...
<div class="oneHundredElements" id="box100"/>
SCRIPT:
<script>
var css = '.oneHundredElements {background-color:#000;}';
$('#specialStyle').html(css);
</script>
http://jsperf.com/foox/4
Related
Talking strictly about CSS 3, html 5, and styles defined on stylesheets or in a top level tag:
This is what I have observed:
Using JavaScript:
If I move an element under another element, or out from under its parent, it and all elements under it will be reviewed for restyling.
If I add or remove a class, an element and all elements under it will be reviewed for restyling.
If I add or remove an attribute, an element and all elements under it will be reviewed for restyling.
I assume this is also true of the sibling (~) relationship as well? I mean moving elements relative to their siblings?
Is there anything else that would trigger this? And is there a document someplace (like mozilla) that specifies this as a standard?
That really depends on what you call "restyling".
Here it seems you are only talking about recalculating all the styles applied by all the stylesheets in the document, which is also known as "reflow" or "layout".
Any change to the DOM will mark the CSSOM as dirty, and before the time of rendering, the browser will perform such a reflow if the CSSOM is dirty.
Note that some operations, (most being referenced in this gist by Paul Irish), will force a synchronous reflow, because they do require that an up-to-date boxing model is calculated to return the correct values, or to act correctly. So one must be careful when doing DOM changes in a loop to not also force such a synchronous reflow and let the browser do it at the best time, (generally just before the next paint, but in some browsers it's also done at idle).
However this reflow may not cost much, browser may very well have enough optimizations to know what could have changed and go only through these. Moreover, these don't include the repaint operation, which will only happen at the next screen refresh.
But this is not the only time the browser needs to recalculate the boxes layout, for instance every time the page is resized, or even if an in-flow element's size changes as part of an animation etc. but here, the full stylesheets are not recomputed.
There is not really a place in the specs where it is defined what should trigger these operations, nor even when they should occur. The HTML specification only asks that the browser performs the "rendering steps" of the event-loop, which does end with a quite underspecified "update the rendering or user interface of that Document". The ResizeObserver API does extend the rendering step to include styles recalc and layout update but they don't go as far as defining these steps. Note that there is an open issue on the HTML specs to define it more clearly, but for the time being we don't even have browser interoperability.
CSS3 is a series of separate specifications covering individual topics but includes CSS2 within the official definition of CSS.
CSS2 definitions define rendered content as (the emphasis mine)
The content of an element after the rendering that applies to it according to the relevant style sheets has been applied. How a replaced element's content is rendered is not defined by this specification. Rendered content may also be alternate text for an element (e.g., the value of the XHTML "alt" attribute), and may include items inserted implicitly or explicitly by the style sheet, such as bullets, numbering, etc.
I take this to mean that when a document or part thereof is rendered, the browser is responsible for ensuring that CSS rules are correctly applied according to the content rendered, with DOM content and CSS rules specifiying the logical requirements of the rendering and the browser ensuring it produces page layout in conformance with the logical model.
My experience is that browsers will update the DOM when vanilla JavaScript1 code adds, moves or removes elements in the DOM, and also when changes to style sheet content or element style attributes are updated in script. Changes in the DOM appear to take place synchronously when modifying element placement or styling rules: getting the bounding rectangles of elements in the DOM whose styling or location in the DOM has been modified does not require browses to render the content first.
Hence you're basic assumptions about what you can rely on are essentially correct apart from the wording
reviewed for restyling
There is no active "review" taking place - excepting that modifying some properties can trigger a automatic and synchronous reflow operation in order for the calling script to have synchronous access to DOM property values that would need a reflow to calculate.
If you change the position of an element in the DOM, it's position has been changed upon return from the method used to change it's position.
If you add, delete or modify an attribute of an element (in the DOM), changes to the attribute and any side effects produced will have been put into effect upon return from the method used to make the change.
If you add, delete or modify style sheet rules, changes are effective in results returned from DOM inspection after the method used to change the style sheet returns.
There is a hint of this in the MDN article on `Window.getCommputedStyle. Overall I don't think it's mentioned anywhere specifically because it's inherent in the behavior of the DOM. You only get to know about it when a) you need to use the results of changes synchronously and b) are curious as to why it works as you hoped it would! :)
Examples showing synchronous results:
Changing element location in the DOM, style attribute changes:
setTimeout( ()=> {
const [div1, div2] = Array.from(document.querySelectorAll('div'));
div2.appendChild(div1);
div1.style.backgroundColor = "yellow";
div1.style.textAlign = "center";
const rect = div1.getBoundingClientRect();
const style = getComputedStyle(div1);
console.log("Synchronous results for div1: ",
{top: rect.top, backgroundColor: style.backgroundColor});
}, 3000);
<div>Division 1</div>
<div>Division 2</div>
... please wait 3 seconds
Changing CSS rules in the CSSOM
"use strict";
let div = document.querySelector('div');
let sheet = Array.from(document.styleSheets)
.find(sheet=> sheet.ownerNode.id == "absDiv");
console.log("div offsetWidth ", div.offsetWidth); // before
sheet.insertRule("div{ width: 200px;}");
console.log("after width set in CSS: ", div.offsetWidth);
<style id="absDiv">
div { background-color: yellow; }
</style>
<div>Div element</div>
1 Vanilla Javascript implicitly excludes cases of shadow DOMs and components. Refer to Kaido's answer for broader treatment.
I want to permanently modify a css rule (such that new elements will take on this css rule). It appears that all jquery modifications using css do not persist (Say modifying a background color for future elements does not persist when they are created):
$(".red").css("background-color", "blue");
See my fiddle here:
https://jsfiddle.net/Lvm0c7m6/
I would like all future elements to now have the new rule created by css, is there a way to do this (with good cross browser support).
You order javascript at execution time to add an inline style to all elements with class 'red', coloring them blue. After that you add new elements to the DOM. They have no knowledge of the earlier command an therefore are not influenced by them.
This solves your problem, as this adds a style rule to the document. This influences all elements and is 'persistent':
$( "<style>.red { background: blue; }</style>" ).appendTo( "body" );
See: https://jsfiddle.net/aLghL2ke/
Note that if you want to run this command multiple times, it would be nice to remove the old style block from your code. This can be done with jQuery too using this command:
$( "body style" ).remove();
See: https://jsfiddle.net/4duxsz0a/
How can i add/remove class according as div width ? I tried some codes but I have no idea about jquery codes. I'd like add div class according as antoher div width. Just i need add class like that. If container is smaller than 600px "add class" to content div else "remove class" from content div. These are my codes;
<div class="container">
<div class="content"></div>
</div>
$(window).resizeboxes(function() {
if ($(".container").width < 600){
$( ".content" ).addClass( ".content_600" );
}
});
else{
removeClass('.content_600')
}
$(window).trigger('resizeboxes');
This works, though the code is changed slightly. There were some problems with the syntax also, so I've corrected those (for instance the else statement was slightly misplaced). Here is a working example:
https://jsfiddle.net/vt0nbx36/3/
Here is the code:
var resizeboxes = function() {
if ($(".container").width() < 600)
{
$(".content").addClass("content_600");
}
else
{
$(".content").removeClass("content_600")
}
};
resizeboxes();
$(window).resize(function(){
resizeboxes();
});
For this need exactly, you have jQuery's .toggleClass() function. It takes the class name as a first parameter, and optional second boolean parameter that states wether the class name should be added or removed. You can find the documentation here
$(".content").toggleClass("content_600", ($(".container").width() < 600));
Even tho your question is a JS related question, CSS as a matter of fact can handle this like no other beast can (mostly)!
CSS allows you to use media-queries to resize your content based on the width of the viewport.
The upside of this is that the browser will handle this for you within the rendering engine rather than having JS between your change and the rendering engine.
The major downside is that you can't define the width of element A based on element B but are unfortunately locked to using the viewport as an indicator.
Before I explain why you'd want to use CSS I'd like to point out why you don't want to use JS for this if possible.
The jQuery.resize eventhandler fires inconsistently across browsers and it fires alot of times usually.
This causes your scrolling to clog up and make your webpage feel laggy.
If there's anything your users will dislike it's the fact that scrolling is controlled by something they don't even know of which is slowing you down.
As for a CSS solution, a media query looks like this:
.my-selector {
width: 900px;
}
#media all and (max-width: 600px) {
.my-selector {
width: 600px;
...
}
}
You wrap your code in a sort-of conditional that allows you to be very flexible with manipulating elements on the page.
What happens in the above piece of code is that when the parser reads the CSS it sees the first selector not in a media query so it applies width: 900px; then it sees a media query and sees the other rule for my-selector however it will only apply that rule when the screen is at that width we defined in the #media ... rule. When you resize CSS handles things differently behind the scenes so it's much faster than JS in that case.
I'm not sure if it actually applies to your situation but if your container is sized by the viewport rather than parent elements this should be possible and I thought it'd be nice atleast to show you a good way of playing with element dimensions.
Also, you can use #media to for instance make a webpage print friendly by changing the all to print for example and setting the background-color: transparent for an element - saves ink ^.^ which is an additional extra on top of the general awesomeness of media queries.
Hope it helps, good luck if you wish to make your webpage 5 times faster ;)
edit:
The problem seems to be that the font size isnt explicitly set and is set by the css class only. so style.fontSize always returns an empty string
if there another way to return the font size?
var allMainFrameElems = parent.main.document.getElementsByTagName('*');
for (i=0; i < allMainFrameElems.length; i++){
if(allMainFrameElems[i].style.fontSize != null){
alert(llMainFrameElems[i].style.fontSize);
}
}
If the fontSize style in not explicitly set on an element (e.g. <p style="font-size:12pt;">...</p>), you won't be able to get it from anywhere. Font-sizes are most often set in your CSS classes, which are not reachable from your element's properties, and the elements do not have any font-size related properties.
In order to even come close to doing this you will need to do some tricks and will not be able to definatively determine font size. Basically you will have to manipulate the page a great deal on every element (not good) just to determine this.
See this fiddle page, especially the pixelPerEm function I tossed together very quickly. http://jsfiddle.net/MarkSchultheiss/vc8Zy/
It is not very clean at the moment and IF I get time I might try to make it better but it might give you something to start with even if it is NOT very pretty.
EDIT: basic explanation is to utilize the em css, inject an element with a known setting, calculate the pixel offset on the injection and then remove the injected element. None of that is pretty and all of it is error/bug prone or has potential for issues.
I'm trying to make a webpage where it basically looks like a word document. There would be multiple boxes that would scroll down and the text would flow and page break from one page to the next.
Does anyone have any idea where I would even start? Thanks.
Edit: It should be right in the browser, looking similar to this:
(Ignore the columns)
CSS mostly applies styles to a full element due to its box model. Exceptions are pseudo elements. So to create an appropriate break after a fixed length you would have to separate your text into correctly sized different elements.
EDIT:
It would be possible using javascript. But even in the simplest case, where everything inside the pages delivered as just one text element with no sub elements (not even other text elements), the code will be a development nightmare and will run quite crappy. This is because there is no measure function in javascript. So you would be forced to do trail and error to find the correct position to break the element. Since the properties of the elements are live it means, that the viewer of the website will see a lot of flickering of your page just after loading. If you dare put other elements inside the html element to break into pages you get even more problems. More or less you get hundreds of special cases (break inside other elements, what if those elements are inside even other elements) to look out for.
Something like that sounds possible using javascript, but it depends a bit on the structure of your html and whether or not you want to break paragraphs or just move the next paragraph to the next page if it doesn´t fit
So the simplest example, not breaking paragraphs / html elements with a flat html structure (no nested divs, columns, etc) like:
<div class="document">
<h1>title</h1>
<p>texts</p>
<h2>subtitle</h2>
<p>texts</p>
...
<p>texts</p>
</div>
would be to do something like:
height = 0
loop through all direct child elements of .document
{
if ( (height + element_height) > page_height)
{
add page_break_element before current element
height = 0
}
height = height + element_height
}
I´d use jquery because it makes it easy to loop through the elements, measure heights, etc.
I guess breaking paragraphs would be possible as well, but a lot of extra work.
<p style="page-break-before: always">This would print on the next page</p>