Diagonally superimposed div over colored td with css gradient

I have a table with background-colored TDs and I want to superimpose on some of them an angled colored div with some text on it.

I tried something here on jsfiddle: [click on TD to make div appear]
(https://jsfiddle.net/7uLta26g/22/)

 <table style="width:100%;border-spacing: 4px; border-collapse: separate; margin-left: auto; margin-right: auto;">
  <tr>
   <td id ="td0" >
        <span>
            test0
        </span>
    </td>
    <td id ="td1" onclick='_addCSSText(this, "KP", "#FFFF00")'>
      <div id="DIVlayer"></div>
        <span>
            CLICK ME
        </span>
    </td>
    <td id="td2">
      <span>test2 does not put div correctly and other problems related to some positioning relative or absolute</span>
      </td>
  </tr>
</table>

CSS:

td {
    background-color: lightgreen;
    text-align: center;
    vertical-align: middle;
    border-radius: 20px;
}
#td1 {
    width: 30%;
    height: 100%;
}
#td2 {
    width:  20%;
    height: 100%;
}
.layer {
    background: linear-gradient(140deg, rgba(0, 0, 255, 100) 20%, transparent 20%);
    position: relative;
    text-align: left;
    vertical-align: left;
    top: 30;
    left: 10;
    width: 100%;
    height: 100%;
    border-radius: 8px;
}
.layer::before {
     content: attr(custom-text);
      /* color: attr(custom-color color);*/
     color: yellow;
     top: 0;
     left: 0;
     font-size: 2em;
}

JS+jQuery:

function _addCSSText(td, text, color) {
        el = jQuery("#DIVlayer")
        let i=3
        el.attr("custom-text",text)
        el.attr("custom-color",color)
        el.addClass("layer")
      }
      

I used css ::before to put the text on the div and used linear gradient css to make the div diagonally colored over TD only on part of it

Problems are:

  1. div with BG blue does not always go diagonally from top to bottom border of the TD (also TD changes its height because of different text inside it, but Div is fixed in its height).

  2. text inside TD goes down when DIV appears, like an inline element, instead I would like TD height to remain the same, even after div appeared

  3. text inside DIV is too much near to the TD border

  4. I would also like to pass the color of the text inside Div, but it seems Browsers do not work with attr(custom-color color) in CSS (instead they work with attr(custom-text)…)

Hi,

For a gradient to the corners don’t use angles but use sides.

e.g.

Then you would need to absolutely position the overlay and remove it from the flow. Of course it will obscure any content in its way.

You would need position:relative on the parent td so that you have stacking context for the absolutely positioned div (don’t use relative position to structurally move things around as that’s not what it is meant for.)

Don’t forget to use units as some browsers will treat unitless values for dimensions as zero. You also set the element to be top:30px and left:10px and then you gave it 100% height and width. 100% + 30px is to big for any container. Use the 4 co-ordinate system (top,left,bottom,right) without width and height when you want to offset and element in relation to its parent container.

These would be the changes you mentioned but I don’t know if indeed that was what you are after.

#td1{position:relative;}
.layer {
      background: linear-gradient(to bottom right, rgba(0, 0, 255, .7) 50%, transparent 50.5%)
    no-repeat 0px 0px;
    position: absolute;
    text-align: left;
    vertical-align: left;
    top: 10px;
    left: 10px;
    right:10px;
    bottom:10px;
    border-radius: 8px;
}
.layer::before {
     content: attr(custom-text);
      /* color: attr(custom-color color);*/
     color: yellow;
     font-size: 2em;
}

Screen Shot 2020-10-20 at 13.17.40

If this is not tabular data then you should not really be using the html table elements as tables are for tabular data and only make sense in that context.

Then give some padding to the td in question to give it some room.e.g. #td2{padding:10px;}

Hi Paul, thank you.
Yes these are tabular data, not only one row, but multiple ones.

Your first suggestion took me quite near to the result I want (the trick was to put the text inside the div). But I prefer the deg instead of sides.
I reached this point (EDIT):
https://jsfiddle.net/dbrh0xwv/3/

Now I have only this problem:
I want the text inside the span of the td to be aligned centered both oriz. and vert.
But the text inside the div aligned to the left, as it must be inside the blue diag.

So I put into td this:

    text-align: center;
    vertical-align: middle;

But the result is the text of div goes out of the blue, near the td text. Bad:
https://jsfiddle.net/f2kmutr5/


If I put into the div:
text-align: left;

It brings also the td text to the left, near the div text and the left border. Not so good.

How to resolve this?

Another thing I don’t understand, is:
I want a padding on general TD, but I don’t want it in the td with the div, to make the blue diag coincide with the td border.
So I zeroed the padding in the specified td, BUT it zeroed only the left padding and not the top one??

https://jsfiddle.net/5zk8phq6/

Hi,

Do you have a drawing of what you want to achieve as I can’t really get a handle on what design you are looking for?

This is what I see in both those examples and there seems no logic to what I’m seeing.

What is the blue diagonal and the letter P supposed to achieve? How is it supposed to align in relation to the text that you have in that section? You said you wanted it as an overlay but now it is in the flow as part of the content in that cell.

If you want the blue to stay at the top you will need to add vertical-align:top here:

#td1 {
    width: 30%;
    height: 100%;
    padding: 0px;
    vertical-align:top;
}

As an aside I note that you are using span elements and applying margins and padding to them but vertical margins don’t really apply to inline elements and padding will bleed out of the line-height. It probably makes no difference at the moment but you should be using a block element like a div (or p element for a paragraph) instead of a span. Spans are inline elements that hold inline phrase content and not usually whole sentences.

No you are mistaken the padding on the td is zeroed. There is some padding on the inner elements and the text will align with the baseline of the enlarged letter P (and the whole lot is vertically aligned to the middle as already mentioned).

Also note that there is no need to give table cells a height of 100% as all table-cells will automatically be the same height.

If you can do a quick mock up of what you want it to look like I will look back in the morning and give a demo. Bear in mind that the cells will adapt to whatever text is inside so you cannot work to a fixed height unless you want things to break. The content needs to be responsive and work at any size.

Back tomorrow now :slight_smile:

1 Like

Hi, I found a solution for the letters inside the blue diag: I create a span inside the div with position:absolute and the div with relative and so I can put the letters precisely and not flow inline with the td text.
The letters inside the blue diag are a fast visual reminder if all that row is whitin certain parameters or not.
What I want is something like this:

and I got it with this:
https://jsfiddle.net/5zk8phq6/3/

BUT if for example one td of the row (without the blue div) has too much text and the height is higher than this, you get the misalignment of the div like

like here:
https://jsfiddle.net/5zk8phq6/4/

So the div placement is also dependant of the height of the tr row… and also of the resizing of the table with the window browser…
So I tried with your previous suggestion, making the div itself absolute… and it seems to work well.
https://jsfiddle.net/5zk8phq6/7/

Now, I can’t put the td text over the div with z-index higher than div… so I ended up with some transparency of the blue diag, not perfect but acceptable.
Scaling the window browser sometimes make the div out of the td, but again it’s acceptable.
If you can improve this, TIA.

I missed your

  vertical-align:top;

!!
Now I got it working with the div not absolute:

https://jsfiddle.net/vgdbn3jw/2/

I think it’s correct now.
Thank you Paul.

2 Likes

That’s starting to look better. Well done :slight_smile:

A couple of minor points though. If the screen is larger you get this effect.

Screen Shot 2020-10-21 at 14.13.41

That’s the problem I mentioned with using angles and I still think you need the method I posted originally.

It looks as though you just want the blue as an overlay so I don’t see that you need all those extra divs as you can apply it the :before element of the cell itself.

I realise you probably have something else in mind with your js hooks etc but in the simplest form your design could come down to this.

It holds up much better at smaller or larger sizes and is simpler and less code :slight_smile:

It may help as a template for you to check things out etc. Hope its of some use anyway :wink:

2 Likes

You’re definitely right!
It’s better your way, I adapted the code to sides!
Thank you again.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.