Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Achieving Style Overriding for Custom UI Component in Unity

Discussion in 'UI Toolkit' started by herkip, Oct 3, 2023.

  1. herkip

    herkip

    Joined:
    Dec 21, 2013
    Posts:
    30
    Hello,

    I am creating a custom UI component in Unity, which is intended to be used across different projects. A crucial requirement for this component is to provide the ability to override its styles in each project it's used in. However, I'm facing a challenge where the styles from the project-specific style sheets are not overriding the styles defined in the custom component as desired.

    Here are the desired rules for style application I am aiming to achieve:
    1. User-Defined Precedence: Styles from project-specific style sheets should always have the ability to override the styles defined in the custom component.
    2. Selector Specificity: If both selectors are in the same type of style sheet, the selector with the highest specificity should take precedence.
    3. Hierarchy Position: If both selectors have the same specificity, the selector whose style sheet is applied lowest in the element hierarchy should take precedence.

    Currently, the third rule is being applied, but I need to ensure that the first rule governs the style application for this component.

    I am seeking guidance on how to ensure that the project-specific styles can override the styles defined in the custom component. Has anyone faced a similar issue or have any insights on how to accomplish this? Your suggestions would be greatly appreciated!

    Thank you in advance for your time and assistance.

    Best regards,
    Herki
     
    oscarAbraham likes this.
  2. martinpa_unity

    martinpa_unity

    Unity Technologies

    Joined:
    Oct 18, 2017
    Posts:
    359
    Hi @herkip,

    How are you adding the style sheets to your custom UI components? Provided that the style sheets are in the correct order (which you can see in the UI Debugger), it should already work.

    Matching selectors will be sorted by their specificity using a stable sort (selectors defined last will be applied last). So if the per-project stylesheet is added last for a given UI element, it will be applied last.

    There is another layer that can be used as well, which is the per-element inline styles. This is available in both the uxml (i.e.
    <engine:VisualElement style="width: 50px;"/>
    ) and directly in code (
    ve.style.width = 50;
    ). These will be applied no matter what value is resolved from the matching selectors.

    The best way to debug this is to open the UI Debugger, select a given element and take a look at both the Stylesheets and Matching Selectors sections.

    Hope this helps!
     
  3. martinpa_unity

    martinpa_unity

    Unity Technologies

    Joined:
    Oct 18, 2017
    Posts:
    359
    Forgot the obligatory question: which version of Unity as you using?
     
  4. herkip

    herkip

    Joined:
    Dec 21, 2013
    Posts:
    30
    Hello and thank you for the response!

    Unity version 2022.3.10f1

    In the `BaseWindow` constructor in my code, I am loading a style sheet named "BaseWindow" and adding it to the `styleSheets` collection of the custom component. This style sheet provides a base style for the custom component. Here’s the relevant code snippet:
    Code (CSharp):
    1.  
    2. var styleSheet = Resources.Load<StyleSheet>("BaseWindow");
    3. styleSheets.Add(styleSheet);
    4.  
    This custom UI component is intended to be shared across multiple projects. In each project, I would like to have the ability to override the styles defined in the "BaseWindow" style sheet with project-specific styles. The goal is to ensure that the project-specific styles always take precedence over the base styles, allowing for customization in the appearance of the custom component per project.

    Based on your suggestion, it seems like ensuring the project-specific style sheet is added last could help achieve the style overriding behavior I am looking for. However, I am not entirely sure how to ensure the project-specific style sheet is always added last, given that this custom component will be used in various projects with potentially different configurations.

    The inline styles suggestion is insightful, and I can see how defining crucial styles inline could ensure they take precedence. However, I am looking for a more scalable and maintainable solution that would allow project-specific style overriding without having to define styles inline.

    Would there be a recommended approach to ensure that the project-specific style sheets always override the base styles of the custom component, irrespective of the order or specificity, especially in a scenario where this component is shared across multiple projects?

    Thank you again for your assistance, and I look forward to any further insights you or anyone else may have on this matter!
     
  5. martinpa_unity

    martinpa_unity

    Unity Technologies

    Joined:
    Oct 18, 2017
    Posts:
    359
    If I understand this correctly, you are adding the stylesheet to all your custom elements. This will make it harder for other people to override the styling because they would need to add their stylesheets on each of your custom elements (and make sure it's added after the one you're adding).

    To make it easier to override, you could add the stylesheet on the root visual element of your window. That way, additional stylesheets further down the hierarchy would automatically be treated after your own.

    What I typically do in my own projects is to create a stylesheet that contains the base styling for my components. In the places where I don't want to use overrides, I simply use it as is. In the places where I want to use overrides, I define another stylesheet, import the base one in it and then add my overrides. So in the end, I'm always dealing with a single stylesheet that I have to add and the stylesheet itself will hold the necessary references.

    For a reusable library, this workflow might ask more effort from the users, but it would work. And if the users are not using the `BaseWindow`, they would still be able to use the correct styling.

    Hope this helps!
     
  6. martinpa_unity

    martinpa_unity

    Unity Technologies

    Joined:
    Oct 18, 2017
    Posts:
    359
    For runtime use-cases, this is usually achieve through a Theme stylesheet, which is pretty much a normal stylesheet that has some flags on it to make additional stylesheets have precedence.

    For this use-case, I use the same workflow that I describe in the previous post (a theme stylesheet that imports other stylesheets before adding my own overrides).