skip to Main Content

I want VS Code to only provide suggestions for custom properties I can actually use. So when I type var() I want VS Code to give me a list of properties which will actually make a change…

In CSS you can define globally scoped custom properties with :root, like this :

:root {
  --custom-property-1: #000;
  --custom-property-2: #fff;
}

However, I think you can also define class scoped properties that only work on a specific class, here is the example I’m giving :

<body>
    <div>
        Hello world
    </div>
    <button class="custom-class">
        <p>Hello world</p>
    </button>
    <button>
        Hello world
    </button>
</body>
.custom-class {
    --background-color: red;
}

.custom-class p {
    background-color: var(--background-color);
}

button {
    background-color: var(--background-color);
}

div {
    background-color: var(--background-color);
}

So in this example I just made a div and two buttons where one button has a paragraph child. My theory is that if I define the custom property --background-color: red; in the scope of the .custom-class ruleset I will only be able to access that property in elements that have that class and not globally.

To prove my theory I gave the custom property to all of my elements. What I expect to happen is that only the elements that are somehow connected to the custom-class will be painted red.

Here are the results:

Results of the "experiment"

So it seems like my theory works… Now that this is over I can start defining my real issue. It is an issue with VS Code and IntelliSense.

VS Code provides suggestions when I type var(), and that is fine for globally scoped custom properties, but it is unacceptable for those which are class scoped.

Here is the example:

Example of the issue

Even though this div element cannot possibly access the custom property and writing it like that makes no change, VS Code is still giving me a suggestion for it… I cannot have that happening because I think I will have lots and lots and lots of these class scoped custom properties and I only want VS Code to suggest the custom properties which the element can actually access.

Is there a way to make this happen?

2

Answers


  1. TL;DR As far as I am aware, and at the time of this writing, VS Code doesn’t support anything significantly more sophisticated than what you have observed, and to do so would be a very difficult task (unless solutions that only address some set of the simpler problems are settled for).

    If the assumption is that a suggestion for referencing a custom property be given if and only if that property will always be accessible at either some number or all of the elements where the selector for the rule referencing the custom property applies, (which is my understanding of what this question is about) then this is significantly more complicated than you are estimating it to be. Some of what I’ve already written in my answer to How can I get color decorations for CSS variable references to work in VS Code? applies, though since this is not exactly the same question (that one is particularly concerned about property values (where the cascade is a big source of complexity), whereas this is concerned more with just whether a property is accessible or not (where the cascade is not really a source of complexity (unless I’m missing some other source of complexity, which I very well could be))), I’ll give it an answer.

    You gave the example of defining a custom property on a class selector, and being surprised that you get suggestions for using it in a selector that doesn’t include that class. That’s not that surprising. For VS Code to be able to prove in all/any cases whether a custom property defined in one selector A is "accessible" from another selector B, it must be able to prove that either

    • everything/something that B selects is necessarily a descendant of A everything A selects (which can be done- for example, the example you gave with .custom-class and .custom-class p),
    • or that in for all/any states of the DOM where both rules with those selectors take effect in the cascade, everything/something that B selects is a descendent of everything/something that A selects (take your pick of the words "everything"/"all" vs. "something"/"any" based on what behaviour you expect). This is really non-trivial:
      • The DOM can change dynamically. Elements can be added, moved, removed, class attributes can be changed (and many other things that a selector such as A or B might reference, such as attributes), custom properties can be added or removed on any element via style properties, etc. All of this being controllable dynamically via JavaScript (imagine IntelliSense having to parse JavaScript to see what it will do at runtime!)
      • VS Code can see your HTML files, but you can have multiple HTML files, each with different structures (arrangements of things selectable by B that are descendants of A), each linking or not linking to your stylesheet where those rules are defined
        • stylesheets can import other stylesheets. Okay, so now if you want to know staticly whether a stylesheet applies to a HTML page, you need to walk stylesheet import references
      • Maybe you don’t even write your pages in HTML- maybe they’re constructed by a server, such as using PHP, Ruby, ExpressJS, Razorpages, some other templating engine, the list goes on forever and keeps expanding as time passes.
      • Maybe your HTML documents or the template files or markup source files that they are derived from are even not even stored in the same codebase (Ex. some sort of CMS involvement). Okay. Now what? What’s VS Code going to do?
      • Even of the files that compose your web page/application that VS Code can see in the workspace folder, how can it be sure of what references in one file are to another file? Directory/path mapping in servers is a thing. The degree to which the path of a file in a codebase correlates to the path by which it is referenced at runtime can vary.

    And so on. I’d wager that even tackling (just) all the complexities mentioned above is intractable or close to intractable. Of course, you can create imperfect solutions and write extensions for VS Code that only support the kind of IntelliSense you want for some subset of those complexities, but writing such extensions I think is getting outside the scope of what this question is asking here- especially given how vast those types of complexities are.


    On the other hand, a tool that works at runtime such as a browser’s developer tools has access to state at runtime, and isn’t subject to many of the sources of complexity above (it still is to some, and to varying degrees for others, such as DOM state changing dynamically, but not to all).

    Login or Signup to reply.
  2. It is not easy to create a solution to this problem because there are simply too many unknowns due to the freedom that CSS offers the developer.

    Here is an example code to demonstrate just one of many unsolvable things:

    <div class="custom">
      <button>Test</button>
    </div>
    
    <button>Test</button>
    
    .custom {
      --background-color: red;
    }
    
    /* The IDE can't know which button you mean.
    The selector is global and can affect both
    the correct and incorrect button */
    button {
      background: var(--background-color)
    }
    

    It would be possible to remove the suggestions completely as long as the element is not clearly assigned to the class in which the variable was defined, but for that someone would have to think apart and write a plugin for vscode.

    In the future, the problem could certainly solve itself with AI integration like Copilot.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search