Dynamically change :after pseudo background-color

445 Views Asked by At

I am creating buttons within a repeater like this (simplyfied):

    <asp:Repeater runat="server" OnItemDataBound="Repeater_Buttons_ItemDataBound">
        <ItemTemplate>
            <telerik:RadButton runat="server" CssClass="myButton" ID="MyButton">
                <ContentTemplate>
                   <...>
                </ContentTemplate>
            </telerik:RadButton>
        </ItemTemplate>
    </asp:Repeater>

those buttons are styled with :after pseudo to create a colored background swiping in the background of this buttons

.myButton {
    ...
}

   .myButton::after {
        content: "";
        display: block;
        width: 45px;
        height: 45px;
        background-color: var(--myColor);
        position: absolute;
        left: 0;
        top: 0;
        transition: 400ms all;
        z-index: 1;
    }

the result looks like this:

enter image description here

my problem is, I need to change the color of this :after content dynamically based on the item bounded.

I can access the RadButton on ItemDataBound where I tried to change it via the Attributes without success.

protected void Repeater_Buttons_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
        var currentItem = (e.Item.DataItem as MyItem);

        var radButton = (e.Item.FindControl("MyButton") as RadButton);

        // whishful function I need:
        radButton.After.BackgroundColor = currentItem.BackColor;

        // or something like 
        radButton.Attributes.Add("style:after", $"background-color: {currentItem.BackColor}");

    }
}

Also approaches via javascript where unsuccessful. I cannot create diffrente css classes hardcode since any color can be choosen for the different items

4

There are 4 best solutions below

0
PIoneer_2 On BEST ANSWER

IMHO, you don't have to override existing CSS. Your CSS already has

.myButton::after {
    ...
    background-color: var(--myColor);
    ...
}

So you need just to change this --myColor CSS variable. Even without a server call. All on a client.

For a fast example, plain JS can do it. Such JS action could be built-in into a click handler.

const root = document.documentElement; //get the root element
...
root.style.setProperty('--myColor', someColorForThisMoment);

Or such code could be a part of an EventListener (randomly change --myColor on each click):

function random(min,max) {
  const num = Math.floor(Math.random()*(max-min)) + min;
  return num;
}

function getRandomColor() {
  return 'rgb(' + random(0,255) + ', ' + random(0,255) + ', ' + random(0,255) +  ')';
}

const root = document.documentElement;
root.addEventListener('click', e => {
  const newRandomColor = getRandomColor();
  root.style.setProperty('--myColor', newRandomColor);
});

UI styling is a client job. Don't overload your server with redundant calls.

0
VDWWD On

Maybe you can just add an extra/different class to the Button instead of trying to add inline styles? See the example below (without the telerik controls)

<asp:Repeater ID="Repeater_Buttons" runat="server" OnItemDataBound="Repeater_Buttons_ItemDataBound">
    <ItemTemplate>

        <div>
            <asp:LinkButton ID="MyButton" runat="server" CssClass="myButton">LinkButton</asp:LinkButton>
        </div>

    </ItemTemplate>
</asp:Repeater>


<style>
    .myButton,
    .myButtonDynamic {
        background-color: red;
    }

        .myButton::after {
            content: "after";
            background-color: yellow;
        }

        .myButtonDynamic::after {
            content: "after";
            background-color: green;
        }
</style>

And then in the ItemDataBound

protected void Repeater_Buttons_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.AlternatingItem)
    {
        var radButton = (LinkButton)e.Item.FindControl("MyButton");

        radButton.CssClass = "myButtonDynamic";
    }
}
0
Richard Deeming On

Assuming the currentItem.BackColor is already formatted as a CSS colour string, this should work:

var radButton = (e.Item.FindControl("MyButton") as RadButton);
radButton.Style["--myColor"] = currentItem.BackColor;

If it's a System.Drawing.Color, then the ColorTranslator.ToHtml method should give you the required string.

0
Simon On

You could just write to the custom property

protected void Repeater_Buttons_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
        var currentItem = (e.Item.DataItem as MyItem);

        var radButton = (e.Item.FindControl("MyButton") as RadButton);

        radButton.Attributes.Add("style", $"--myColor: {currentItem.BackColor}");

    }
}