CSS Custom properties follow the standard cascade rules. Following example will help you understand it clearly:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
:root {
--text-color: #06c;
}
h1 {
--text-color: red;
}
div {
--text-color: magenta;
}
#d1{
--text-color: green;
}
* {
color: var(--text-color)
}
</style>
</head>
<body>
<h1>CSS VARIABLES</h1>
<div>Lorem ipsum dolor sit amet consectetur adipisicing elit. Deleniti sapiente aliquid nobis?
In asperiores laborum autem, et facilis enim numquam non assumenda nobis eligendi.
Ullam debitis laboriosam maiores ex voluptate?</div>
<div id="d1">
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Incidunt alias error cupiditate
voluptatibus!
Quaerat, ratione placeat.
Enim voluptas laborum adipisci animi, fuga omnis in unde iure sint incidunt voluptatum itaque?
</p>
</div>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>Javascript</li>
</ul>
</body>
</html>

In the example above:
- Color of the heading h1 is red as variable – – text-color value is red under h1 element selector.
- Color of the first div is magenta as defined under div element selector
- Color of the p element under second div is green. As id selector #d1 defines – – text-color as green. Id selector has higher specificity than the element selector div. Element p inherits the property from its parent div i.e. #d1 , its color is also green.
- Color of the list is blue. There is no color specified for the list separately. By default it takes the color defined under :root pseudo class.
- Under * universal selector we have mentioned the var() function. Universal selector matches all the elements with the – – text-color variable set for them. var() function retrieves the value of the colors defined by – – text-color variable for all the elements. We do not have to write var() function separately for each element, we just put it under * universal selector.