VolkovLabs / volkovlabs-dynamictext-panel

Business Text Panel for @grafana
https://docs.volkovlabs.io
Apache License 2.0
78 stars 14 forks source link

Positioning of HTML elements over overriding css in style attribute does not work #209

Closed nikchuk closed 9 months ago

nikchuk commented 10 months ago

In case of dynamic visualization it is needed sometimes to control positioning of elements on the page depending on values retrieved from database. Static positioning works fine when adjusted in CSS styles. However, if there is a need to override it dynamically in style attribute of HTML tag, it doesn't work. Looks like all other overridings except top, bottom, left, and right work.

In example below div with style attribute ignores top and left properties, but all other are applied:

Content:

<div class="parent">
  <div id= "1" class="child"></div>
  <div id= "2"style="position : absolute, top : 100px; left : 200px; height : 20px; width : 20px; background-color: red;"></div>
</div>

CSS Style:

.parent {
    position: relative;
    width: 200px;
    height: 300px;
    border: 5px solid #1C4C97;
    background-color: blue;
}
.child {
    position: absolute;
    top:50px;
    left: 50px;
    width: 10px;
    height: 10px;
    background: white;
}
nikchuk commented 10 months ago

Here is example how height of the item can be dynamically according to value from DB, but the same trick doesn't work for top, bottom, left, and right.

<div class="parent">
  <div id= "1" class="child" style="height: {{value_from_TSDB}}%;"></div>
  <div id= "2"style="position : absolute, top : 100px; left : 200px; height : 20px; width : 20px; background-color: red;"></div>
</div>
mikhail-vl commented 10 months ago

@nikchuk I will take a look and get back to you.

nikchuk commented 9 months ago

@mikhail-vl maybe you had a chance to check this out?

asimonok commented 9 months ago

Hi @nikchuk There is html syntax error so styles are not applied. Unfortunately, we don't check HTML for errors so it's not clear what was wrong. Please make sure that you separate inline styles by semicolon.

style="position : absolute ,// error here ..."

Here is the valid HTML for your case: First:

<div class="parent">
  <div id= "1" class="child"></div>
  <div id= "2"style="position : absolute; top : 100px; left : 200px; height : 20px; width : 20px; background-color: red;"></div>
</div>

Second:

<div class="parent">
  <div id= "1" class="child" style="height: {{value_from_TSDB}}%;"></div>
  <div id= "2"style="position : absolute; top : 100px; left : 200px; height : 20px; width : 20px; background-color: red;"></div>
</div>
nikchuk commented 9 months ago

hi @asimonok. Thanks for answering and sorry for confusion. It was not a copy paste from my code, it was a typo here. In my code there was semicolon and the positioning over inline style still does not work.

asimonok commented 9 months ago

@nikchuk could you share more details about the issue? using code, screenshots, etc.

Is this the expected result on the screenshot?

Screenshot 2023-09-26 at 13 20 50
nikchuk commented 9 months ago

@asimonok Sure. Here is how it looks like with inline style: image

<div class="tank">
  <div class="liquid" style="height: {{level}}%;"></div>
  <div class="sq" style="position : absolute; top : 100px; left : 100px; height : 30px; width : 30px; background-color: red;"></div>
</div>
  .tank {
    position: relative;
    width: 200px;
    height: 300px;
    border: 3px solid black;
    border-bottom-left-radius: 20px;
    border-bottom-right-radius: 20px;
    border-top-left-radius: 1px;
    border-top-right-radius: 1px;    
  }
  .liquid {
    position: absolute;
    bottom: 0;
    width: 100%;
    background-color: blue;
    opacity: 0.2;
    border-bottom-left-radius: 20px;
    border-bottom-right-radius: 20px;
  }
  .sq {
    position: absolute;
    height: 150px;
    width: 150px;
    //top : 200px;
    //left : 200px;
    background: red;
  }

As you can see red square is at the top left corner (position ignored) but the size is 30px as written in inline style.

If position is defined in css, everything looks ok, but I can not use then the value from database for positioning: image

<div class="tank">
  <div class="liquid" style="height: {{level}}%;"></div>
  <div class="sq" style="position : absolute; height : 30px; width : 30px; background-color: red;"></div>
</div>
  .tank {
    position: relative;
    width: 200px;
    height: 300px;
    border: 3px solid black;
    border-bottom-left-radius: 20px;
    border-bottom-right-radius: 20px;
    border-top-left-radius: 1px;
    border-top-right-radius: 1px;    
  }
  .liquid {
    position: absolute;
    bottom: 0;
    width: 100%;
    background-color: blue;
    opacity: 0.2;
    border-bottom-left-radius: 20px;
    border-bottom-right-radius: 20px;
  }
  .sq {
    position: absolute;
    height: 150px;
    width: 150px;
    top : 200px;
    left : 200px;
    background: red;
  }
nikchuk commented 9 months ago

It is really weird, because the part with positioning is missing for this div (red square) in the inspection mode: image

Also, the same code works fine isolated (out of the DynamicText plugin).

asimonok commented 9 months ago

@nikchuk thanks for the provided details. If I got it correctly, It looks .sq class doesn't have the left and top CSS rules in the CSS file. Please check if it really has. Because we don't sanitize imported CSS files somehow.

Also, it's interesting that there is a combined CSS selector .css-1nas63 .sq. Is it a hardcoded value in your CSS file or made dynamically?

In addition, CSS styles will be used overridden with inline styles. The problem could be that. https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity

nikchuk commented 9 months ago

@asimonok it has for sure. And if you add them directly in the inspection tool - they appear and apply to dedicated div. .css-1nas63 is something dynamic, I'm not sure from where it comes. My css added in DynamicText was mentioned in one of the comments above. There is nothing else connected to the page.

As I also mentioned, the same code works absolutely as expected if added into simple html file and launched in browser.

nikchuk commented 9 months ago

@asimonok FYI, disable sanitizing in Grafana has helped. This specific inline style is not removed and properly applied.

mikhail-vl commented 9 months ago

@nikchuk Sanitizing in Grafana is tricky and it's constantly improving, which is great from the security point of view. Also, Grafana runs JavaScript in a Sandbox now, which can lead to unexpected results.

Great to hear that you figured it out.