bug: performance issue with select + checkbox
Reproduction URL (Required)
https://michaelkhabarov.github.io/daisyui-performance-issue/
What version of daisyUI are you using?
v5.0.27
Which browsers are you seeing the problem on?
Chrome
Describe your issue
Hello
I am experiencing a performance issue with DaisyUI using the following simple HTML:
<html>
<head>
<link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet" type="text/css" />
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
</head>
<body>
<!-- removing this select fixes issue -->
<select></select>
<label>Checkbox: <input type="checkbox" /></label>
<script>
content = ""
for (let i = 0; i < 3000; i++) {
content += `<div class="btn">Btn</div>`
}
document.body.innerHTML += content
</script>
</body>
</html>
Clicking the checkbox takes approximately 150 ms to process, and about 500 ms with a 4x CPU slowdown. This action triggers a repaint of the entire page, including all 3000 .btn elements. The more elements on the page, the slower the performance becomes.
Removing the select tag completely resolves the issue, reducing the checkbox selection time to around 50 ms and repainting only the checkbox itself.
This issue is reproducible on Chrome for macOS M1 v135.0.7049.96, but not on Chrome for Linux v132.0.6834.110. So, Iโm not sure if this is entirely a DaisyUI issue
Thank you @michaelkhabarov
for reporting issues. It helps daisyUI a lot ๐
I'll be working on issues one by one. I will help with this one as soon as a I
find a solution.
In the meantime providing more details and reproduction links would be
helpful.
This might be because of :root:has(input.theme-controller[value=dark]:checked) selector.
Are you also experiencing a lag with devtools closed? or on a real app? I assume 4x slower than M1 would be a ~2015 Macbook airโฆ
@michaelkhabarov @saadeghi I was about to open the same issue. I'm using AG Grid, and I've noticed a visible performance drop โ especially with row highlighting on hover (cpu goes > 140)โ when there's a select component on the page.
If I either disable the DaisyUI plugin or remove the select component, AG Grid works smoothly without any lag during hover. (cpu < 30)
This might be because of
:root:has(input.theme-controller[value=dark]:checked)selector.
Removing this selector from final bundle does not help
Are you also experiencing a lag with devtools closed? or on a real app?
Yes, we have a relatively big page with around 20,000 DOM elements in production. Clicking on checkbox takes about a second with devtools closed and without CPU slowdown. Also tried in incognito tab - same result
We also encountered this issue in DaisyUI v4.12.23
I also experienced a similar issue with DaisyUI and ag-grid table.
It's the "Recalculate Styles" that is taking all the time. A sample from dev-tools with css-selectors enabled for one "Recalculate Styles":
| Elapsed (ms) | Match attempts | Match count | % of slow-path non-matches | Selector | Style Sheet |
|---|---|---|---|---|---|
| 140.051 | 101548 | 8652 | 47.1 | (Totals for all selectors) | |
| 5.359 | 3948 | 0 | 85.7 | & > * | Unable to link via style-sheet-1326118-640 |
| 5.271 | 3948 | 0 | 85.7 | & > * | Unable to link via style-sheet-1326118-641 |
| 4.801 | 3384 | 0 | 0.0 | &:nth-child(2) | Unable to link via style-sheet-1326118-640 |
| 4.701 | 3384 | 0 | 0.0 | &:nth-child(2) | Unable to link via style-sheet-1326118-641 |
| 3.889 | 2820 | 0 | 0.0 | &:nth-child(1) | Unable to link via style-sheet-1326118-641 |
| 3.853 | 2820 | 0 | 0.0 | &:nth-child(1) | Unable to link via style-sheet-1326118-640 |
| 3.292 | 2256 | 6 | 0.0 | :where(& > :not(:last-child)) | Unable to link via style-sheet-1326118-640 |
| 3.244 | 2256 | 6 | 0.0 | :where(& > :not(:last-child)) | Unable to link via style-sheet-1326118-641 |
| 2.402 | 1718 | 18 | 0.0 | &::before | Unable to link via style-sheet-1326118-641 |
| 2.372 | 1718 | 18 | 0.0 | &::before | Unable to link via style |
I'm working on it.
Apparently the repaint is because of a shared CSS variable --fx-noise used in different elements. That can be fixed by putting the value in each element repeatedly instead of using a global variable and it would fix the unnecessary repaint issue.
However that doesn't effect INP. Looks like using less CSS properties for button decreases the INP, but that's not an option since all the used properties are necessary.
I will try more things.
We're also experiencing a major drop in performance with Chrome (also Edge) when using the class select.
Started commenting out CSS until I discovered that when removing these lines from the class select the drop in performance issue was fixed:
@supports (appearance: base-select) {
appearance: base-select;
}
@supports (appearance: base-select) {
&::picker(select) {
appearance: base-select;
}
}
"daisyui": "^5.1.13",
I had the same problem.
@Drelekin's alternative didn't work. Maybe I did it wrong or something else.
So the solution I found was to avoid using and use https://daisyui.com/components/dropdown/
"daisyui": "^5.3.10",
We've also been seeing the performance issues with style recalculations since 5.1.0
Doesn't seem related to any specific components being on screen, but performance of even simple animations (anything that causes a style recalculation) is pretty much unusable
Can you pinpoint the version that has problems at 5.1.0? I mean with 5.0.55 it was ok and with 5.1.0 the problems showed up? I need the info to try to identify the change
That'll be a little tricky as my work uses an internal npm repo so I only have 5.1.0 and 5.0.0 available
I'll get a test project at home tomorrow and bisect through to narrow it down
Yes, please, of you can it would help because you can identify better when the problem happens
BTW, skip checking 5.0.55 (it's the same as 5.1.0), check 5.054 and before (if it's already present in 5.1.0)
I've put together a simple Vue app that moves cards around with a TransitionGroup to replicate this: daisyui-perf-test
While the performance here is pretty okay across all versions (as it's a simple app), there is a significant increase in CSS selector times at 5.0.30 and at 5.0.32
Full results are in results/ with the complete CSS selector stats, but the totals for each version I tested are:
| Version | Time | Diff (ms) | Diff % |
|---|---|---|---|
| 5.0.0 (baseline) | 7.259 | 0 | 0.00% |
| 5.0.25 | 7.489 | + 0.23 | + 3.17% |
| 5.0.28 | 7.905 | + 0.646 | + 8.90% |
| 5.0.29 | 7.669 | + 0.41 | + 5.65% |
| 5.0.30 | 9.287 | + 2.028 | + 27.94% |
| 5.0.31 | 9.67 | + 2.411 | + 33.21% |
| 5.0.32 | 12.401 | + 5.142 | + 70.84% |
| 5.0.35 | 12.022 | + 4.763 | + 65.62% |
| 5.0.55 | 12.651 | + 5.392 | + 74.28% |
| 5.1.0 | 12.433 | + 5.174 | + 71.28% |
| 5.4.3 | 12.599 | + 5.34 | + 73.56% |
Tested on an M2 Macbook Air, Chrome 141
This doesn't seem to make sense:
5.0.29->5.0.30: modified the matches on .tooltip, but it should be already qualified by .tooltip and you don't have any
5.0.31->5.0.32: added a touch-action: manipulation on .btn and the increase in time is 33%
@pdanpdan There's tooltip in the card that was used for benchmark src/components/TestCard.vue
@lewisdoesstuff Thanks for the benchmark repo. The added selectors (which uses CSS :has() or the touch-action: manipulation in button) are required, and they are not decorative.
It is expected for CSS :has() selector to have relatively lower performance than a .classname selector because browsers need to check the children. But this shouldn't be an issue, since a browser is way more faster than that in rendering.
Maybe we can find a way to help if you share a real-life example of the situation.
For example if there's a need for 100 cards to have animations, maybe using a tooltip inside them is not worth it ๐
Sorry, I missed the tooltip, so for 29->30 it is reasonable, but why the huge difference between 31 and 32 which should be very similar
Thanks guys, I'll try and put together a more real-world example tomorrow, as I've noticed this when doing things other than list animations