What is involved in Chrome's Recalculate Style Event? - css

TL;DR
What causes Recalculate Style in Chrome and what could be done to reduce the time for this step?
Background
In an application with many elements (variable, e.g. 10,000) I observe Recalculate Style taking a long time when adding a class on the parent element of those elements. There are selectors that will affect elements of each subtree when the container has this class.
In the developer tools I was able to trace the cause of the Recalculate Style event by clicking here (screenshot of a MCVE):
From to the name I assume that this step involves calculating the effective (final) element style. I think this happens when
a changed element style,
a changed (pseudo-) class
of the element itself or
of a parent or sibling element that is related by a selector or
a changed CSS selector (importing new CSS, generating <style>)
forces the browser to recalculate the CSS attributes of an element.
Attempt to prove my thesis
I created a MCVE with the same amount of elements as static HTML and toggling a class .change on a .container using a click handler on the document - dead simple code.
The MCVE performs much better than the actual application, the step Recalculate Style takes less time. This is probably due to the simpler tree and less styles.
Then I started adding more styles to all selectors and the average time increased with every bunch of new CSS attributes. Adding more elements to the 10,000 subtrees did not change the average time.
So, I'd say that the amount of CSS attributes, the count of selectors affected and the count of elements affected influences this time.

Recalculate Style
Get all the style rules
Evaluate the selectors and match against the DOM
Calculate the computed style for every element
Basically anytime you change a classname or other operations like that.
References
https://youtu.be/0xx_dkv9DEY?t=204
https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations

Related

angular showing/hiding DOM elements based on what class they have

I'm going to simplify my problem a bit, because I really want to avoid adding a lot of code, because this is a gigantic project we are working on if I started adding code snippets, there would be a lot of it.
My project has one feature, where you have a list of different div elements in the left column of the page, and they can be individually dragged to the right column, where you can make your own list out of these elements in the order you choose.
These div elements are all the same child component. My task is to add a dropdown to these div elements, but only to the ones that have been dragged to the right column (you can choose additional preferences, once it's in the right column). It shouldn't be there on the divs in the left column.
The only way to differentiate between them is by the class name. The ones on the left have a class="left" and the ones on the right get the class="right".
Now I'm wondering if there's a way where I can write some code to the effect: if the element has the class 'left', hide the dropdown, else show the dropdown?
Yes, this is definitely possible.
Create a Directive that has a #HostBinding() for a specific class and just add the directive to every component.
Inject ChildComponent into the constructor of that Directive. You can also inject ViewContainerRef and then call this.viewContainerRef["_data"].componentView.component This will give you reference to that child element that the directive is put on.
Once the #HostBinding('.left') event handler is triggered this will be the function that gets called when the class you're looking for is added. Here you can then access that ChildComponent and then presumably call a method on that child component to show/hide the mat-select
I haven't actually tested this but thats the approach I would take.
You might also achieve this thru your css. Something like
div[class*="left"] dropdown-element {
display: none;
~or~
visibility: hidden;
}

Is there a way to change size of ng-cicle-progress CircleProgressComponent element dynamically?

In the Angular 11 project I need to change ng-circle-progress library CircleProgressComponent element size dynamically.
I have found out, that size of the element can be changed by putting width/height CSS properties on the child DOM element - svg. Problem is that svg doesn't have any id or class values, so even if I could somehow query the element, this would be not that easy and flexible as it should be.
Would be extremely nice to have a parameter in the CircleProgressComponent, that listens to outer variable changes and re-renders the element with a new size.
I had never used this library, so I've read their doc and thier demo page.
If I understand, they have the parameter that you want called radius
<circle-progress
[percent]="85"
[radius]="200" // the size you want
[outerStrokeWidth]="16"
[innerStrokeWidth]="8"
[outerStrokeColor]="'#78C000'"
[innerStrokeColor]="'#C7E596'"
[animation]="true"
[animationDuration]="300"
></circle-progress>

Why do I get a different offsetHeight value within ngOnChanges?

Example plunker:
http://plnkr.co/edit/YLLslImGOpS8u6zx
In the plunker, I display the height and width of a div from the parent component using ViewChild.
I pass the div from the parent component to the child component as an Input HTMLElement, and in the child component, I again read the currentValue of this input. If you open the browser console, I logged the SimpleChanges object. If you look at the currentValue.offsetHeight, the height is the expected value (i.e. the value matches what the parent component is displaying)
However, the child component is displaying a different value from the expected.
Whats even stranger is if you edit the child component template to something like:
<div>
<p>Child: {{ display }}</p>
</div>
Simply adding some additional content in the div, the child component now displays the expected value (i.e. the value matches what the parent component is displaying, and it matches the value in SimpleChanges)
To put it simply, why does this difference occur?
In my code-base, I'm experiencing an issue using offsetHeight where the value within SimpleChanges is accurate, but the value I try to store on an instance variable and use within the component is inaccurate. This plunker probably does not emulate exactly the issue I face in my code-base but maybe understanding the cause/effects of what I described above might help me figure out the problem I face in my code-base.
Thanks!

CSS , GWT and reading composed class name

in a GWT project I have a CSS with
.my_datagrid tr {
height: 26px;
}
and in my client code i do
grid.getElement().setClassName("my_datagrid");
that modify the minimum hight (i know isn't final) of datagrid rows, i would need for some reason to set this property (the TR height value) code way or at least read it...but the tr part make it over my understanding,
i tried with
grid.getElement().getPropertyString("tr height")
or
with
dataGrid.getElement().getStyle().getProperty("tr height")
but doesn't work..I understand that i'm working on the data grid element and not on the row but i need to know (or set) the minimal height BEFORE any row is added.
So..anyone knows how to read from css that value or remove it from css and set directly code way on my data grid?
If you need to tweak the CSS itself, then you have to use the CSSOM to manipulate the stylesheet (independently of where it's applied through matching).
GWT doesn't provide a CSSOM API, so you'll have to use JSNI. Also, beware of cross-browser support.
With a DataGrid widget, you'd better use a custom CellTableBuilder where you can inject inline style="" attributes on each generated row and/or cell.
To set a row height on all rows, you do:
myDataGrid.addStyleName("my_datagrid");
There is no way to set a height of all rows to a specific number other than by using a CSS class, but you can set height of a single row:
myDataGrid.getRowElement(index).getStyle().setHeight(26, Unit.PX);
If you need a height of a row, you can do:
int h = myDataGrid.getRowElement(index).getOffsetHeight();
Note that the actual height of a row may be different from the "style" setting, because text can wrap to have more than one line (unless you prevent it).

Is it possible to see all changes that occur because you change a css class in Chrome?

I am trying to fix a presentation bug in Google Chrome. When I change one class, the page looks correct. However, if I change every attribute of class A to those of class B, the presentation is still wrong. Therefore, one of the child elements has a different style applied when I change the style.
Is there a way to quickly see all the changes in the computed styles on all elements that occur because you change a class on one element?
With an element selected, click on the '+' in the upper right corner of the inspector. This will allow you to write a new rule.

Resources