Getting real card parameters and using them in Javascript Templates
Hello. In the case when some card parameters are set as a percentage (for example, the width or height of the card), the actual parameters will vary depending on the device parameters (in particular, the display resolution) and the browser used. For example, there may be a situation in which the card will have a larger width (in pixels) on one device, and a smaller one on the other. But the width of a text box containing, for example, the name of an entity will be the same in both cases. Let's say the width of this text box is less than the width of the card on the first device, but it is larger than the width of the card on the second device. Respectively, on the first device the entity name will be displayed in full, but not on the second. I would like to be able (in the case described above) to get the real width of the card on the device and the real width of the text box containing the name of the entity, be able to compare them, and also use the comparison result in Javascript Templates. For example, for the second case, it would be possible to assign word wrapping to a new line, reduce the font size, or arrange automatic horizontal scrolling of the text. But the most important thing is that all these additional activities should only take place when the width of the text box is larger than the width of the card. That is, for example, I do not need automatic horizontal scrolling of the text or font size reduction in the event that it already fits completely on the card. To organize what I described above, I apparently need to get the real width values inside Javascript Templates. More generally, access to more card parameters (as well as its composite and nested elements) inside Javascript Templates is desirable. Is there even such a possibility? Or maybe it can be provided in future versions?
you seem to be looking for relative sizing options, which are part of available css options. Not sure you really need them, as you still are very new to this card, and dont yet grasp all of its possibilities in combination with all that css has to offer.
why don't you try getting acquainted with the css and button-card options first. Please don't create FR's for anything you dont yet really understand. Again, go to the community for help first.
Please close this FR, there is no need for it
@Mariusthvdb, first of all, I would like to say that I have great respect for all developers, as well as those people who help ordinary users here in solving their problems... Accordingly, I do not want to create any additional problems by my actions in any way.
If by contacting the community you mean this page: https://github.com/custom-cards/button-card/discussions then, of course, I visited this page... You can probably also notice what percentage of the messages there have at least some answers, not to mention the answers that have a solution... If you have something else in mind, please provide the appropriate link...
Yes, of course, I'm a beginner, but this does not mean at all that I immediately started writing here without trying to study the issue in more depth. Of course, I tried to solve my questions on my own (and solved most of them).
Or do you think that I, as the most ordinary ordinary user, should learn css on my own at the developer level?
Yes, I have studied the information about em, rem, ex, vw, vh, but it seems to me that this is not exactly what I need - all these units determine the dimensions relative to the parent objects, but I want to understand the size of the text block relative to the size of the card... It seems to me that this is not suitable for solving my problem. If there is anything else, please tell me.
Perhaps the problem is that I did not explain very well what I want to achieve. Probably, I need to try a specific example:
The width of the left card is such that the entire text is fully displayed on the card. The width of the right card (and this is the same card) is not enough to place the entire text (this is possible, for example, on another device with a different physical screen resolution) - and in this case I need the text to automatically (without user intervention) "scroll" left and right - this also allows you to see the entire text.
Thus, as I suppose, in the java script of the card it should be possible to obtain the real size of the width of the card and the real size of the width of the text box, then a comparison of these values is required, and then the application of the necessary display option. That is, if the width of the card is sufficient, the text should not "scroll"... That's why I'm asking about the possibility of obtaining the described parameters using a Java script... Of course, if there is some other way to implement my idea (for example, using "clean" css), please tell me... I will be very grateful to you!
I suppose that getting some other actual parameters of the card using java script can be useful for solving some other interesting tasks. That is why I have raised this issue here.
Of course, if there is some other way to implement my idea (for example, using "clean" css), please tell me... I will be very grateful to you! I suppose that getting some other actual parameters of the card using java script can be useful for solving some other interesting tasks. That is why I have raised this issue here.
There is a way to do this with CSS using Container Queries and the Container Length Units, you can use container units such as cqw in a @keyframes rule and it'll adjust to the specific element the container units apply to. You can use this combination in order to create a keyframe rule which moves a text element from translateX(0), the default position, to translateX( min( calc(100cqw - 100%), 0px).
You can apply these keyframe rule animation to any text element you want to scroll back and forth. This isn't a full tutorial, but if you need any help with it just reply to this comment.
P.S. I completely believe something like element size should be something accessible in button-card templating, as it is, I haven't found a way to adjust the speed of the animation based on the size of the text.
@Jbautista13, thank you very much! But unfortunately, in my case it works somehow differently... So, if I use this option (your proposal):
@keyframes slider {
0% { transform: translateX(0px) }
100% { transform: translateX( min(calc(100cqw - 100%), 0px) ) }
}
then the text doesn't move! Apparently, because calc(100cqw - 100%) is greater than zero, respectively, min returns 0px ...
But if I use, for example, this option (1cqw instead of 100cqw):
@keyframes slider {
0% { transform: translateX(0px) }
100% { transform: translateX( min(calc(1cqw - 100%), 0px) ) }
}
the text moves! But it moves even if the width of the card is greater than the width of the text! Which I don't want at all...
Maybe the problem is with cqw... But where is the problem specifically... I don't quite understand...
@il77781 calc(100cqw - 100%) should be the correct line, did you set the container-type to inline-size on the parent element? If you're applying the @keyframes slider animation to the #name element in button-card, the styles you would apply to ensure it works correctly would pretty much be,
styles:
name:
- text-overflow: unset
- overflow-x: scroll
- max-width: unset
- justify-self: start
grid:
- container-type: inline-size
It's important you set container-type: inline-size on the parent element of the text element you want to scroll, in this case, grid is how you style the #container element which is the parent element of the name element.
On top of this you would add the @keyframes slider animation rule and apply it the to the name element.
@Jbautista13, thank you very much!!! Of all the parameters you provided, in my case, the following turned out to be mandatory:
styles:
name:
- max-width: unset
- justify-self: start
grid:
- container-type: inline-size
I don't know how mandatory it is to apply the others you have listed... Perhaps everything is displayed correctly only in my case, and in some other conditions nothing will work correctly... Well, in order to understand this for sure, I probably need to study css more deeply...
And one more small "nuisance"... When using justify-self: start, if the width of the text is less than the width of the card, the text will be aligned to the left... But I would like to align to the center of the card for such a case...
I tried using justify-self: safe center, and in my case everything worked correctly: when the width of the text was greater than the width of the card, the text moved correctly (as if justify-self: start was set), and when the width of the text was less than the width of the card, it was displayed in the center... Is it even possible to do this?
@il77781 justify-self: safe center; as you found works perfectly in this case.
justify-self: start isn't actually necessary for this to work, I accidentally sent it in my previous message as I was working on a button-card where the text has to be left-aligned and not centered.
justify-self: safe center; changes the justify to start automatically when the text is too long which works perfectly as if the text is short enough to be centered the transform: translateX( min(calc(100cqw - 100%), 0px) ) line in the animation rule won't allow it to scroll anyways. Technically you could get away with just justify-self: safe center but this would require adjusting the scrolling animation so it's easiest to ensure the text is going to be left-aligned the moment you need it to scroll which justify-self: safe center does.
@Jbautista13, yes, apparently everything works exactly as you describe...
as if the text is short enough to be centered the
transform: translateX( min(calc(100cqw - 100%), 0px) )line in the animation rule won't allow it to scroll anyways.
Yes, I understood that too.
Now I use only justify-self: safe center and everything works well!
Thanks again for the suggested solution!
In my opinion, it is much simpler than what I found and used earlier...
P.S. I completely believe something like element size should be something accessible in button-card templating,
Previously, to get the width of the text, I used this.shadowRoot.querySelector("[id='name']").scrollWidth
But, unfortunately, this method has a very significant drawback: apparently, a significant value (not null) of this.shadowRoot.querySelector("[id='name']").scrollWidth appears a little later than the button-card rendering occurs... Therefore, initially the template does not receive the current text width value, and therefore the text does not move... The text starts moving only after the next "update" of the button-card. And since the button-card update is a rather specific story, laid down by the author, apparently, to reduce the use of resources, the "update" of the card may not happen immediately and the text will not move all that time... Therefore, I also had to create an additional sensor that changes its state (with a slight delay, so that this.shadowRoot.querySelector("[id='name']").scrollWidth would surely take on a significant value) when changing the dashboard and changing the screen orientation. That is, this sensor changes its value in situations where the width of the card may change (which, in turn, may require comparing the new width of the card and the width of the text)... And then I also need to specify this sensor in the triggers_update for the button-card.
Unfortunately, I did not find how to change the state of this additional sensor when hiding/showing the sidebar (since the width of the cards also changes in this case), therefore, the described method is not quite complete ...
Your solution is much simpler and much more complete!
Perhaps there are some other methods...
You can wait for the lit updateComplete promise of the button-card. See here for an example of how to use.
Modern CSS allows for what you wish to achieve so closing this issue. Moreover, providing for sizes which would likely change with CSS changes would be an endless loop.
Note: Expanded Sidebar menu is defined in ha-sidebar css
https://github.com/home-assistant/frontend/blob/10e09b238a9e97092986f4f8f089787b6251dbb5/src/components/ha-sidebar.ts#L733
@dcapslock, thank you for your response!
Do I understand correctly that updateComplete avoids the situation where data requested through shadowRoot is not available at the time of the button-card rendering? The required data will only be requested after the card is fully "updated," right?
In this case, it seems to solve the described problem...
Unfortunately, I cannot verify this right now, as I am currently using the method suggested by @Jbautista13 ... I think it's lighter anyway, isn't it?
Modern CSS allows for what you wish to achieve so closing this issue.
And, apparently, you also write about this here, right?
Note: Expanded Sidebar menu is defined in ha-sidebar css
To be honest, I don't quite understand how this can help... The sidebar is removed/appears - the width of the cards changes... Accordingly, when the width of the cards changes, it is necessary to re-render the cards to check the width of the text and the new width of the cards. Therefore, it is necessary to track this change in width (similar to tracking screen orientation changes). However, it is unclear how to track this change when the sidebar appears or disappears...
Do I understand correctly that
updateCompleteavoids the situation where data requested throughshadowRootis not available at the time of thebutton-cardrendering? The required data will only be requested after the card is fully "updated," right? In this case, it seems to solve the described problem...
Yes, with the lit lifecycle the updatePromise will be resolved if the lit element has finished updating, but will be unresolved while it is updating. You speak of data availability. In reality it is about components being ready.
And, apparently, you also write about this here, right?
Yes. Modern web layout is done with CSS. Elements provide CSS variables to use. You have at your disposal media queries, calc() etc. You have examples here for positioning, translation, flow etc. You should not need to use javascript just for layout. For example, if you know that below a certain screen size, your text is likely to overflow, then think about reflowing the buttons so that they stack rather than quish.
As for the sidebar query, that CSS variable could be used as a divisor perhaps for a ratio in a CSS calc(). Without knowing your whole config its hard to provide an example.
Overall, think about how CSS provides for what you need, not a state machine that you need to track.
@dcapslock,
then think about reflowing the buttons so that they stack rather than quish
As far as I understand, the Home Assistant dashboards themselves, in accordance with some specific rules, determine the number of columns for placing cards, depending on the available width. Apparently, we have a more "flexible" situation when using the Sections layout, but there are still some rules that may change the number of columns when the available width is reached... To be honest, I don't really like the idea of moving the buttons to a new row (in some situations, it may disrupt the logic of their placement based on their functionality), and it's not always possible... So, as far as I understand, I can only provide for the use of the "scroll" described above in cases where the width of the cards decreases when the dashboard's content is "rebuilt" in case of available width - and using css, this works perfectly in all situations!
Without knowing your whole config its hard to provide an example.
I don't have this configuration anymore either, as the css works perfectly when the sidebar's state changes... My question was about how this could help in a situation where the css is not being used (my initial solution). However, it now has only theoretical significance, as there is an easier and more effective solution available...
Overall, think about how CSS provides for what you need, not a state machine that you need to track.
Thank you so much for your help and clarification, and I will try to delve deeper into the possibilities provided by css whenever possible!